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 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
38 #include "dispextern.h"
39 #include "blockinput.h"
48 #include <sys/types.h>
51 #define COLOR_TABLE_SUPPORT 1
53 typedef struct x_bitmap_record Bitmap_Record
;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
57 #define RGB_PIXEL_COLOR unsigned long
59 #define PIX_MASK_RETAIN 0
60 #define PIX_MASK_DRAW 1
61 #endif /* HAVE_X_WINDOWS */
67 /* W32_TODO : Color tables on W32. */
68 #undef COLOR_TABLE_SUPPORT
70 typedef struct w32_bitmap_record Bitmap_Record
;
71 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
82 #endif /* HAVE_NTGUI */
90 #include <sys/param.h>
92 #if TARGET_API_MAC_CARBON
94 #include <QuickTime/QuickTime.h>
95 #else /* not MAC_OSX */
96 #include <QuickTime.h>
97 #endif /* not MAC_OSX */
98 #else /* not TARGET_API_MAC_CARBON */
101 #include <TextUtils.h>
102 #include <ImageCompression.h>
103 #include <QuickTimeComponents.h>
104 #endif /* not TARGET_API_MAC_CARBON */
106 /* MAC_TODO : Color tables on Mac. */
107 #undef COLOR_TABLE_SUPPORT
109 #define ZPixmap 0 /* arbitrary */
110 typedef struct mac_bitmap_record Bitmap_Record
;
112 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
115 #define RGB_PIXEL_COLOR unsigned long
117 /* A black pixel in a mask bitmap/pixmap means ``draw a source
118 pixel''. A white pixel means ``retain the current pixel''. */
119 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
120 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
122 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
123 #define x_defined_color mac_defined_color
124 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
125 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
126 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
131 /* Search path for bitmap files. */
133 Lisp_Object Vx_bitmap_file_path
;
136 static void x_disable_image
P_ ((struct frame
*, struct image
*));
137 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
140 static void init_color_table
P_ ((void));
141 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
142 #ifdef COLOR_TABLE_SUPPORT
143 static void free_color_table
P_ ((void));
144 static unsigned long *colors_in_color_table
P_ ((int *n
));
145 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
148 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
149 id, which is just an int that this section returns. Bitmaps are
150 reference counted so they can be shared among frames.
152 Bitmap indices are guaranteed to be > 0, so a negative number can
153 be used to indicate no bitmap.
155 If you use x_create_bitmap_from_data, then you must keep track of
156 the bitmaps yourself. That is, creating a bitmap from the same
157 data more than once will not be caught. */
162 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
163 Display
*display
; /* not used */
165 int x
, y
; /* not used */
166 unsigned int width
, height
; /* not used */
167 unsigned long plane_mask
; /* not used */
168 int format
; /* not used */
171 xassert (x
== 0 && y
== 0);
174 SetRect (&ri
, 0, 0, width
, height
);
175 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
177 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
180 LockPixels (GetGWorldPixMap (pixmap
));
186 XPutPixel (ximage
, x
, y
, pixel
)
191 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
192 short depth
= GetPixDepth (pixmap
);
194 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
197 char *base_addr
= GetPixBaseAddr (pixmap
);
198 short row_bytes
= GetPixRowBytes (pixmap
);
200 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
206 char *base_addr
= GetPixBaseAddr (pixmap
);
207 short row_bytes
= GetPixRowBytes (pixmap
);
209 if (pixel
== PIX_MASK_DRAW
)
210 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
212 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
220 GetGWorld (&old_port
, &old_gdh
);
221 SetGWorld (ximage
, NULL
);
223 color
.red
= RED16_FROM_ULONG (pixel
);
224 color
.green
= GREEN16_FROM_ULONG (pixel
);
225 color
.blue
= BLUE16_FROM_ULONG (pixel
);
227 SetCPixel (x
, y
, &color
);
229 SetGWorld (old_port
, old_gdh
);
234 XGetPixel (ximage
, x
, y
)
238 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
239 short depth
= GetPixDepth (pixmap
);
241 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
244 char *base_addr
= GetPixBaseAddr (pixmap
);
245 short row_bytes
= GetPixRowBytes (pixmap
);
247 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
253 char *base_addr
= GetPixBaseAddr (pixmap
);
254 short row_bytes
= GetPixRowBytes (pixmap
);
256 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
257 return PIX_MASK_DRAW
;
259 return PIX_MASK_RETAIN
;
267 GetGWorld (&old_port
, &old_gdh
);
268 SetGWorld (ximage
, NULL
);
270 GetCPixel (x
, y
, &color
);
272 SetGWorld (old_port
, old_gdh
);
273 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
281 UnlockPixels (GetGWorldPixMap (ximg
));
286 mac_create_cg_image_from_image (f
, img
)
291 CGImageRef result
= NULL
;
298 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
299 img
->width
, img
->height
, 1);
306 GetGWorld (&old_port
, &old_gdh
);
307 SetGWorld (mask
, NULL
);
308 BackColor (blackColor
); /* Don't mask. */
309 SetRect (&r
, 0, 0, img
->width
, img
->height
);
311 SetGWorld (old_port
, old_gdh
);
316 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
317 GetGWorldPixMap (mask
), &result
);
318 if (mask
!= img
->mask
)
319 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
325 #endif /* USE_CG_DRAWING */
329 /* Functions to access the contents of a bitmap, given an id. */
332 x_bitmap_height (f
, id
)
336 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
340 x_bitmap_width (f
, id
)
344 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
347 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
349 x_bitmap_pixmap (f
, id
)
353 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
357 #ifdef HAVE_X_WINDOWS
359 x_bitmap_mask (f
, id
)
363 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
367 /* Allocate a new bitmap record. Returns index of new record. */
370 x_allocate_bitmap_record (f
)
373 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
376 if (dpyinfo
->bitmaps
== NULL
)
378 dpyinfo
->bitmaps_size
= 10;
380 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
381 dpyinfo
->bitmaps_last
= 1;
385 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
386 return ++dpyinfo
->bitmaps_last
;
388 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
389 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
392 dpyinfo
->bitmaps_size
*= 2;
394 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
395 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
396 return ++dpyinfo
->bitmaps_last
;
399 /* Add one reference to the reference count of the bitmap with id ID. */
402 x_reference_bitmap (f
, id
)
406 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
409 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
412 x_create_bitmap_from_data (f
, bits
, width
, height
)
415 unsigned int width
, height
;
417 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
420 #ifdef HAVE_X_WINDOWS
422 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
423 bits
, width
, height
);
426 #endif /* HAVE_X_WINDOWS */
430 bitmap
= CreateBitmap (width
, height
,
431 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
432 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
436 #endif /* HAVE_NTGUI */
439 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
444 id
= x_allocate_bitmap_record (f
);
446 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
447 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
450 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
451 dpyinfo
->bitmaps
[id
- 1].height
= height
;
452 dpyinfo
->bitmaps
[id
- 1].width
= width
;
453 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
455 #ifdef HAVE_X_WINDOWS
456 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
457 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
458 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
459 #endif /* HAVE_X_WINDOWS */
462 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
463 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
464 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
465 #endif /* HAVE_NTGUI */
470 /* Create bitmap from file FILE for frame F. */
473 x_create_bitmap_from_file (f
, file
)
478 return -1; /* MAC_TODO : bitmap support */
482 return -1; /* W32_TODO : bitmap support */
483 #endif /* HAVE_NTGUI */
485 #ifdef HAVE_X_WINDOWS
486 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
487 unsigned int width
, height
;
489 int xhot
, yhot
, result
, id
;
494 /* Look for an existing bitmap with the same name. */
495 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
497 if (dpyinfo
->bitmaps
[id
].refcount
498 && dpyinfo
->bitmaps
[id
].file
499 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
501 ++dpyinfo
->bitmaps
[id
].refcount
;
506 /* Search bitmap-file-path for the file, if appropriate. */
507 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
512 filename
= (char *) SDATA (found
);
514 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
515 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
516 if (result
!= BitmapSuccess
)
519 id
= x_allocate_bitmap_record (f
);
520 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
521 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
522 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
523 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
524 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
525 dpyinfo
->bitmaps
[id
- 1].height
= height
;
526 dpyinfo
->bitmaps
[id
- 1].width
= width
;
527 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
530 #endif /* HAVE_X_WINDOWS */
536 Free_Bitmap_Record (dpyinfo
, bm
)
537 Display_Info
*dpyinfo
;
540 #ifdef HAVE_X_WINDOWS
541 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
543 XFreePixmap (dpyinfo
->display
, bm
->mask
);
544 #endif /* HAVE_X_WINDOWS */
547 DeleteObject (bm
->pixmap
);
548 #endif /* HAVE_NTGUI */
551 xfree (bm
->bitmap_data
); /* Added ++kfs */
552 bm
->bitmap_data
= NULL
;
562 /* Remove reference to bitmap with id number ID. */
565 x_destroy_bitmap (f
, id
)
569 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
573 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
575 if (--bm
->refcount
== 0)
578 Free_Bitmap_Record (dpyinfo
, bm
);
584 /* Free all the bitmaps for the display specified by DPYINFO. */
587 x_destroy_all_bitmaps (dpyinfo
)
588 Display_Info
*dpyinfo
;
591 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
593 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
594 if (bm
->refcount
> 0)
595 Free_Bitmap_Record (dpyinfo
, bm
);
597 dpyinfo
->bitmaps_last
= 0;
601 #ifdef HAVE_X_WINDOWS
603 /* Useful functions defined in the section
604 `Image type independent image structures' below. */
606 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
609 unsigned long height
));
611 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
612 int depth
, XImagePtr
*ximg
,
615 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
618 /* Create a mask of a bitmap. Note is this not a perfect mask.
619 It's nicer with some borders in this context */
622 x_create_bitmap_mask (f
, id
)
627 XImagePtr ximg
, mask_img
;
628 unsigned long width
, height
;
631 unsigned long x
, y
, xp
, xm
, yp
, ym
;
634 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
639 pixmap
= x_bitmap_pixmap (f
, id
);
640 width
= x_bitmap_width (f
, id
);
641 height
= x_bitmap_height (f
, id
);
644 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
653 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
658 XDestroyImage (ximg
);
662 bg
= four_corners_best (ximg
, NULL
, width
, height
);
664 for (y
= 0; y
< ximg
->height
; ++y
)
666 for (x
= 0; x
< ximg
->width
; ++x
)
668 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
669 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
670 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
671 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
672 if (XGetPixel (ximg
, x
, y
) == bg
673 && XGetPixel (ximg
, x
, yp
) == bg
674 && XGetPixel (ximg
, x
, ym
) == bg
675 && XGetPixel (ximg
, xp
, y
) == bg
676 && XGetPixel (ximg
, xp
, yp
) == bg
677 && XGetPixel (ximg
, xp
, ym
) == bg
678 && XGetPixel (ximg
, xm
, y
) == bg
679 && XGetPixel (ximg
, xm
, yp
) == bg
680 && XGetPixel (ximg
, xm
, ym
) == bg
)
681 XPutPixel (mask_img
, x
, y
, 0);
683 XPutPixel (mask_img
, x
, y
, 1);
687 xassert (interrupt_input_blocked
);
688 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
689 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
691 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
693 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
694 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
696 XDestroyImage (ximg
);
697 x_destroy_x_image (mask_img
);
702 #endif /* HAVE_X_WINDOWS */
705 /***********************************************************************
707 ***********************************************************************/
709 /* Value is the number of elements of vector VECTOR. */
711 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
713 /* List of supported image types. Use define_image_type to add new
714 types. Use lookup_image_type to find a type for a given symbol. */
716 static struct image_type
*image_types
;
718 /* A list of symbols, one for each supported image type. */
720 Lisp_Object Vimage_types
;
722 /* An alist of image types and libraries that implement the type. */
724 Lisp_Object Vimage_library_alist
;
726 /* Cache for delayed-loading image types. */
728 static Lisp_Object Vimage_type_cache
;
730 /* The symbol `xbm' which is used as the type symbol for XBM images. */
736 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
737 extern Lisp_Object QCdata
, QCtype
, Qcount
;
738 extern Lisp_Object Qcenter
;
739 Lisp_Object QCascent
, QCmargin
, QCrelief
;
740 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
741 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
745 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
747 /* Time in seconds after which images should be removed from the cache
750 Lisp_Object Vimage_cache_eviction_delay
;
752 /* Function prototypes. */
754 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
755 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
756 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
757 static void x_laplace
P_ ((struct frame
*, struct image
*));
758 static void x_emboss
P_ ((struct frame
*, struct image
*));
759 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
762 #define CACHE_IMAGE_TYPE(type, status) \
763 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
765 #define ADD_IMAGE_TYPE(type) \
766 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
768 /* Define a new image type from TYPE. This adds a copy of TYPE to
769 image_types and caches the loading status of TYPE. */
772 define_image_type (type
, loaded
)
773 struct image_type
*type
;
782 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
783 The initialized data segment is read-only. */
784 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
785 bcopy (type
, p
, sizeof *p
);
786 p
->next
= image_types
;
791 CACHE_IMAGE_TYPE (*type
->type
, success
);
796 /* Look up image type SYMBOL, and return a pointer to its image_type
797 structure. Value is null if SYMBOL is not a known image type. */
799 static INLINE
struct image_type
*
800 lookup_image_type (symbol
)
803 struct image_type
*type
;
805 /* We must initialize the image-type if it hasn't been already. */
806 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
807 return 0; /* unimplemented */
809 for (type
= image_types
; type
; type
= type
->next
)
810 if (EQ (symbol
, *type
->type
))
817 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
818 valid image specification is a list whose car is the symbol
819 `image', and whose rest is a property list. The property list must
820 contain a value for key `:type'. That value must be the name of a
821 supported image type. The rest of the property list depends on the
825 valid_image_p (object
)
834 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
835 if (EQ (XCAR (tem
), QCtype
))
838 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
840 struct image_type
*type
;
841 type
= lookup_image_type (XCAR (tem
));
843 valid_p
= type
->valid_p (object
);
854 /* Log error message with format string FORMAT and argument ARG.
855 Signaling an error, e.g. when an image cannot be loaded, is not a
856 good idea because this would interrupt redisplay, and the error
857 message display would lead to another redisplay. This function
858 therefore simply displays a message. */
861 image_error (format
, arg1
, arg2
)
863 Lisp_Object arg1
, arg2
;
865 add_to_log (format
, arg1
, arg2
);
870 /***********************************************************************
872 ***********************************************************************/
874 enum image_value_type
876 IMAGE_DONT_CHECK_VALUE_TYPE
,
878 IMAGE_STRING_OR_NIL_VALUE
,
880 IMAGE_POSITIVE_INTEGER_VALUE
,
881 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
882 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
885 IMAGE_FUNCTION_VALUE
,
890 /* Structure used when parsing image specifications. */
894 /* Name of keyword. */
897 /* The type of value allowed. */
898 enum image_value_type type
;
900 /* Non-zero means key must be present. */
903 /* Used to recognize duplicate keywords in a property list. */
906 /* The value that was found. */
911 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
913 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
916 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
917 has the format (image KEYWORD VALUE ...). One of the keyword/
918 value pairs must be `:type TYPE'. KEYWORDS is a vector of
919 image_keywords structures of size NKEYWORDS describing other
920 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
923 parse_image_spec (spec
, keywords
, nkeywords
, type
)
925 struct image_keyword
*keywords
;
936 while (CONSP (plist
))
938 Lisp_Object key
, value
;
940 /* First element of a pair must be a symbol. */
942 plist
= XCDR (plist
);
946 /* There must follow a value. */
949 value
= XCAR (plist
);
950 plist
= XCDR (plist
);
952 /* Find key in KEYWORDS. Error if not found. */
953 for (i
= 0; i
< nkeywords
; ++i
)
954 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
960 /* Record that we recognized the keyword. If a keywords
961 was found more than once, it's an error. */
962 keywords
[i
].value
= value
;
965 if (keywords
[i
].count
> 1)
968 /* Check type of value against allowed type. */
969 switch (keywords
[i
].type
)
971 case IMAGE_STRING_VALUE
:
972 if (!STRINGP (value
))
976 case IMAGE_STRING_OR_NIL_VALUE
:
977 if (!STRINGP (value
) && !NILP (value
))
981 case IMAGE_SYMBOL_VALUE
:
982 if (!SYMBOLP (value
))
986 case IMAGE_POSITIVE_INTEGER_VALUE
:
987 if (!INTEGERP (value
) || XINT (value
) <= 0)
991 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
992 if (INTEGERP (value
) && XINT (value
) >= 0)
995 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
996 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1000 case IMAGE_ASCENT_VALUE
:
1001 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1003 else if (INTEGERP (value
)
1004 && XINT (value
) >= 0
1005 && XINT (value
) <= 100)
1009 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1010 if (!INTEGERP (value
) || XINT (value
) < 0)
1014 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1017 case IMAGE_FUNCTION_VALUE
:
1018 value
= indirect_function (value
);
1020 || COMPILEDP (value
)
1021 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1025 case IMAGE_NUMBER_VALUE
:
1026 if (!INTEGERP (value
) && !FLOATP (value
))
1030 case IMAGE_INTEGER_VALUE
:
1031 if (!INTEGERP (value
))
1035 case IMAGE_BOOL_VALUE
:
1036 if (!NILP (value
) && !EQ (value
, Qt
))
1045 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1049 /* Check that all mandatory fields are present. */
1050 for (i
= 0; i
< nkeywords
; ++i
)
1051 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1054 return NILP (plist
);
1058 /* Return the value of KEY in image specification SPEC. Value is nil
1059 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1060 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1063 image_spec_value (spec
, key
, found
)
1064 Lisp_Object spec
, key
;
1069 xassert (valid_image_p (spec
));
1071 for (tail
= XCDR (spec
);
1072 CONSP (tail
) && CONSP (XCDR (tail
));
1073 tail
= XCDR (XCDR (tail
)))
1075 if (EQ (XCAR (tail
), key
))
1079 return XCAR (XCDR (tail
));
1089 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1090 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1091 PIXELS non-nil means return the size in pixels, otherwise return the
1092 size in canonical character units.
1093 FRAME is the frame on which the image will be displayed. FRAME nil
1094 or omitted means use the selected frame. */)
1095 (spec
, pixels
, frame
)
1096 Lisp_Object spec
, pixels
, frame
;
1101 if (valid_image_p (spec
))
1103 struct frame
*f
= check_x_frame (frame
);
1104 int id
= lookup_image (f
, spec
);
1105 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1106 int width
= img
->width
+ 2 * img
->hmargin
;
1107 int height
= img
->height
+ 2 * img
->vmargin
;
1110 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1111 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1113 size
= Fcons (make_number (width
), make_number (height
));
1116 error ("Invalid image specification");
1122 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1123 doc
: /* Return t if image SPEC has a mask bitmap.
1124 FRAME is the frame on which the image will be displayed. FRAME nil
1125 or omitted means use the selected frame. */)
1127 Lisp_Object spec
, frame
;
1132 if (valid_image_p (spec
))
1134 struct frame
*f
= check_x_frame (frame
);
1135 int id
= lookup_image (f
, spec
);
1136 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1141 error ("Invalid image specification");
1146 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1147 doc
: /* Return extension data for image SPEC.
1148 FRAME is the frame on which the image will be displayed. FRAME nil
1149 or omitted means use the selected frame. */)
1151 Lisp_Object spec
, frame
;
1156 if (valid_image_p (spec
))
1158 struct frame
*f
= check_x_frame (frame
);
1159 int id
= lookup_image (f
, spec
);
1160 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1161 ext
= img
->data
.lisp_val
;
1168 /***********************************************************************
1169 Image type independent image structures
1170 ***********************************************************************/
1172 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1173 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1174 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1176 #define MAX_IMAGE_SIZE 6.0
1177 Lisp_Object Vmax_image_size
;
1179 /* Allocate and return a new image structure for image specification
1180 SPEC. SPEC has a hash value of HASH. */
1182 static struct image
*
1183 make_image (spec
, hash
)
1187 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1189 xassert (valid_image_p (spec
));
1190 bzero (img
, sizeof *img
);
1191 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1192 xassert (img
->type
!= NULL
);
1194 img
->data
.lisp_val
= Qnil
;
1195 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1197 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1202 /* Free image IMG which was used on frame F, including its resources. */
1211 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1213 /* Remove IMG from the hash table of its cache. */
1215 img
->prev
->next
= img
->next
;
1217 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1220 img
->next
->prev
= img
->prev
;
1222 c
->images
[img
->id
] = NULL
;
1224 /* Free resources, then free IMG. */
1225 img
->type
->free (f
, img
);
1230 /* Return 1 if the given widths and heights are valid for display;
1231 otherwise, return 0. */
1234 check_image_size (f
, width
, height
)
1241 if (width
<= 0 || height
<= 0)
1244 if (INTEGERP (Vmax_image_size
))
1245 w
= h
= XINT (Vmax_image_size
);
1246 else if (FLOATP (Vmax_image_size
))
1250 w
= FRAME_PIXEL_WIDTH (f
);
1251 h
= FRAME_PIXEL_HEIGHT (f
);
1254 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1255 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1256 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1261 return (width
<= w
&& height
<= h
);
1264 /* Prepare image IMG for display on frame F. Must be called before
1265 drawing an image. */
1268 prepare_image_for_display (f
, img
)
1274 /* We're about to display IMG, so set its timestamp to `now'. */
1276 img
->timestamp
= EMACS_SECS (t
);
1278 /* If IMG doesn't have a pixmap yet, load it now, using the image
1279 type dependent loader function. */
1280 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1281 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1283 #if defined (MAC_OS) && USE_CG_DRAWING
1284 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1286 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1287 if (img
->data
.ptr_val
== NULL
)
1289 img
->load_failed_p
= 1;
1290 img
->type
->free (f
, img
);
1297 /* Value is the number of pixels for the ascent of image IMG when
1298 drawn in face FACE. */
1301 image_ascent (img
, face
, slice
)
1304 struct glyph_slice
*slice
;
1309 if (slice
->height
== img
->height
)
1310 height
= img
->height
+ img
->vmargin
;
1311 else if (slice
->y
== 0)
1312 height
= slice
->height
+ img
->vmargin
;
1314 height
= slice
->height
;
1316 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1321 /* W32 specific version. Why?. ++kfs */
1322 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1323 - FONT_BASE(face
->font
)) / 2;
1325 /* This expression is arranged so that if the image can't be
1326 exactly centered, it will be moved slightly up. This is
1327 because a typical font is `top-heavy' (due to the presence
1328 uppercase letters), so the image placement should err towards
1329 being top-heavy too. It also just generally looks better. */
1330 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1331 #endif /* HAVE_NTGUI */
1334 ascent
= height
/ 2;
1337 ascent
= (int) (height
* img
->ascent
/ 100.0);
1343 /* Image background colors. */
1345 /* Find the "best" corner color of a bitmap.
1346 On W32, XIMG is assumed to a device context with the bitmap selected. */
1348 static RGB_PIXEL_COLOR
1349 four_corners_best (ximg
, corners
, width
, height
)
1350 XImagePtr_or_DC ximg
;
1352 unsigned long width
, height
;
1354 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1357 if (corners
&& corners
[BOT_CORNER
] >= 0)
1359 /* Get the colors at the corner_pixels of ximg. */
1360 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1361 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1362 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1363 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1367 /* Get the colors at the corner_pixels of ximg. */
1368 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1369 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1370 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1371 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1373 /* Choose the most frequently found color as background. */
1374 for (i
= best_count
= 0; i
< 4; ++i
)
1378 for (j
= n
= 0; j
< 4; ++j
)
1379 if (corner_pixels
[i
] == corner_pixels
[j
])
1383 best
= corner_pixels
[i
], best_count
= n
;
1389 /* Portability macros */
1393 #define Destroy_Image(img_dc, prev) \
1394 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1396 #define Free_Pixmap(display, pixmap) \
1397 DeleteObject (pixmap)
1401 #define Destroy_Image(ximg, dummy) \
1402 XDestroyImage (ximg)
1404 #define Free_Pixmap(display, pixmap) \
1405 XFreePixmap (display, pixmap)
1407 #endif /* HAVE_NTGUI */
1410 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1411 it is guessed heuristically. If non-zero, XIMG is an existing
1412 XImage object (or device context with the image selected on W32) to
1413 use for the heuristic. */
1416 image_background (img
, f
, ximg
)
1419 XImagePtr_or_DC ximg
;
1421 if (! img
->background_valid
)
1422 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1424 int free_ximg
= !ximg
;
1427 #endif /* HAVE_NTGUI */
1432 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1433 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1435 HDC frame_dc
= get_frame_dc (f
);
1436 ximg
= CreateCompatibleDC (frame_dc
);
1437 release_frame_dc (f
, frame_dc
);
1438 prev
= SelectObject (ximg
, img
->pixmap
);
1439 #endif /* !HAVE_NTGUI */
1442 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1445 Destroy_Image (ximg
, prev
);
1447 img
->background_valid
= 1;
1450 return img
->background
;
1453 /* Return the `background_transparent' field of IMG. If IMG doesn't
1454 have one yet, it is guessed heuristically. If non-zero, MASK is an
1455 existing XImage object to use for the heuristic. */
1458 image_background_transparent (img
, f
, mask
)
1461 XImagePtr_or_DC mask
;
1463 if (! img
->background_transparent_valid
)
1464 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1468 int free_mask
= !mask
;
1471 #endif /* HAVE_NTGUI */
1476 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1477 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1479 HDC frame_dc
= get_frame_dc (f
);
1480 mask
= CreateCompatibleDC (frame_dc
);
1481 release_frame_dc (f
, frame_dc
);
1482 prev
= SelectObject (mask
, img
->mask
);
1483 #endif /* HAVE_NTGUI */
1486 img
->background_transparent
1487 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1490 Destroy_Image (mask
, prev
);
1493 img
->background_transparent
= 0;
1495 img
->background_transparent_valid
= 1;
1498 return img
->background_transparent
;
1502 /***********************************************************************
1503 Helper functions for X image types
1504 ***********************************************************************/
1506 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1508 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1509 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1511 Lisp_Object color_name
,
1512 unsigned long dflt
));
1515 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1516 free the pixmap if any. MASK_P non-zero means clear the mask
1517 pixmap if any. COLORS_P non-zero means free colors allocated for
1518 the image, if any. */
1521 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1524 int pixmap_p
, mask_p
, colors_p
;
1526 if (pixmap_p
&& img
->pixmap
)
1528 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1529 img
->pixmap
= NO_PIXMAP
;
1530 img
->background_valid
= 0;
1533 if (mask_p
&& img
->mask
)
1535 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1536 img
->mask
= NO_PIXMAP
;
1537 img
->background_transparent_valid
= 0;
1540 if (colors_p
&& img
->ncolors
)
1542 /* MAC_TODO: color table support. */
1543 /* W32_TODO: color table support. */
1544 #ifdef HAVE_X_WINDOWS
1545 x_free_colors (f
, img
->colors
, img
->ncolors
);
1546 #endif /* HAVE_X_WINDOWS */
1547 xfree (img
->colors
);
1552 #if defined (MAC_OS) && USE_CG_DRAWING
1553 if (img
->data
.ptr_val
)
1555 CGImageRelease (img
->data
.ptr_val
);
1556 img
->data
.ptr_val
= NULL
;
1561 /* Free X resources of image IMG which is used on frame F. */
1564 x_clear_image (f
, img
)
1569 x_clear_image_1 (f
, img
, 1, 1, 1);
1574 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1575 cannot be allocated, use DFLT. Add a newly allocated color to
1576 IMG->colors, so that it can be freed again. Value is the pixel
1579 static unsigned long
1580 x_alloc_image_color (f
, img
, color_name
, dflt
)
1583 Lisp_Object color_name
;
1587 unsigned long result
;
1589 xassert (STRINGP (color_name
));
1591 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1593 /* This isn't called frequently so we get away with simply
1594 reallocating the color vector to the needed size, here. */
1597 (unsigned long *) xrealloc (img
->colors
,
1598 img
->ncolors
* sizeof *img
->colors
);
1599 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1600 result
= color
.pixel
;
1610 /***********************************************************************
1612 ***********************************************************************/
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 /* Free image cache of frame F. Be aware that X frames share images
1640 free_image_cache (f
)
1643 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1648 /* Cache should not be referenced by any frame when freed. */
1649 xassert (c
->refcount
== 0);
1651 for (i
= 0; i
< c
->used
; ++i
)
1652 free_image (f
, c
->images
[i
]);
1656 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1661 /* Clear image cache of frame F. FORCE_P non-zero means free all
1662 images. FORCE_P zero means clear only images that haven't been
1663 displayed for some time. Should be called from time to time to
1664 reduce the number of loaded images. If image-eviction-seconds is
1665 non-nil, this frees images in the cache which weren't displayed for
1666 at least that many seconds. */
1669 clear_image_cache (f
, force_p
)
1673 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1675 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1682 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1684 /* Block input so that we won't be interrupted by a SIGIO
1685 while being in an inconsistent state. */
1688 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1690 struct image
*img
= c
->images
[i
];
1692 && (force_p
|| img
->timestamp
< old
))
1694 free_image (f
, img
);
1699 /* We may be clearing the image cache because, for example,
1700 Emacs was iconified for a longer period of time. In that
1701 case, current matrices may still contain references to
1702 images freed above. So, clear these matrices. */
1705 Lisp_Object tail
, frame
;
1707 FOR_EACH_FRAME (tail
, frame
)
1709 struct frame
*f
= XFRAME (frame
);
1710 if (FRAME_WINDOW_P (f
)
1711 && FRAME_X_IMAGE_CACHE (f
) == c
)
1712 clear_current_matrices (f
);
1715 ++windows_or_buffers_changed
;
1723 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1725 doc
: /* Clear the image cache of FRAME.
1726 FRAME nil or omitted means use the selected frame.
1727 FRAME t means clear the image caches of all frames. */)
1735 FOR_EACH_FRAME (tail
, frame
)
1736 if (FRAME_WINDOW_P (XFRAME (frame
)))
1737 clear_image_cache (XFRAME (frame
), 1);
1740 clear_image_cache (check_x_frame (frame
), 1);
1746 /* Compute masks and transform image IMG on frame F, as specified
1747 by the image's specification, */
1750 postprocess_image (f
, img
)
1754 /* Manipulation of the image's mask. */
1757 Lisp_Object conversion
, spec
;
1762 /* `:heuristic-mask t'
1764 means build a mask heuristically.
1765 `:heuristic-mask (R G B)'
1766 `:mask (heuristic (R G B))'
1767 means build a mask from color (R G B) in the
1770 means remove a mask, if any. */
1772 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1774 x_build_heuristic_mask (f
, img
, mask
);
1779 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1781 if (EQ (mask
, Qheuristic
))
1782 x_build_heuristic_mask (f
, img
, Qt
);
1783 else if (CONSP (mask
)
1784 && EQ (XCAR (mask
), Qheuristic
))
1786 if (CONSP (XCDR (mask
)))
1787 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1789 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1791 else if (NILP (mask
) && found_p
&& img
->mask
)
1793 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1794 img
->mask
= NO_PIXMAP
;
1799 /* Should we apply an image transformation algorithm? */
1800 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1801 if (EQ (conversion
, Qdisabled
))
1802 x_disable_image (f
, img
);
1803 else if (EQ (conversion
, Qlaplace
))
1805 else if (EQ (conversion
, Qemboss
))
1807 else if (CONSP (conversion
)
1808 && EQ (XCAR (conversion
), Qedge_detection
))
1811 tem
= XCDR (conversion
);
1813 x_edge_detection (f
, img
,
1814 Fplist_get (tem
, QCmatrix
),
1815 Fplist_get (tem
, QCcolor_adjustment
));
1821 /* Return the id of image with Lisp specification SPEC on frame F.
1822 SPEC must be a valid Lisp image specification (see valid_image_p). */
1825 lookup_image (f
, spec
)
1829 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1833 struct gcpro gcpro1
;
1836 /* F must be a window-system frame, and SPEC must be a valid image
1838 xassert (FRAME_WINDOW_P (f
));
1839 xassert (valid_image_p (spec
));
1843 /* Look up SPEC in the hash table of the image cache. */
1844 hash
= sxhash (spec
, 0);
1845 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1847 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1848 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1851 if (img
&& img
->load_failed_p
)
1853 free_image (f
, img
);
1857 /* If not found, create a new image and cache it. */
1860 extern Lisp_Object Qpostscript
;
1863 img
= make_image (spec
, hash
);
1864 cache_image (f
, img
);
1865 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1867 /* If we can't load the image, and we don't have a width and
1868 height, use some arbitrary width and height so that we can
1869 draw a rectangle for it. */
1870 if (img
->load_failed_p
)
1874 value
= image_spec_value (spec
, QCwidth
, NULL
);
1875 img
->width
= (INTEGERP (value
)
1876 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1877 value
= image_spec_value (spec
, QCheight
, NULL
);
1878 img
->height
= (INTEGERP (value
)
1879 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1883 /* Handle image type independent image attributes
1884 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1885 `:background COLOR'. */
1886 Lisp_Object ascent
, margin
, relief
, bg
;
1888 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1889 if (INTEGERP (ascent
))
1890 img
->ascent
= XFASTINT (ascent
);
1891 else if (EQ (ascent
, Qcenter
))
1892 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1894 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1895 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1896 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1897 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1898 && INTEGERP (XCDR (margin
)))
1900 if (XINT (XCAR (margin
)) > 0)
1901 img
->hmargin
= XFASTINT (XCAR (margin
));
1902 if (XINT (XCDR (margin
)) > 0)
1903 img
->vmargin
= XFASTINT (XCDR (margin
));
1906 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1907 if (INTEGERP (relief
))
1909 img
->relief
= XINT (relief
);
1910 img
->hmargin
+= abs (img
->relief
);
1911 img
->vmargin
+= abs (img
->relief
);
1914 if (! img
->background_valid
)
1916 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1920 = x_alloc_image_color (f
, img
, bg
,
1921 FRAME_BACKGROUND_PIXEL (f
));
1922 img
->background_valid
= 1;
1926 /* Do image transformations and compute masks, unless we
1927 don't have the image yet. */
1928 if (!EQ (*img
->type
->type
, Qpostscript
))
1929 postprocess_image (f
, img
);
1935 /* We're using IMG, so set its timestamp to `now'. */
1936 EMACS_GET_TIME (now
);
1937 img
->timestamp
= EMACS_SECS (now
);
1941 /* Value is the image id. */
1946 /* Cache image IMG in the image cache of frame F. */
1949 cache_image (f
, img
)
1953 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1956 /* Find a free slot in c->images. */
1957 for (i
= 0; i
< c
->used
; ++i
)
1958 if (c
->images
[i
] == NULL
)
1961 /* If no free slot found, maybe enlarge c->images. */
1962 if (i
== c
->used
&& c
->used
== c
->size
)
1965 c
->images
= (struct image
**) xrealloc (c
->images
,
1966 c
->size
* sizeof *c
->images
);
1969 /* Add IMG to c->images, and assign IMG an id. */
1975 /* Add IMG to the cache's hash table. */
1976 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1977 img
->next
= c
->buckets
[i
];
1979 img
->next
->prev
= img
;
1981 c
->buckets
[i
] = img
;
1985 /* Call FN on every image in the image cache of frame F. Used to mark
1986 Lisp Objects in the image cache. */
1989 forall_images_in_image_cache (f
, fn
)
1991 void (*fn
) P_ ((struct image
*img
));
1993 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1995 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1999 for (i
= 0; i
< c
->used
; ++i
)
2008 /***********************************************************************
2009 X / MAC / W32 support code
2010 ***********************************************************************/
2014 /* Macro for defining functions that will be loaded from image DLLs. */
2015 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2017 /* Macro for loading those image functions from the library. */
2018 #define LOAD_IMGLIB_FN(lib,func) { \
2019 fn_##func = (void *) GetProcAddress (lib, #func); \
2020 if (!fn_##func) return 0; \
2023 /* Load a DLL implementing an image type.
2024 The `image-library-alist' variable associates a symbol,
2025 identifying an image type, to a list of possible filenames.
2026 The function returns NULL if no library could be loaded for
2027 the given image type, or if the library was previously loaded;
2028 else the handle of the DLL. */
2030 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2032 HMODULE library
= NULL
;
2034 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2036 Lisp_Object dlls
= Fassq (type
, libraries
);
2039 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2041 CHECK_STRING_CAR (dlls
);
2042 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2050 #endif /* HAVE_NTGUI */
2052 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2053 XImagePtr
*, Pixmap
*));
2054 static void x_destroy_x_image
P_ ((XImagePtr
));
2055 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2058 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2059 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2060 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2061 via xmalloc. Print error messages via image_error if an error
2062 occurs. Value is non-zero if successful.
2064 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2065 should indicate the bit depth of the image. */
2068 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2070 int width
, height
, depth
;
2074 #ifdef HAVE_X_WINDOWS
2075 Display
*display
= FRAME_X_DISPLAY (f
);
2076 Window window
= FRAME_X_WINDOW (f
);
2077 Screen
*screen
= FRAME_X_SCREEN (f
);
2079 xassert (interrupt_input_blocked
);
2082 depth
= DefaultDepthOfScreen (screen
);
2083 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2084 depth
, ZPixmap
, 0, NULL
, width
, height
,
2085 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2088 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2092 /* Allocate image raster. */
2093 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2095 /* Allocate a pixmap of the same size. */
2096 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2097 if (*pixmap
== NO_PIXMAP
)
2099 x_destroy_x_image (*ximg
);
2101 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2106 #endif /* HAVE_X_WINDOWS */
2110 BITMAPINFOHEADER
*header
;
2112 int scanline_width_bits
;
2114 int palette_colors
= 0;
2119 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2120 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2122 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2126 scanline_width_bits
= width
* depth
;
2127 remainder
= scanline_width_bits
% 32;
2130 scanline_width_bits
+= 32 - remainder
;
2132 /* Bitmaps with a depth less than 16 need a palette. */
2133 /* BITMAPINFO structure already contains the first RGBQUAD. */
2135 palette_colors
= 1 << depth
- 1;
2137 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2140 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2144 header
= &((*ximg
)->info
.bmiHeader
);
2145 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2146 header
->biSize
= sizeof (*header
);
2147 header
->biWidth
= width
;
2148 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2149 header
->biPlanes
= 1;
2150 header
->biBitCount
= depth
;
2151 header
->biCompression
= BI_RGB
;
2152 header
->biClrUsed
= palette_colors
;
2154 /* TODO: fill in palette. */
2157 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2158 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2159 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2160 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2161 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2162 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2163 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2164 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2167 hdc
= get_frame_dc (f
);
2169 /* Create a DIBSection and raster array for the bitmap,
2170 and store its handle in *pixmap. */
2171 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2172 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2173 /* casting avoids a GCC warning */
2174 (void **)&((*ximg
)->data
), NULL
, 0);
2176 /* Realize display palette and garbage all frames. */
2177 release_frame_dc (f
, hdc
);
2179 if (*pixmap
== NULL
)
2181 DWORD err
= GetLastError();
2182 Lisp_Object errcode
;
2183 /* All system errors are < 10000, so the following is safe. */
2184 XSETINT (errcode
, (int) err
);
2185 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2186 x_destroy_x_image (*ximg
);
2192 #endif /* HAVE_NTGUI */
2195 Display
*display
= FRAME_X_DISPLAY (f
);
2196 Window window
= FRAME_X_WINDOW (f
);
2198 xassert (interrupt_input_blocked
);
2200 /* Allocate a pixmap of the same size. */
2201 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2202 if (*pixmap
== NO_PIXMAP
)
2205 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2209 LockPixels (GetGWorldPixMap (*pixmap
));
2217 /* Destroy XImage XIMG. Free XIMG->data. */
2220 x_destroy_x_image (ximg
)
2223 xassert (interrupt_input_blocked
);
2226 #ifdef HAVE_X_WINDOWS
2229 XDestroyImage (ximg
);
2230 #endif /* HAVE_X_WINDOWS */
2232 /* Data will be freed by DestroyObject. */
2235 #endif /* HAVE_NTGUI */
2237 XDestroyImage (ximg
);
2243 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2244 are width and height of both the image and pixmap. */
2247 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2253 #ifdef HAVE_X_WINDOWS
2256 xassert (interrupt_input_blocked
);
2257 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2258 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2259 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2260 #endif /* HAVE_X_WINDOWS */
2263 #if 0 /* I don't think this is necessary looking at where it is used. */
2264 HDC hdc
= get_frame_dc (f
);
2265 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2266 release_frame_dc (f
, hdc
);
2268 #endif /* HAVE_NTGUI */
2271 xassert (ximg
== pixmap
);
2276 /***********************************************************************
2278 ***********************************************************************/
2280 static unsigned char *slurp_file
P_ ((char *, int *));
2283 /* Find image file FILE. Look in data-directory, then
2284 x-bitmap-file-path. Value is the encoded full name of the file
2285 found, or nil if not found. */
2288 x_find_image_file (file
)
2291 Lisp_Object file_found
, search_path
;
2292 struct gcpro gcpro1
, gcpro2
;
2296 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2297 GCPRO2 (file_found
, search_path
);
2299 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2300 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2306 file_found
= ENCODE_FILE (file_found
);
2315 /* Read FILE into memory. Value is a pointer to a buffer allocated
2316 with xmalloc holding FILE's contents. Value is null if an error
2317 occurred. *SIZE is set to the size of the file. */
2319 static unsigned char *
2320 slurp_file (file
, size
)
2325 unsigned char *buf
= NULL
;
2328 if (stat (file
, &st
) == 0
2329 && (fp
= fopen (file
, "rb")) != NULL
2330 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2331 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2354 /***********************************************************************
2355 MAC Image Load Functions
2356 ***********************************************************************/
2358 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2361 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2365 find_image_fsspec (specified_file
, file
, fss
)
2366 Lisp_Object specified_file
, *file
;
2372 *file
= x_find_image_file (specified_file
);
2373 if (!STRINGP (*file
))
2374 return fnfErr
; /* file or directory not found;
2375 incomplete pathname */
2376 /* Try to open the image file. */
2377 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2378 SBYTES (*file
), typeFSS
, &desc
);
2381 #if TARGET_API_MAC_CARBON
2382 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2384 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2386 AEDisposeDesc (&desc
);
2392 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2399 ComponentResult err
;
2400 GraphicsImportComponent gi
;
2403 ImageDescriptionHandle desc_handle
;
2404 short draw_all_pixels
;
2405 Lisp_Object specified_bg
;
2410 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2414 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2419 /* read from file system spec */
2420 err
= GraphicsImportSetDataFile (gi
, fss
);
2423 image_error ("Cannot set fsspec to graphics importer for '%s'",
2430 /* read from data handle */
2431 err
= GraphicsImportSetDataHandle (gi
, dh
);
2434 image_error ("Cannot set data handle to graphics importer for `%s'",
2439 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2440 if (err
!= noErr
|| desc_handle
== NULL
)
2442 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2445 width
= img
->width
= (*desc_handle
)->width
;
2446 height
= img
->height
= (*desc_handle
)->height
;
2447 DisposeHandle ((Handle
)desc_handle
);
2449 if (!check_image_size (f
, width
, height
))
2451 image_error ("Invalid image size", Qnil
, Qnil
);
2455 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2457 /* Don't check the error code here. It may have an undocumented
2461 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2465 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2467 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2468 if (!STRINGP (specified_bg
) ||
2469 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2471 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2472 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2473 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2474 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2478 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2480 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2485 GetGWorld (&old_port
, &old_gdh
);
2486 SetGWorld (ximg
, NULL
);
2487 bg_color
.red
= color
.red
;
2488 bg_color
.green
= color
.green
;
2489 bg_color
.blue
= color
.blue
;
2490 RGBBackColor (&bg_color
);
2491 #if TARGET_API_MAC_CARBON
2492 GetPortBounds (ximg
, &rect
);
2495 EraseRect (&(ximg
->portRect
));
2497 SetGWorld (old_port
, old_gdh
);
2499 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2500 GraphicsImportDraw (gi
);
2501 CloseComponent (gi
);
2503 /* Maybe fill in the background field while we have ximg handy. */
2504 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2505 IMAGE_BACKGROUND (img
, f
, ximg
);
2507 /* Put the image into the pixmap. */
2508 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2509 x_destroy_x_image (ximg
);
2513 CloseComponent (gi
);
2518 /* Load an image using the QuickTime Graphics Importer.
2519 Note: The alpha channel does not work for PNG images. */
2521 image_load_quicktime (f
, img
, type
)
2526 Lisp_Object specified_file
;
2527 Lisp_Object specified_data
;
2530 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2531 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2533 if (NILP (specified_data
))
2535 /* Read from a file */
2539 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2543 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2545 image_error ("Cannot open `%s'", file
, Qnil
);
2548 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2552 /* Memory source! */
2556 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2559 image_error ("Cannot allocate data handle for `%s'",
2563 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2571 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2572 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2573 So don't use this function directly but determine at runtime
2574 whether it exists. */
2575 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2576 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2577 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2581 init_image_func_pointer ()
2583 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2585 MyCGImageCreateWithPNGDataProvider
2586 = (CGImageCreateWithPNGDataProviderProcType
)
2587 NSAddressOfSymbol (NSLookupAndBindSymbol
2588 ("_CGImageCreateWithPNGDataProvider"));
2591 MyCGImageCreateWithPNGDataProvider
= NULL
;
2596 image_load_quartz2d (f
, img
, png_p
)
2601 Lisp_Object file
, specified_file
;
2602 Lisp_Object specified_data
, specified_bg
;
2603 struct gcpro gcpro1
;
2604 CGDataProviderRef source
;
2608 XImagePtr ximg
= NULL
;
2609 CGContextRef context
;
2612 /* Open the file. */
2613 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2614 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2619 if (NILP (specified_data
))
2624 file
= x_find_image_file (specified_file
);
2625 if (!STRINGP (file
))
2627 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2631 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2632 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2633 kCFURLPOSIXPathStyle
, 0);
2635 source
= CGDataProviderCreateWithURL (url
);
2639 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2640 SBYTES (specified_data
), NULL
);
2643 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2644 kCGRenderingIntentDefault
);
2646 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2647 kCGRenderingIntentDefault
);
2649 CGDataProviderRelease (source
);
2653 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2656 width
= img
->width
= CGImageGetWidth (image
);
2657 height
= img
->height
= CGImageGetHeight (image
);
2659 if (!check_image_size (f
, width
, height
))
2661 CGImageRelease (image
);
2663 image_error ("Invalid image size", Qnil
, Qnil
);
2669 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2670 if (!STRINGP (specified_bg
) ||
2671 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2673 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2674 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2675 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2676 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2680 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2682 CGImageRelease (image
);
2686 rectangle
= CGRectMake (0, 0, width
, height
);
2687 QDBeginCGContext (ximg
, &context
);
2690 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2691 color
.green
/ 65535.0,
2692 color
.blue
/ 65535.0, 1.0);
2693 CGContextFillRect (context
, rectangle
);
2695 CGContextDrawImage (context
, rectangle
, image
);
2696 QDEndCGContext (ximg
, &context
);
2697 CGImageRelease (image
);
2699 /* Maybe fill in the background field while we have ximg handy. */
2700 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2701 IMAGE_BACKGROUND (img
, f
, ximg
);
2703 /* Put the image into the pixmap. */
2704 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2705 x_destroy_x_image (ximg
);
2714 /***********************************************************************
2716 ***********************************************************************/
2718 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2719 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2720 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2721 unsigned char *, unsigned char *));
2722 static int xbm_image_p
P_ ((Lisp_Object object
));
2723 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2724 unsigned char *, unsigned char *,
2725 int *, int *, unsigned char **));
2726 static int xbm_file_p
P_ ((Lisp_Object
));
2729 /* Indices of image specification fields in xbm_format, below. */
2731 enum xbm_keyword_index
2749 /* Vector of image_keyword structures describing the format
2750 of valid XBM image specifications. */
2752 static struct image_keyword xbm_format
[XBM_LAST
] =
2754 {":type", IMAGE_SYMBOL_VALUE
, 1},
2755 {":file", IMAGE_STRING_VALUE
, 0},
2756 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2757 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2758 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2759 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2760 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2761 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2762 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2763 {":relief", IMAGE_INTEGER_VALUE
, 0},
2764 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2765 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2766 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2769 /* Structure describing the image type XBM. */
2771 static struct image_type xbm_type
=
2780 /* Tokens returned from xbm_scan. */
2789 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2790 A valid specification is a list starting with the symbol `image'
2791 The rest of the list is a property list which must contain an
2794 If the specification specifies a file to load, it must contain
2795 an entry `:file FILENAME' where FILENAME is a string.
2797 If the specification is for a bitmap loaded from memory it must
2798 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2799 WIDTH and HEIGHT are integers > 0. DATA may be:
2801 1. a string large enough to hold the bitmap data, i.e. it must
2802 have a size >= (WIDTH + 7) / 8 * HEIGHT
2804 2. a bool-vector of size >= WIDTH * HEIGHT
2806 3. a vector of strings or bool-vectors, one for each line of the
2809 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2810 may not be specified in this case because they are defined in the
2813 Both the file and data forms may contain the additional entries
2814 `:background COLOR' and `:foreground COLOR'. If not present,
2815 foreground and background of the frame on which the image is
2816 displayed is used. */
2819 xbm_image_p (object
)
2822 struct image_keyword kw
[XBM_LAST
];
2824 bcopy (xbm_format
, kw
, sizeof kw
);
2825 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2828 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2830 if (kw
[XBM_FILE
].count
)
2832 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2835 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2837 /* In-memory XBM file. */
2838 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2846 /* Entries for `:width', `:height' and `:data' must be present. */
2847 if (!kw
[XBM_WIDTH
].count
2848 || !kw
[XBM_HEIGHT
].count
2849 || !kw
[XBM_DATA
].count
)
2852 data
= kw
[XBM_DATA
].value
;
2853 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2854 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2856 /* Check type of data, and width and height against contents of
2862 /* Number of elements of the vector must be >= height. */
2863 if (XVECTOR (data
)->size
< height
)
2866 /* Each string or bool-vector in data must be large enough
2867 for one line of the image. */
2868 for (i
= 0; i
< height
; ++i
)
2870 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2875 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2878 else if (BOOL_VECTOR_P (elt
))
2880 if (XBOOL_VECTOR (elt
)->size
< width
)
2887 else if (STRINGP (data
))
2890 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2893 else if (BOOL_VECTOR_P (data
))
2895 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2906 /* Scan a bitmap file. FP is the stream to read from. Value is
2907 either an enumerator from enum xbm_token, or a character for a
2908 single-character token, or 0 at end of file. If scanning an
2909 identifier, store the lexeme of the identifier in SVAL. If
2910 scanning a number, store its value in *IVAL. */
2913 xbm_scan (s
, end
, sval
, ival
)
2914 unsigned char **s
, *end
;
2922 /* Skip white space. */
2923 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2928 else if (isdigit (c
))
2930 int value
= 0, digit
;
2932 if (c
== '0' && *s
< end
)
2935 if (c
== 'x' || c
== 'X')
2942 else if (c
>= 'a' && c
<= 'f')
2943 digit
= c
- 'a' + 10;
2944 else if (c
>= 'A' && c
<= 'F')
2945 digit
= c
- 'A' + 10;
2948 value
= 16 * value
+ digit
;
2951 else if (isdigit (c
))
2955 && (c
= *(*s
)++, isdigit (c
)))
2956 value
= 8 * value
+ c
- '0';
2963 && (c
= *(*s
)++, isdigit (c
)))
2964 value
= 10 * value
+ c
- '0';
2972 else if (isalpha (c
) || c
== '_')
2976 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2983 else if (c
== '/' && **s
== '*')
2985 /* C-style comment. */
2987 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3001 /* Create a Windows bitmap from X bitmap data. */
3003 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3005 static unsigned char swap_nibble
[16]
3006 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3007 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3008 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3009 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3011 unsigned char *bits
, *p
;
3014 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3015 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3016 bits
= (unsigned char *) alloca (height
* w2
);
3017 bzero (bits
, height
* w2
);
3018 for (i
= 0; i
< height
; i
++)
3021 for (j
= 0; j
< w1
; j
++)
3023 /* Bitswap XBM bytes to match how Windows does things. */
3024 unsigned char c
= *data
++;
3025 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3026 | (swap_nibble
[(c
>>4) & 0xf]));
3029 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3034 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
3037 COLORREF foreground
, background
;
3039 HDC hdc
, old_img_dc
, new_img_dc
;
3040 HGDIOBJ old_prev
, new_prev
;
3043 hdc
= get_frame_dc (f
);
3044 old_img_dc
= CreateCompatibleDC (hdc
);
3045 new_img_dc
= CreateCompatibleDC (hdc
);
3046 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3047 release_frame_dc (f
, hdc
);
3048 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3049 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3050 SetTextColor (new_img_dc
, foreground
);
3051 SetBkColor (new_img_dc
, background
);
3053 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3056 SelectObject (old_img_dc
, old_prev
);
3057 SelectObject (new_img_dc
, new_prev
);
3058 DeleteDC (old_img_dc
);
3059 DeleteDC (new_img_dc
);
3060 DeleteObject (img
->pixmap
);
3061 if (new_pixmap
== 0)
3062 fprintf (stderr
, "Failed to convert image to color.\n");
3064 img
->pixmap
= new_pixmap
;
3067 #define XBM_BIT_SHUFFLE(b) (~(b))
3071 #define XBM_BIT_SHUFFLE(b) (b)
3073 #endif /* HAVE_NTGUI */
3077 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
3081 RGB_PIXEL_COLOR fg
, bg
;
3082 int non_default_colors
;
3086 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3088 /* If colors were specified, transfer the bitmap to a color one. */
3089 if (non_default_colors
)
3090 convert_mono_to_color_image (f
, img
, fg
, bg
);
3093 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3096 img
->width
, img
->height
,
3098 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3099 #endif /* HAVE_NTGUI */
3104 /* Replacement for XReadBitmapFileData which isn't available under old
3105 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3106 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3107 the image. Return in *DATA the bitmap data allocated with xmalloc.
3108 Value is non-zero if successful. DATA null means just test if
3109 CONTENTS looks like an in-memory XBM file. */
3112 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3114 unsigned char *contents
, *end
;
3115 int *width
, *height
;
3116 unsigned char **data
;
3118 unsigned char *s
= contents
;
3119 char buffer
[BUFSIZ
];
3122 int bytes_per_line
, i
, nbytes
;
3128 LA1 = xbm_scan (&s, end, buffer, &value)
3130 #define expect(TOKEN) \
3131 if (LA1 != (TOKEN)) \
3136 #define expect_ident(IDENT) \
3137 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3142 *width
= *height
= -1;
3145 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3147 /* Parse defines for width, height and hot-spots. */
3151 expect_ident ("define");
3152 expect (XBM_TK_IDENT
);
3154 if (LA1
== XBM_TK_NUMBER
);
3156 char *p
= strrchr (buffer
, '_');
3157 p
= p
? p
+ 1 : buffer
;
3158 if (strcmp (p
, "width") == 0)
3160 else if (strcmp (p
, "height") == 0)
3163 expect (XBM_TK_NUMBER
);
3166 if (!check_image_size (f
, *width
, *height
))
3168 else if (data
== NULL
)
3171 /* Parse bits. Must start with `static'. */
3172 expect_ident ("static");
3173 if (LA1
== XBM_TK_IDENT
)
3175 if (strcmp (buffer
, "unsigned") == 0)
3178 expect_ident ("char");
3180 else if (strcmp (buffer
, "short") == 0)
3184 if (*width
% 16 && *width
% 16 < 9)
3187 else if (strcmp (buffer
, "char") == 0)
3195 expect (XBM_TK_IDENT
);
3201 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3202 nbytes
= bytes_per_line
* *height
;
3203 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3207 for (i
= 0; i
< nbytes
; i
+= 2)
3210 expect (XBM_TK_NUMBER
);
3212 *p
++ = XBM_BIT_SHUFFLE (val
);
3213 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3214 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3216 if (LA1
== ',' || LA1
== '}')
3224 for (i
= 0; i
< nbytes
; ++i
)
3227 expect (XBM_TK_NUMBER
);
3229 *p
++ = XBM_BIT_SHUFFLE (val
);
3231 if (LA1
== ',' || LA1
== '}')
3256 /* Load XBM image IMG which will be displayed on frame F from buffer
3257 CONTENTS. END is the end of the buffer. Value is non-zero if
3261 xbm_load_image (f
, img
, contents
, end
)
3264 unsigned char *contents
, *end
;
3267 unsigned char *data
;
3270 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3273 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3274 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3275 int non_default_colors
= 0;
3278 xassert (img
->width
> 0 && img
->height
> 0);
3280 /* Get foreground and background colors, maybe allocate colors. */
3281 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3284 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3285 non_default_colors
= 1;
3287 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3290 background
= x_alloc_image_color (f
, img
, value
, background
);
3291 img
->background
= background
;
3292 img
->background_valid
= 1;
3293 non_default_colors
= 1;
3296 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3297 foreground
, background
,
3298 non_default_colors
);
3301 if (img
->pixmap
== NO_PIXMAP
)
3303 x_clear_image (f
, img
);
3304 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3310 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3316 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3323 return (STRINGP (data
)
3324 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3331 /* Fill image IMG which is used on frame F with pixmap data. Value is
3332 non-zero if successful. */
3340 Lisp_Object file_name
;
3342 xassert (xbm_image_p (img
->spec
));
3344 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3345 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3346 if (STRINGP (file_name
))
3349 unsigned char *contents
;
3351 struct gcpro gcpro1
;
3353 file
= x_find_image_file (file_name
);
3355 if (!STRINGP (file
))
3357 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3362 contents
= slurp_file (SDATA (file
), &size
);
3363 if (contents
== NULL
)
3365 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3370 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3375 struct image_keyword fmt
[XBM_LAST
];
3377 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3378 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3379 int non_default_colors
= 0;
3382 int in_memory_file_p
= 0;
3384 /* See if data looks like an in-memory XBM file. */
3385 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3386 in_memory_file_p
= xbm_file_p (data
);
3388 /* Parse the image specification. */
3389 bcopy (xbm_format
, fmt
, sizeof fmt
);
3390 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3393 /* Get specified width, and height. */
3394 if (!in_memory_file_p
)
3396 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3397 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3398 xassert (img
->width
> 0 && img
->height
> 0);
3401 /* Get foreground and background colors, maybe allocate colors. */
3402 if (fmt
[XBM_FOREGROUND
].count
3403 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3405 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3407 non_default_colors
= 1;
3410 if (fmt
[XBM_BACKGROUND
].count
3411 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3413 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3415 non_default_colors
= 1;
3418 if (in_memory_file_p
)
3419 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3428 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3430 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3431 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3433 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3435 bcopy (SDATA (line
), p
, nbytes
);
3437 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3440 else if (STRINGP (data
))
3441 bits
= SDATA (data
);
3443 bits
= XBOOL_VECTOR (data
)->data
;
3445 /* Create the pixmap. */
3447 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3448 foreground
, background
,
3449 non_default_colors
);
3454 image_error ("Unable to create pixmap for XBM image `%s'",
3456 x_clear_image (f
, img
);
3466 /***********************************************************************
3468 ***********************************************************************/
3470 #if defined (HAVE_XPM) || defined (MAC_OS)
3472 static int xpm_image_p
P_ ((Lisp_Object object
));
3473 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3474 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3476 #endif /* HAVE_XPM || MAC_OS */
3480 /* Indicate to xpm.h that we don't have Xlib. */
3482 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3483 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3484 #define XColor xpm_XColor
3485 #define XImage xpm_XImage
3486 #define Display xpm_Display
3487 #define PIXEL_ALREADY_TYPEDEFED
3488 #include "X11/xpm.h"
3493 #undef PIXEL_ALREADY_TYPEDEFED
3495 #include "X11/xpm.h"
3496 #endif /* HAVE_NTGUI */
3497 #endif /* HAVE_XPM */
3499 #if defined (HAVE_XPM) || defined (MAC_OS)
3500 /* The symbol `xpm' identifying XPM-format images. */
3504 /* Indices of image specification fields in xpm_format, below. */
3506 enum xpm_keyword_index
3522 /* Vector of image_keyword structures describing the format
3523 of valid XPM image specifications. */
3525 static struct image_keyword xpm_format
[XPM_LAST
] =
3527 {":type", IMAGE_SYMBOL_VALUE
, 1},
3528 {":file", IMAGE_STRING_VALUE
, 0},
3529 {":data", IMAGE_STRING_VALUE
, 0},
3530 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3531 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3532 {":relief", IMAGE_INTEGER_VALUE
, 0},
3533 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3534 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3535 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3536 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3537 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3540 /* Structure describing the image type XPM. */
3542 static struct image_type xpm_type
=
3551 #ifdef HAVE_X_WINDOWS
3553 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3554 functions for allocating image colors. Our own functions handle
3555 color allocation failures more gracefully than the ones on the XPM
3558 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3559 #define ALLOC_XPM_COLORS
3561 #endif /* HAVE_X_WINDOWS */
3563 #ifdef ALLOC_XPM_COLORS
3565 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3566 static void xpm_free_color_cache
P_ ((void));
3567 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3568 static int xpm_color_bucket
P_ ((char *));
3569 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3572 /* An entry in a hash table used to cache color definitions of named
3573 colors. This cache is necessary to speed up XPM image loading in
3574 case we do color allocations ourselves. Without it, we would need
3575 a call to XParseColor per pixel in the image. */
3577 struct xpm_cached_color
3579 /* Next in collision chain. */
3580 struct xpm_cached_color
*next
;
3582 /* Color definition (RGB and pixel color). */
3589 /* The hash table used for the color cache, and its bucket vector
3592 #define XPM_COLOR_CACHE_BUCKETS 1001
3593 struct xpm_cached_color
**xpm_color_cache
;
3595 /* Initialize the color cache. */
3598 xpm_init_color_cache (f
, attrs
)
3600 XpmAttributes
*attrs
;
3602 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3603 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3604 memset (xpm_color_cache
, 0, nbytes
);
3605 init_color_table ();
3607 if (attrs
->valuemask
& XpmColorSymbols
)
3612 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3613 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3614 attrs
->colorsymbols
[i
].value
, &color
))
3616 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3618 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3623 /* Free the color cache. */
3626 xpm_free_color_cache ()
3628 struct xpm_cached_color
*p
, *next
;
3631 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3632 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3638 xfree (xpm_color_cache
);
3639 xpm_color_cache
= NULL
;
3640 free_color_table ();
3643 /* Return the bucket index for color named COLOR_NAME in the color
3647 xpm_color_bucket (color_name
)
3653 for (s
= color_name
; *s
; ++s
)
3655 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3659 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3660 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3663 static struct xpm_cached_color
*
3664 xpm_cache_color (f
, color_name
, color
, bucket
)
3671 struct xpm_cached_color
*p
;
3674 bucket
= xpm_color_bucket (color_name
);
3676 nbytes
= sizeof *p
+ strlen (color_name
);
3677 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3678 strcpy (p
->name
, color_name
);
3680 p
->next
= xpm_color_cache
[bucket
];
3681 xpm_color_cache
[bucket
] = p
;
3685 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3686 return the cached definition in *COLOR. Otherwise, make a new
3687 entry in the cache and allocate the color. Value is zero if color
3688 allocation failed. */
3691 xpm_lookup_color (f
, color_name
, color
)
3696 struct xpm_cached_color
*p
;
3697 int h
= xpm_color_bucket (color_name
);
3699 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3700 if (strcmp (p
->name
, color_name
) == 0)
3705 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3708 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3710 p
= xpm_cache_color (f
, color_name
, color
, h
);
3712 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3713 with transparency, and it's useful. */
3714 else if (strcmp ("opaque", color_name
) == 0)
3716 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3717 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3718 p
= xpm_cache_color (f
, color_name
, color
, h
);
3725 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3726 CLOSURE is a pointer to the frame on which we allocate the
3727 color. Return in *COLOR the allocated color. Value is non-zero
3731 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3738 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3742 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3743 is a pointer to the frame on which we allocate the color. Value is
3744 non-zero if successful. */
3747 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3757 #endif /* ALLOC_XPM_COLORS */
3762 /* XPM library details. */
3764 DEF_IMGLIB_FN (XpmFreeAttributes
);
3765 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3766 DEF_IMGLIB_FN (XpmReadFileToImage
);
3767 DEF_IMGLIB_FN (XImageFree
);
3770 init_xpm_functions (Lisp_Object libraries
)
3774 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3777 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3778 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3779 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3780 LOAD_IMGLIB_FN (library
, XImageFree
);
3784 #endif /* HAVE_NTGUI */
3787 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3788 for XPM images. Such a list must consist of conses whose car and
3792 xpm_valid_color_symbols_p (color_symbols
)
3793 Lisp_Object color_symbols
;
3795 while (CONSP (color_symbols
))
3797 Lisp_Object sym
= XCAR (color_symbols
);
3799 || !STRINGP (XCAR (sym
))
3800 || !STRINGP (XCDR (sym
)))
3802 color_symbols
= XCDR (color_symbols
);
3805 return NILP (color_symbols
);
3809 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3812 xpm_image_p (object
)
3815 struct image_keyword fmt
[XPM_LAST
];
3816 bcopy (xpm_format
, fmt
, sizeof fmt
);
3817 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3818 /* Either `:file' or `:data' must be present. */
3819 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3820 /* Either no `:color-symbols' or it's a list of conses
3821 whose car and cdr are strings. */
3822 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3823 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3826 #endif /* HAVE_XPM || MAC_OS */
3828 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3830 x_create_bitmap_from_xpm_data (f
, bits
)
3834 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3836 XpmAttributes attrs
;
3837 Pixmap bitmap
, mask
;
3839 bzero (&attrs
, sizeof attrs
);
3841 attrs
.visual
= FRAME_X_VISUAL (f
);
3842 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3843 attrs
.valuemask
|= XpmVisual
;
3844 attrs
.valuemask
|= XpmColormap
;
3846 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3847 bits
, &bitmap
, &mask
, &attrs
);
3848 if (rc
!= XpmSuccess
)
3850 XpmFreeAttributes (&attrs
);
3854 id
= x_allocate_bitmap_record (f
);
3855 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3856 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3857 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3858 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3859 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3860 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3861 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3862 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3864 XpmFreeAttributes (&attrs
);
3867 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3869 /* Load image IMG which will be displayed on frame F. Value is
3870 non-zero if successful. */
3880 XpmAttributes attrs
;
3881 Lisp_Object specified_file
, color_symbols
;
3884 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3885 #endif /* HAVE_NTGUI */
3887 /* Configure the XPM lib. Use the visual of frame F. Allocate
3888 close colors. Return colors allocated. */
3889 bzero (&attrs
, sizeof attrs
);
3892 attrs
.visual
= FRAME_X_VISUAL (f
);
3893 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3894 attrs
.valuemask
|= XpmVisual
;
3895 attrs
.valuemask
|= XpmColormap
;
3896 #endif /* HAVE_NTGUI */
3898 #ifdef ALLOC_XPM_COLORS
3899 /* Allocate colors with our own functions which handle
3900 failing color allocation more gracefully. */
3901 attrs
.color_closure
= f
;
3902 attrs
.alloc_color
= xpm_alloc_color
;
3903 attrs
.free_colors
= xpm_free_colors
;
3904 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3905 #else /* not ALLOC_XPM_COLORS */
3906 /* Let the XPM lib allocate colors. */
3907 attrs
.valuemask
|= XpmReturnAllocPixels
;
3908 #ifdef XpmAllocCloseColors
3909 attrs
.alloc_close_colors
= 1;
3910 attrs
.valuemask
|= XpmAllocCloseColors
;
3911 #else /* not XpmAllocCloseColors */
3912 attrs
.closeness
= 600;
3913 attrs
.valuemask
|= XpmCloseness
;
3914 #endif /* not XpmAllocCloseColors */
3915 #endif /* ALLOC_XPM_COLORS */
3916 #ifdef ALLOC_XPM_COLORS
3917 xpm_init_color_cache (f
, &attrs
);
3920 /* If image specification contains symbolic color definitions, add
3921 these to `attrs'. */
3922 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3923 if (CONSP (color_symbols
))
3926 XpmColorSymbol
*xpm_syms
;
3929 attrs
.valuemask
|= XpmColorSymbols
;
3931 /* Count number of symbols. */
3932 attrs
.numsymbols
= 0;
3933 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3936 /* Allocate an XpmColorSymbol array. */
3937 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3938 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3939 bzero (xpm_syms
, size
);
3940 attrs
.colorsymbols
= xpm_syms
;
3942 /* Fill the color symbol array. */
3943 for (tail
= color_symbols
, i
= 0;
3945 ++i
, tail
= XCDR (tail
))
3947 Lisp_Object name
= XCAR (XCAR (tail
));
3948 Lisp_Object color
= XCDR (XCAR (tail
));
3949 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3950 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3951 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3952 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3956 /* Create a pixmap for the image, either from a file, or from a
3957 string buffer containing data in the same format as an XPM file. */
3958 #ifdef ALLOC_XPM_COLORS
3959 xpm_init_color_cache (f
, &attrs
);
3962 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3966 HDC frame_dc
= get_frame_dc (f
);
3967 hdc
= CreateCompatibleDC (frame_dc
);
3968 release_frame_dc (f
, frame_dc
);
3970 #endif /* HAVE_NTGUI */
3972 if (STRINGP (specified_file
))
3974 Lisp_Object file
= x_find_image_file (specified_file
);
3975 if (!STRINGP (file
))
3977 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3982 /* XpmReadFileToPixmap is not available in the Windows port of
3983 libxpm. But XpmReadFileToImage almost does what we want. */
3984 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3985 &xpm_image
, &xpm_mask
,
3988 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3989 SDATA (file
), &img
->pixmap
, &img
->mask
,
3991 #endif /* HAVE_NTGUI */
3995 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3997 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3998 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3999 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4000 &xpm_image
, &xpm_mask
,
4003 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4005 &img
->pixmap
, &img
->mask
,
4007 #endif /* HAVE_NTGUI */
4010 if (rc
== XpmSuccess
)
4012 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4013 img
->colors
= colors_in_color_table (&img
->ncolors
);
4014 #else /* not ALLOC_XPM_COLORS */
4018 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4019 plus some duplicate attributes. */
4020 if (xpm_image
&& xpm_image
->bitmap
)
4022 img
->pixmap
= xpm_image
->bitmap
;
4023 /* XImageFree in libXpm frees XImage struct without destroying
4024 the bitmap, which is what we want. */
4025 fn_XImageFree (xpm_image
);
4027 if (xpm_mask
&& xpm_mask
->bitmap
)
4029 /* The mask appears to be inverted compared with what we expect.
4030 TODO: invert our expectations. See other places where we
4031 have to invert bits because our idea of masks is backwards. */
4033 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4035 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4036 SelectObject (hdc
, old_obj
);
4038 img
->mask
= xpm_mask
->bitmap
;
4039 fn_XImageFree (xpm_mask
);
4044 #endif /* HAVE_NTGUI */
4046 /* Remember allocated colors. */
4047 img
->ncolors
= attrs
.nalloc_pixels
;
4048 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4049 * sizeof *img
->colors
);
4050 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4052 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4053 #ifdef DEBUG_X_COLORS
4054 register_color (img
->colors
[i
]);
4057 #endif /* not ALLOC_XPM_COLORS */
4059 img
->width
= attrs
.width
;
4060 img
->height
= attrs
.height
;
4061 xassert (img
->width
> 0 && img
->height
> 0);
4063 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4065 fn_XpmFreeAttributes (&attrs
);
4067 XpmFreeAttributes (&attrs
);
4068 #endif /* HAVE_NTGUI */
4074 #endif /* HAVE_NTGUI */
4079 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4082 case XpmFileInvalid
:
4083 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4087 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4090 case XpmColorFailed
:
4091 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4095 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4100 #ifdef ALLOC_XPM_COLORS
4101 xpm_free_color_cache ();
4103 return rc
== XpmSuccess
;
4106 #endif /* HAVE_XPM */
4110 /* XPM support functions for Mac OS where libxpm is not available.
4111 Only XPM version 3 (without any extensions) is supported. */
4113 static int xpm_scan
P_ ((unsigned char **, unsigned char *,
4114 unsigned char **, int *));
4115 static Lisp_Object xpm_make_color_table_v
4116 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
4117 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
4118 static void xpm_put_color_table_v
P_ ((Lisp_Object
, unsigned char *,
4120 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4121 unsigned char *, int));
4122 static Lisp_Object xpm_make_color_table_h
4123 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
4124 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
4125 static void xpm_put_color_table_h
P_ ((Lisp_Object
, unsigned char *,
4127 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4128 unsigned char *, int));
4129 static int xpm_str_to_color_key
P_ ((char *));
4130 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4131 unsigned char *, unsigned char *));
4133 /* Tokens returned from xpm_scan. */
4142 /* Scan an XPM data and return a character (< 256) or a token defined
4143 by enum xpm_token above. *S and END are the start (inclusive) and
4144 the end (exclusive) addresses of the data, respectively. Advance
4145 *S while scanning. If token is either XPM_TK_IDENT or
4146 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4147 length of the corresponding token, respectively. */
4150 xpm_scan (s
, end
, beg
, len
)
4151 unsigned char **s
, *end
, **beg
;
4158 /* Skip white-space. */
4159 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4162 /* gnus-pointer.xpm uses '-' in its identifier.
4163 sb-dir-plus.xpm uses '+' in its identifier. */
4164 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4168 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4171 return XPM_TK_IDENT
;
4176 while (*s
< end
&& **s
!= '"')
4181 return XPM_TK_STRING
;
4185 if (*s
< end
&& **s
== '*')
4187 /* C-style comment. */
4191 while (*s
< end
&& *(*s
)++ != '*')
4194 while (*s
< end
&& **s
!= '/');
4208 /* Functions for color table lookup in XPM data. A Key is a string
4209 specifying the color of each pixel in XPM data. A value is either
4210 an integer that specifies a pixel color, Qt that specifies
4211 transparency, or Qnil for the unspecified color. If the length of
4212 the key string is one, a vector is used as a table. Otherwise, a
4213 hash table is used. */
4216 xpm_make_color_table_v (put_func
, get_func
)
4217 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4218 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
4220 *put_func
= xpm_put_color_table_v
;
4221 *get_func
= xpm_get_color_table_v
;
4222 return Fmake_vector (make_number (256), Qnil
);
4226 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4227 Lisp_Object color_table
;
4228 unsigned char *chars_start
;
4232 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4236 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4237 Lisp_Object color_table
;
4238 unsigned char *chars_start
;
4241 return XVECTOR (color_table
)->contents
[*chars_start
];
4245 xpm_make_color_table_h (put_func
, get_func
)
4246 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4247 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
4249 *put_func
= xpm_put_color_table_h
;
4250 *get_func
= xpm_get_color_table_h
;
4251 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4252 make_float (DEFAULT_REHASH_SIZE
),
4253 make_float (DEFAULT_REHASH_THRESHOLD
),
4258 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4259 Lisp_Object color_table
;
4260 unsigned char *chars_start
;
4264 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4266 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4268 hash_lookup (table
, chars
, &hash_code
);
4269 hash_put (table
, chars
, color
, hash_code
);
4273 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4274 Lisp_Object color_table
;
4275 unsigned char *chars_start
;
4278 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4279 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4282 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4285 enum xpm_color_key
{
4293 static char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4296 xpm_str_to_color_key (s
)
4302 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4304 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4310 xpm_load_image (f
, img
, contents
, end
)
4313 unsigned char *contents
, *end
;
4315 unsigned char *s
= contents
, *beg
, *str
;
4316 unsigned char buffer
[BUFSIZ
];
4317 int width
, height
, x
, y
;
4318 int num_colors
, chars_per_pixel
;
4320 void (*put_color_table
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4321 Lisp_Object (*get_color_table
) (Lisp_Object
, unsigned char *, int);
4322 Lisp_Object frame
, color_symbols
, color_table
;
4323 int best_key
, have_mask
= 0;
4324 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4327 LA1 = xpm_scan (&s, end, &beg, &len)
4329 #define expect(TOKEN) \
4330 if (LA1 != (TOKEN)) \
4335 #define expect_ident(IDENT) \
4336 if (LA1 == XPM_TK_IDENT \
4337 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4342 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4346 expect_ident ("static");
4347 expect_ident ("char");
4349 expect (XPM_TK_IDENT
);
4354 expect (XPM_TK_STRING
);
4357 memcpy (buffer
, beg
, len
);
4359 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4360 &num_colors
, &chars_per_pixel
) != 4
4361 || width
<= 0 || height
<= 0
4362 || num_colors
<= 0 || chars_per_pixel
<= 0)
4365 if (!check_image_size (f
, width
, height
))
4367 image_error ("Invalid image size", Qnil
, Qnil
);
4373 XSETFRAME (frame
, f
);
4374 if (!NILP (Fxw_display_color_p (frame
)))
4375 best_key
= XPM_COLOR_KEY_C
;
4376 else if (!NILP (Fx_display_grayscale_p (frame
)))
4377 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4378 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4380 best_key
= XPM_COLOR_KEY_M
;
4382 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4383 if (chars_per_pixel
== 1)
4384 color_table
= xpm_make_color_table_v (&put_color_table
,
4387 color_table
= xpm_make_color_table_h (&put_color_table
,
4390 while (num_colors
-- > 0)
4392 unsigned char *color
, *max_color
;
4393 int key
, next_key
, max_key
= 0;
4394 Lisp_Object symbol_color
= Qnil
, color_val
;
4397 expect (XPM_TK_STRING
);
4398 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4400 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4401 buffer
[len
- chars_per_pixel
] = '\0';
4403 str
= strtok (buffer
, " \t");
4406 key
= xpm_str_to_color_key (str
);
4411 color
= strtok (NULL
, " \t");
4415 while ((str
= strtok (NULL
, " \t")) != NULL
)
4417 next_key
= xpm_str_to_color_key (str
);
4420 color
[strlen (color
)] = ' ';
4423 if (key
== XPM_COLOR_KEY_S
)
4425 if (NILP (symbol_color
))
4426 symbol_color
= build_string (color
);
4428 else if (max_key
< key
&& key
<= best_key
)
4438 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4440 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4442 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4444 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4446 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4448 color_val
= make_number (cdef
.pixel
);
4451 if (NILP (color_val
) && max_key
> 0)
4453 if (xstricmp (max_color
, "None") == 0)
4455 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4456 color_val
= make_number (cdef
.pixel
);
4458 if (!NILP (color_val
))
4459 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4464 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4465 &ximg
, &img
->pixmap
)
4466 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4467 &mask_img
, &img
->mask
))
4469 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4473 for (y
= 0; y
< height
; y
++)
4475 expect (XPM_TK_STRING
);
4477 if (len
< width
* chars_per_pixel
)
4479 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4481 Lisp_Object color_val
=
4482 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4484 XPutPixel (ximg
, x
, y
,
4485 (INTEGERP (color_val
) ? XINT (color_val
)
4486 : FRAME_FOREGROUND_PIXEL (f
)));
4487 XPutPixel (mask_img
, x
, y
,
4488 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4489 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4496 img
->height
= height
;
4498 /* Maybe fill in the background field while we have ximg handy. */
4499 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4500 IMAGE_BACKGROUND (img
, f
, ximg
);
4502 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4503 x_destroy_x_image (ximg
);
4506 /* Fill in the background_transparent field while we have the
4508 image_background_transparent (img
, f
, mask_img
);
4510 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4511 x_destroy_x_image (mask_img
);
4515 x_destroy_x_image (mask_img
);
4516 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4517 img
->mask
= NO_PIXMAP
;
4523 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4525 x_destroy_x_image (ximg
);
4526 x_destroy_x_image (mask_img
);
4527 x_clear_image (f
, img
);
4541 Lisp_Object file_name
;
4543 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4544 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4545 if (STRINGP (file_name
))
4548 unsigned char *contents
;
4550 struct gcpro gcpro1
;
4552 file
= x_find_image_file (file_name
);
4554 if (!STRINGP (file
))
4556 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4561 contents
= slurp_file (SDATA (file
), &size
);
4562 if (contents
== NULL
)
4564 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4569 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4577 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4578 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4579 SDATA (data
) + SBYTES (data
));
4589 /***********************************************************************
4591 ***********************************************************************/
4593 #ifdef COLOR_TABLE_SUPPORT
4595 /* An entry in the color table mapping an RGB color to a pixel color. */
4600 unsigned long pixel
;
4602 /* Next in color table collision list. */
4603 struct ct_color
*next
;
4606 /* The bucket vector size to use. Must be prime. */
4610 /* Value is a hash of the RGB color given by R, G, and B. */
4612 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4614 /* The color hash table. */
4616 struct ct_color
**ct_table
;
4618 /* Number of entries in the color table. */
4620 int ct_colors_allocated
;
4622 /* Initialize the color table. */
4627 int size
= CT_SIZE
* sizeof (*ct_table
);
4628 ct_table
= (struct ct_color
**) xmalloc (size
);
4629 bzero (ct_table
, size
);
4630 ct_colors_allocated
= 0;
4634 /* Free memory associated with the color table. */
4640 struct ct_color
*p
, *next
;
4642 for (i
= 0; i
< CT_SIZE
; ++i
)
4643 for (p
= ct_table
[i
]; p
; p
= next
)
4654 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4655 entry for that color already is in the color table, return the
4656 pixel color of that entry. Otherwise, allocate a new color for R,
4657 G, B, and make an entry in the color table. */
4659 static unsigned long
4660 lookup_rgb_color (f
, r
, g
, b
)
4664 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4665 int i
= hash
% CT_SIZE
;
4667 Display_Info
*dpyinfo
;
4669 /* Handle TrueColor visuals specially, which improves performance by
4670 two orders of magnitude. Freeing colors on TrueColor visuals is
4671 a nop, and pixel colors specify RGB values directly. See also
4672 the Xlib spec, chapter 3.1. */
4673 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4674 if (dpyinfo
->red_bits
> 0)
4676 unsigned long pr
, pg
, pb
;
4678 /* Apply gamma-correction like normal color allocation does. */
4682 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4683 gamma_correct (f
, &color
);
4684 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4687 /* Scale down RGB values to the visual's bits per RGB, and shift
4688 them to the right position in the pixel color. Note that the
4689 original RGB values are 16-bit values, as usual in X. */
4690 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4691 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4692 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4694 /* Assemble the pixel color. */
4695 return pr
| pg
| pb
;
4698 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4699 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4705 #ifdef HAVE_X_WINDOWS
4714 cmap
= FRAME_X_COLORMAP (f
);
4715 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4718 ++ct_colors_allocated
;
4719 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4723 p
->pixel
= color
.pixel
;
4724 p
->next
= ct_table
[i
];
4728 return FRAME_FOREGROUND_PIXEL (f
);
4733 color
= PALETTERGB (r
, g
, b
);
4735 color
= RGB_TO_ULONG (r
, g
, b
);
4736 #endif /* HAVE_NTGUI */
4737 ++ct_colors_allocated
;
4738 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4743 p
->next
= ct_table
[i
];
4745 #endif /* HAVE_X_WINDOWS */
4753 /* Look up pixel color PIXEL which is used on frame F in the color
4754 table. If not already present, allocate it. Value is PIXEL. */
4756 static unsigned long
4757 lookup_pixel_color (f
, pixel
)
4759 unsigned long pixel
;
4761 int i
= pixel
% CT_SIZE
;
4764 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4765 if (p
->pixel
== pixel
)
4774 #ifdef HAVE_X_WINDOWS
4775 cmap
= FRAME_X_COLORMAP (f
);
4776 color
.pixel
= pixel
;
4777 x_query_color (f
, &color
);
4778 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4781 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4782 color
.pixel
= pixel
;
4783 XQueryColor (NULL
, cmap
, &color
);
4784 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4786 #endif /* HAVE_X_WINDOWS */
4790 ++ct_colors_allocated
;
4792 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4797 p
->next
= ct_table
[i
];
4801 return FRAME_FOREGROUND_PIXEL (f
);
4807 /* Value is a vector of all pixel colors contained in the color table,
4808 allocated via xmalloc. Set *N to the number of colors. */
4810 static unsigned long *
4811 colors_in_color_table (n
)
4816 unsigned long *colors
;
4818 if (ct_colors_allocated
== 0)
4825 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4827 *n
= ct_colors_allocated
;
4829 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4830 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4831 colors
[j
++] = p
->pixel
;
4837 #else /* COLOR_TABLE_SUPPORT */
4839 static unsigned long
4840 lookup_rgb_color (f
, r
, g
, b
)
4844 unsigned long pixel
;
4847 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4848 gamma_correct (f
, &pixel
);
4852 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4853 #endif /* HAVE_NTGUI */
4862 #endif /* COLOR_TABLE_SUPPORT */
4865 /***********************************************************************
4867 ***********************************************************************/
4869 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4870 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4871 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4874 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4875 #endif /* HAVE_NTGUI */
4877 /* Non-zero means draw a cross on images having `:conversion
4880 int cross_disabled_images
;
4882 /* Edge detection matrices for different edge-detection
4885 static int emboss_matrix
[9] = {
4887 2, -1, 0, /* y - 1 */
4889 0, 1, -2 /* y + 1 */
4892 static int laplace_matrix
[9] = {
4894 1, 0, 0, /* y - 1 */
4896 0, 0, -1 /* y + 1 */
4899 /* Value is the intensity of the color whose red/green/blue values
4902 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4905 /* On frame F, return an array of XColor structures describing image
4906 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4907 non-zero means also fill the red/green/blue members of the XColor
4908 structures. Value is a pointer to the array of XColors structures,
4909 allocated with xmalloc; it must be freed by the caller. */
4912 x_to_xcolors (f
, img
, rgb_p
)
4919 XImagePtr_or_DC ximg
;
4923 #endif /* HAVE_NTGUI */
4925 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4928 /* Get the X image IMG->pixmap. */
4929 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4930 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4932 /* Load the image into a memory device context. */
4933 hdc
= get_frame_dc (f
);
4934 ximg
= CreateCompatibleDC (hdc
);
4935 release_frame_dc (f
, hdc
);
4936 prev
= SelectObject (ximg
, img
->pixmap
);
4937 #endif /* HAVE_NTGUI */
4939 /* Fill the `pixel' members of the XColor array. I wished there
4940 were an easy and portable way to circumvent XGetPixel. */
4942 for (y
= 0; y
< img
->height
; ++y
)
4946 #ifdef HAVE_X_WINDOWS
4947 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4948 p
->pixel
= XGetPixel (ximg
, x
, y
);
4950 x_query_colors (f
, row
, img
->width
);
4954 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4956 /* W32_TODO: palette support needed here? */
4957 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4961 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4962 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4963 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4966 p
->red
= 256 * GetRValue (p
->pixel
);
4967 p
->green
= 256 * GetGValue (p
->pixel
);
4968 p
->blue
= 256 * GetBValue (p
->pixel
);
4969 #endif /* HAVE_NTGUI */
4972 #endif /* HAVE_X_WINDOWS */
4975 Destroy_Image (ximg
, prev
);
4982 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4983 created with CreateDIBSection, with the pointer to the bit values
4984 stored in ximg->data. */
4986 static void XPutPixel (ximg
, x
, y
, color
)
4991 int width
= ximg
->info
.bmiHeader
.biWidth
;
4992 int height
= ximg
->info
.bmiHeader
.biHeight
;
4993 unsigned char * pixel
;
4995 /* True color images. */
4996 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4998 int rowbytes
= width
* 3;
4999 /* Ensure scanlines are aligned on 4 byte boundaries. */
5001 rowbytes
+= 4 - (rowbytes
% 4);
5003 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5004 /* Windows bitmaps are in BGR order. */
5005 *pixel
= GetBValue (color
);
5006 *(pixel
+ 1) = GetGValue (color
);
5007 *(pixel
+ 2) = GetRValue (color
);
5009 /* Monochrome images. */
5010 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5012 int rowbytes
= width
/ 8;
5013 /* Ensure scanlines are aligned on 4 byte boundaries. */
5015 rowbytes
+= 4 - (rowbytes
% 4);
5016 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5017 /* Filter out palette info. */
5018 if (color
& 0x00ffffff)
5019 *pixel
= *pixel
| (1 << x
% 8);
5021 *pixel
= *pixel
& ~(1 << x
% 8);
5024 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5027 #endif /* HAVE_NTGUI */
5029 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5030 RGB members are set. F is the frame on which this all happens.
5031 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5034 x_from_xcolors (f
, img
, colors
)
5044 init_color_table ();
5046 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5049 for (y
= 0; y
< img
->height
; ++y
)
5050 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5052 unsigned long pixel
;
5053 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5054 XPutPixel (oimg
, x
, y
, pixel
);
5058 x_clear_image_1 (f
, img
, 1, 0, 1);
5060 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5061 x_destroy_x_image (oimg
);
5062 img
->pixmap
= pixmap
;
5063 #ifdef COLOR_TABLE_SUPPORT
5064 img
->colors
= colors_in_color_table (&img
->ncolors
);
5065 free_color_table ();
5066 #endif /* COLOR_TABLE_SUPPORT */
5070 /* On frame F, perform edge-detection on image IMG.
5072 MATRIX is a nine-element array specifying the transformation
5073 matrix. See emboss_matrix for an example.
5075 COLOR_ADJUST is a color adjustment added to each pixel of the
5079 x_detect_edges (f
, img
, matrix
, color_adjust
)
5082 int matrix
[9], color_adjust
;
5084 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5088 for (i
= sum
= 0; i
< 9; ++i
)
5089 sum
+= abs (matrix
[i
]);
5091 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5093 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5095 for (y
= 0; y
< img
->height
; ++y
)
5097 p
= COLOR (new, 0, y
);
5098 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5099 p
= COLOR (new, img
->width
- 1, y
);
5100 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5103 for (x
= 1; x
< img
->width
- 1; ++x
)
5105 p
= COLOR (new, x
, 0);
5106 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5107 p
= COLOR (new, x
, img
->height
- 1);
5108 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5111 for (y
= 1; y
< img
->height
- 1; ++y
)
5113 p
= COLOR (new, 1, y
);
5115 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5117 int r
, g
, b
, y1
, x1
;
5120 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5121 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5124 XColor
*t
= COLOR (colors
, x1
, y1
);
5125 r
+= matrix
[i
] * t
->red
;
5126 g
+= matrix
[i
] * t
->green
;
5127 b
+= matrix
[i
] * t
->blue
;
5130 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5131 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5132 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5133 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5138 x_from_xcolors (f
, img
, new);
5144 /* Perform the pre-defined `emboss' edge-detection on image IMG
5152 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5156 /* Transform image IMG which is used on frame F with a Laplace
5157 edge-detection algorithm. The result is an image that can be used
5158 to draw disabled buttons, for example. */
5165 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5169 /* Perform edge-detection on image IMG on frame F, with specified
5170 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5172 MATRIX must be either
5174 - a list of at least 9 numbers in row-major form
5175 - a vector of at least 9 numbers
5177 COLOR_ADJUST nil means use a default; otherwise it must be a
5181 x_edge_detection (f
, img
, matrix
, color_adjust
)
5184 Lisp_Object matrix
, color_adjust
;
5192 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5193 ++i
, matrix
= XCDR (matrix
))
5194 trans
[i
] = XFLOATINT (XCAR (matrix
));
5196 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5198 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5199 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5202 if (NILP (color_adjust
))
5203 color_adjust
= make_number (0xffff / 2);
5205 if (i
== 9 && NUMBERP (color_adjust
))
5206 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5210 /* Transform image IMG on frame F so that it looks disabled. */
5213 x_disable_image (f
, img
)
5217 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5219 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5221 int n_planes
= dpyinfo
->n_planes
;
5222 #endif /* HAVE_NTGUI */
5226 /* Color (or grayscale). Convert to gray, and equalize. Just
5227 drawing such images with a stipple can look very odd, so
5228 we're using this method instead. */
5229 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5231 const int h
= 15000;
5232 const int l
= 30000;
5234 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5238 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5239 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5240 p
->red
= p
->green
= p
->blue
= i2
;
5243 x_from_xcolors (f
, img
, colors
);
5246 /* Draw a cross over the disabled image, if we must or if we
5248 if (n_planes
< 2 || cross_disabled_images
)
5251 Display
*dpy
= FRAME_X_DISPLAY (f
);
5255 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
5256 #define MaskForeground(f) PIX_MASK_DRAW
5258 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
5259 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5262 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
5263 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5264 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5265 img
->width
- 1, img
->height
- 1);
5266 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5272 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
5273 XSetForeground (dpy
, gc
, MaskForeground (f
));
5274 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5275 img
->width
- 1, img
->height
- 1);
5276 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5284 hdc
= get_frame_dc (f
);
5285 bmpdc
= CreateCompatibleDC (hdc
);
5286 release_frame_dc (f
, hdc
);
5288 prev
= SelectObject (bmpdc
, img
->pixmap
);
5290 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5291 MoveToEx (bmpdc
, 0, 0, NULL
);
5292 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5293 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5294 LineTo (bmpdc
, img
->width
- 1, 0);
5298 SelectObject (bmpdc
, img
->mask
);
5299 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5300 MoveToEx (bmpdc
, 0, 0, NULL
);
5301 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5302 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5303 LineTo (bmpdc
, img
->width
- 1, 0);
5305 SelectObject (bmpdc
, prev
);
5307 #endif /* HAVE_NTGUI */
5312 /* Build a mask for image IMG which is used on frame F. FILE is the
5313 name of an image file, for error messages. HOW determines how to
5314 determine the background color of IMG. If it is a list '(R G B)',
5315 with R, G, and B being integers >= 0, take that as the color of the
5316 background. Otherwise, determine the background color of IMG
5317 heuristically. Value is non-zero if successful. */
5320 x_build_heuristic_mask (f
, img
, how
)
5325 XImagePtr_or_DC ximg
;
5333 #endif /* HAVE_NTGUI */
5334 int x
, y
, rc
, use_img_background
;
5335 unsigned long bg
= 0;
5339 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5340 img
->mask
= NO_PIXMAP
;
5341 img
->background_transparent_valid
= 0;
5345 /* Create an image and pixmap serving as mask. */
5346 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5347 &mask_img
, &img
->mask
);
5351 /* Get the X image of IMG->pixmap. */
5352 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5353 img
->width
, img
->height
,
5356 /* Create the bit array serving as mask. */
5357 row_width
= (img
->width
+ 7) / 8;
5358 mask_img
= xmalloc (row_width
* img
->height
);
5359 bzero (mask_img
, row_width
* img
->height
);
5361 /* Create a memory device context for IMG->pixmap. */
5362 frame_dc
= get_frame_dc (f
);
5363 ximg
= CreateCompatibleDC (frame_dc
);
5364 release_frame_dc (f
, frame_dc
);
5365 prev
= SelectObject (ximg
, img
->pixmap
);
5366 #endif /* HAVE_NTGUI */
5368 /* Determine the background color of ximg. If HOW is `(R G B)'
5369 take that as color. Otherwise, use the image's background color. */
5370 use_img_background
= 1;
5376 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5378 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5382 if (i
== 3 && NILP (how
))
5384 char color_name
[30];
5385 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5388 0x00ffffff & /* Filter out palette info. */
5389 #endif /* HAVE_NTGUI */
5390 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5391 use_img_background
= 0;
5395 if (use_img_background
)
5396 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5398 /* Set all bits in mask_img to 1 whose color in ximg is different
5399 from the background color bg. */
5401 for (y
= 0; y
< img
->height
; ++y
)
5402 for (x
= 0; x
< img
->width
; ++x
)
5403 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5404 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5406 /* Fill in the background_transparent field while we have the mask handy. */
5407 image_background_transparent (img
, f
, mask_img
);
5409 /* Put mask_img into img->mask. */
5410 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5411 x_destroy_x_image (mask_img
);
5414 for (y
= 0; y
< img
->height
; ++y
)
5415 for (x
= 0; x
< img
->width
; ++x
)
5417 COLORREF p
= GetPixel (ximg
, x
, y
);
5419 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5422 /* Create the mask image. */
5423 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5425 /* Fill in the background_transparent field while we have the mask handy. */
5426 SelectObject (ximg
, img
->mask
);
5427 image_background_transparent (img
, f
, ximg
);
5429 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5431 #endif /* HAVE_NTGUI */
5433 Destroy_Image (ximg
, prev
);
5439 /***********************************************************************
5440 PBM (mono, gray, color)
5441 ***********************************************************************/
5443 static int pbm_image_p
P_ ((Lisp_Object object
));
5444 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5445 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5447 /* The symbol `pbm' identifying images of this type. */
5451 /* Indices of image specification fields in gs_format, below. */
5453 enum pbm_keyword_index
5469 /* Vector of image_keyword structures describing the format
5470 of valid user-defined image specifications. */
5472 static struct image_keyword pbm_format
[PBM_LAST
] =
5474 {":type", IMAGE_SYMBOL_VALUE
, 1},
5475 {":file", IMAGE_STRING_VALUE
, 0},
5476 {":data", IMAGE_STRING_VALUE
, 0},
5477 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5478 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5479 {":relief", IMAGE_INTEGER_VALUE
, 0},
5480 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5481 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5482 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5483 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5484 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5487 /* Structure describing the image type `pbm'. */
5489 static struct image_type pbm_type
=
5499 /* Return non-zero if OBJECT is a valid PBM image specification. */
5502 pbm_image_p (object
)
5505 struct image_keyword fmt
[PBM_LAST
];
5507 bcopy (pbm_format
, fmt
, sizeof fmt
);
5509 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5512 /* Must specify either :data or :file. */
5513 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5517 /* Scan a decimal number from *S and return it. Advance *S while
5518 reading the number. END is the end of the string. Value is -1 at
5522 pbm_scan_number (s
, end
)
5523 unsigned char **s
, *end
;
5525 int c
= 0, val
= -1;
5529 /* Skip white-space. */
5530 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5535 /* Skip comment to end of line. */
5536 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5539 else if (isdigit (c
))
5541 /* Read decimal number. */
5543 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5544 val
= 10 * val
+ c
- '0';
5556 #if 0 /* Unused. ++kfs */
5558 /* Read FILE into memory. Value is a pointer to a buffer allocated
5559 with xmalloc holding FILE's contents. Value is null if an error
5560 occurred. *SIZE is set to the size of the file. */
5563 pbm_read_file (file
, size
)
5571 if (stat (SDATA (file
), &st
) == 0
5572 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5573 && (buf
= (char *) xmalloc (st
.st_size
),
5574 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5593 #endif /* HAVE_NTGUI */
5595 /* Load PBM image IMG for use on frame F. */
5603 int width
, height
, max_color_idx
= 0;
5605 Lisp_Object file
, specified_file
;
5606 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5607 struct gcpro gcpro1
;
5608 unsigned char *contents
= NULL
;
5609 unsigned char *end
, *p
;
5612 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5616 if (STRINGP (specified_file
))
5618 file
= x_find_image_file (specified_file
);
5619 if (!STRINGP (file
))
5621 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5626 contents
= slurp_file (SDATA (file
), &size
);
5627 if (contents
== NULL
)
5629 image_error ("Error reading `%s'", file
, Qnil
);
5635 end
= contents
+ size
;
5640 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5642 end
= p
+ SBYTES (data
);
5645 /* Check magic number. */
5646 if (end
- p
< 2 || *p
++ != 'P')
5648 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5658 raw_p
= 0, type
= PBM_MONO
;
5662 raw_p
= 0, type
= PBM_GRAY
;
5666 raw_p
= 0, type
= PBM_COLOR
;
5670 raw_p
= 1, type
= PBM_MONO
;
5674 raw_p
= 1, type
= PBM_GRAY
;
5678 raw_p
= 1, type
= PBM_COLOR
;
5682 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5686 /* Read width, height, maximum color-component. Characters
5687 starting with `#' up to the end of a line are ignored. */
5688 width
= pbm_scan_number (&p
, end
);
5689 height
= pbm_scan_number (&p
, end
);
5691 if (type
!= PBM_MONO
)
5693 max_color_idx
= pbm_scan_number (&p
, end
);
5694 if (raw_p
&& max_color_idx
> 255)
5695 max_color_idx
= 255;
5698 if (!check_image_size (f
, width
, height
)
5699 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5702 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5703 &ximg
, &img
->pixmap
))
5706 /* Initialize the color hash table. */
5707 init_color_table ();
5709 if (type
== PBM_MONO
)
5712 struct image_keyword fmt
[PBM_LAST
];
5713 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5714 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5716 /* Parse the image specification. */
5717 bcopy (pbm_format
, fmt
, sizeof fmt
);
5718 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5720 /* Get foreground and background colors, maybe allocate colors. */
5721 if (fmt
[PBM_FOREGROUND
].count
5722 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5723 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5724 if (fmt
[PBM_BACKGROUND
].count
5725 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5727 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5728 img
->background
= bg
;
5729 img
->background_valid
= 1;
5732 for (y
= 0; y
< height
; ++y
)
5733 for (x
= 0; x
< width
; ++x
)
5743 g
= pbm_scan_number (&p
, end
);
5745 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5750 for (y
= 0; y
< height
; ++y
)
5751 for (x
= 0; x
< width
; ++x
)
5755 if (type
== PBM_GRAY
)
5756 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5765 r
= pbm_scan_number (&p
, end
);
5766 g
= pbm_scan_number (&p
, end
);
5767 b
= pbm_scan_number (&p
, end
);
5770 if (r
< 0 || g
< 0 || b
< 0)
5772 x_destroy_x_image (ximg
);
5773 image_error ("Invalid pixel value in image `%s'",
5778 /* RGB values are now in the range 0..max_color_idx.
5779 Scale this to the range 0..0xffff supported by X. */
5780 r
= (double) r
* 65535 / max_color_idx
;
5781 g
= (double) g
* 65535 / max_color_idx
;
5782 b
= (double) b
* 65535 / max_color_idx
;
5783 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5787 #ifdef COLOR_TABLE_SUPPORT
5788 /* Store in IMG->colors the colors allocated for the image, and
5789 free the color table. */
5790 img
->colors
= colors_in_color_table (&img
->ncolors
);
5791 free_color_table ();
5792 #endif /* COLOR_TABLE_SUPPORT */
5795 img
->height
= height
;
5797 /* Maybe fill in the background field while we have ximg handy. */
5799 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5800 /* Casting avoids a GCC warning. */
5801 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5803 /* Put the image into a pixmap. */
5804 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5805 x_destroy_x_image (ximg
);
5807 /* X and W32 versions did it here, MAC version above. ++kfs
5809 img->height = height; */
5817 /***********************************************************************
5819 ***********************************************************************/
5821 #if defined (HAVE_PNG) || defined (MAC_OS)
5823 /* Function prototypes. */
5825 static int png_image_p
P_ ((Lisp_Object object
));
5826 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5828 /* The symbol `png' identifying images of this type. */
5832 /* Indices of image specification fields in png_format, below. */
5834 enum png_keyword_index
5849 /* Vector of image_keyword structures describing the format
5850 of valid user-defined image specifications. */
5852 static struct image_keyword png_format
[PNG_LAST
] =
5854 {":type", IMAGE_SYMBOL_VALUE
, 1},
5855 {":data", IMAGE_STRING_VALUE
, 0},
5856 {":file", IMAGE_STRING_VALUE
, 0},
5857 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5858 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5859 {":relief", IMAGE_INTEGER_VALUE
, 0},
5860 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5861 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5862 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5863 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5866 /* Structure describing the image type `png'. */
5868 static struct image_type png_type
=
5877 /* Return non-zero if OBJECT is a valid PNG image specification. */
5880 png_image_p (object
)
5883 struct image_keyword fmt
[PNG_LAST
];
5884 bcopy (png_format
, fmt
, sizeof fmt
);
5886 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5889 /* Must specify either the :data or :file keyword. */
5890 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5893 #endif /* HAVE_PNG || MAC_OS */
5898 #if defined HAVE_LIBPNG_PNG_H
5899 # include <libpng/png.h>
5905 /* PNG library details. */
5907 DEF_IMGLIB_FN (png_get_io_ptr
);
5908 DEF_IMGLIB_FN (png_check_sig
);
5909 DEF_IMGLIB_FN (png_create_read_struct
);
5910 DEF_IMGLIB_FN (png_create_info_struct
);
5911 DEF_IMGLIB_FN (png_destroy_read_struct
);
5912 DEF_IMGLIB_FN (png_set_read_fn
);
5913 DEF_IMGLIB_FN (png_set_sig_bytes
);
5914 DEF_IMGLIB_FN (png_read_info
);
5915 DEF_IMGLIB_FN (png_get_IHDR
);
5916 DEF_IMGLIB_FN (png_get_valid
);
5917 DEF_IMGLIB_FN (png_set_strip_16
);
5918 DEF_IMGLIB_FN (png_set_expand
);
5919 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5920 DEF_IMGLIB_FN (png_set_background
);
5921 DEF_IMGLIB_FN (png_get_bKGD
);
5922 DEF_IMGLIB_FN (png_read_update_info
);
5923 DEF_IMGLIB_FN (png_get_channels
);
5924 DEF_IMGLIB_FN (png_get_rowbytes
);
5925 DEF_IMGLIB_FN (png_read_image
);
5926 DEF_IMGLIB_FN (png_read_end
);
5927 DEF_IMGLIB_FN (png_error
);
5930 init_png_functions (Lisp_Object libraries
)
5934 /* Try loading libpng under probable names. */
5935 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5938 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5939 LOAD_IMGLIB_FN (library
, png_check_sig
);
5940 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5941 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5942 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5943 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5944 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5945 LOAD_IMGLIB_FN (library
, png_read_info
);
5946 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5947 LOAD_IMGLIB_FN (library
, png_get_valid
);
5948 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5949 LOAD_IMGLIB_FN (library
, png_set_expand
);
5950 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5951 LOAD_IMGLIB_FN (library
, png_set_background
);
5952 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5953 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5954 LOAD_IMGLIB_FN (library
, png_get_channels
);
5955 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5956 LOAD_IMGLIB_FN (library
, png_read_image
);
5957 LOAD_IMGLIB_FN (library
, png_read_end
);
5958 LOAD_IMGLIB_FN (library
, png_error
);
5963 #define fn_png_get_io_ptr png_get_io_ptr
5964 #define fn_png_check_sig png_check_sig
5965 #define fn_png_create_read_struct png_create_read_struct
5966 #define fn_png_create_info_struct png_create_info_struct
5967 #define fn_png_destroy_read_struct png_destroy_read_struct
5968 #define fn_png_set_read_fn png_set_read_fn
5969 #define fn_png_set_sig_bytes png_set_sig_bytes
5970 #define fn_png_read_info png_read_info
5971 #define fn_png_get_IHDR png_get_IHDR
5972 #define fn_png_get_valid png_get_valid
5973 #define fn_png_set_strip_16 png_set_strip_16
5974 #define fn_png_set_expand png_set_expand
5975 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5976 #define fn_png_set_background png_set_background
5977 #define fn_png_get_bKGD png_get_bKGD
5978 #define fn_png_read_update_info png_read_update_info
5979 #define fn_png_get_channels png_get_channels
5980 #define fn_png_get_rowbytes png_get_rowbytes
5981 #define fn_png_read_image png_read_image
5982 #define fn_png_read_end png_read_end
5983 #define fn_png_error png_error
5985 #endif /* HAVE_NTGUI */
5987 /* Error and warning handlers installed when the PNG library
5991 my_png_error (png_ptr
, msg
)
5992 png_struct
*png_ptr
;
5995 xassert (png_ptr
!= NULL
);
5996 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5997 longjmp (png_ptr
->jmpbuf
, 1);
6002 my_png_warning (png_ptr
, msg
)
6003 png_struct
*png_ptr
;
6006 xassert (png_ptr
!= NULL
);
6007 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6010 /* Memory source for PNG decoding. */
6012 struct png_memory_storage
6014 unsigned char *bytes
; /* The data */
6015 size_t len
; /* How big is it? */
6016 int index
; /* Where are we? */
6020 /* Function set as reader function when reading PNG image from memory.
6021 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6022 bytes from the input to DATA. */
6025 png_read_from_memory (png_ptr
, data
, length
)
6026 png_structp png_ptr
;
6030 struct png_memory_storage
*tbr
6031 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6033 if (length
> tbr
->len
- tbr
->index
)
6034 fn_png_error (png_ptr
, "Read error");
6036 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6037 tbr
->index
= tbr
->index
+ length
;
6041 /* Function set as reader function when reading PNG image from a file.
6042 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6043 bytes from the input to DATA. */
6046 png_read_from_file (png_ptr
, data
, length
)
6047 png_structp png_ptr
;
6051 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6053 if (fread (data
, 1, length
, fp
) < length
)
6054 fn_png_error (png_ptr
, "Read error");
6058 /* Load PNG image IMG for use on frame F. Value is non-zero if
6066 Lisp_Object file
, specified_file
;
6067 Lisp_Object specified_data
;
6069 XImagePtr ximg
, mask_img
= NULL
;
6070 struct gcpro gcpro1
;
6071 png_struct
*png_ptr
= NULL
;
6072 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6073 FILE *volatile fp
= NULL
;
6075 png_byte
* volatile pixels
= NULL
;
6076 png_byte
** volatile rows
= NULL
;
6077 png_uint_32 width
, height
;
6078 int bit_depth
, color_type
, interlace_type
;
6080 png_uint_32 row_bytes
;
6082 double screen_gamma
;
6083 struct png_memory_storage tbr
; /* Data to be read */
6085 /* Find out what file to load. */
6086 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6087 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6091 if (NILP (specified_data
))
6093 file
= x_find_image_file (specified_file
);
6094 if (!STRINGP (file
))
6096 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6101 /* Open the image file. */
6102 fp
= fopen (SDATA (file
), "rb");
6105 image_error ("Cannot open image file `%s'", file
, Qnil
);
6110 /* Check PNG signature. */
6111 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6112 || !fn_png_check_sig (sig
, sizeof sig
))
6114 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6122 /* Read from memory. */
6123 tbr
.bytes
= SDATA (specified_data
);
6124 tbr
.len
= SBYTES (specified_data
);
6127 /* Check PNG signature. */
6128 if (tbr
.len
< sizeof sig
6129 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6131 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6136 /* Need to skip past the signature. */
6137 tbr
.bytes
+= sizeof (sig
);
6140 /* Initialize read and info structs for PNG lib. Casting return
6141 value avoids a GCC warning on W32. */
6142 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6147 if (fp
) fclose (fp
);
6152 /* Casting return value avoids a GCC warning on W32. */
6153 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6156 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6157 if (fp
) fclose (fp
);
6162 /* Casting return value avoids a GCC warning on W32. */
6163 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6166 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6167 if (fp
) fclose (fp
);
6172 /* Set error jump-back. We come back here when the PNG library
6173 detects an error. */
6174 if (setjmp (png_ptr
->jmpbuf
))
6178 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6181 if (fp
) fclose (fp
);
6186 /* Read image info. */
6187 if (!NILP (specified_data
))
6188 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6190 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6192 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6193 fn_png_read_info (png_ptr
, info_ptr
);
6194 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6195 &interlace_type
, NULL
, NULL
);
6197 if (!check_image_size (f
, width
, height
))
6200 /* If image contains simply transparency data, we prefer to
6201 construct a clipping mask. */
6202 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6207 /* This function is easier to write if we only have to handle
6208 one data format: RGB or RGBA with 8 bits per channel. Let's
6209 transform other formats into that format. */
6211 /* Strip more than 8 bits per channel. */
6212 if (bit_depth
== 16)
6213 fn_png_set_strip_16 (png_ptr
);
6215 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6217 fn_png_set_expand (png_ptr
);
6219 /* Convert grayscale images to RGB. */
6220 if (color_type
== PNG_COLOR_TYPE_GRAY
6221 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6222 fn_png_set_gray_to_rgb (png_ptr
);
6224 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
6226 #if 0 /* Avoid double gamma correction for PNG images. */
6227 { /* Tell the PNG lib to handle gamma correction for us. */
6230 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6231 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
6232 /* The libpng documentation says this is right in this case. */
6233 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6236 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
6237 /* Image contains gamma information. */
6238 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
6240 /* Use the standard default for the image gamma. */
6241 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6245 /* Handle alpha channel by combining the image with a background
6246 color. Do this only if a real alpha channel is supplied. For
6247 simple transparency, we prefer a clipping mask. */
6250 png_color_16
*image_bg
;
6251 Lisp_Object specified_bg
6252 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6254 if (STRINGP (specified_bg
))
6255 /* The user specified `:background', use that. */
6257 /* W32 version incorrectly used COLORREF here!! ++kfs */
6259 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6261 png_color_16 user_bg
;
6263 bzero (&user_bg
, sizeof user_bg
);
6264 user_bg
.red
= color
.red
>> 8;
6265 user_bg
.green
= color
.green
>> 8;
6266 user_bg
.blue
= color
.blue
>> 8;
6268 fn_png_set_background (png_ptr
, &user_bg
,
6269 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6272 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
6273 /* Image contains a background color with which to
6274 combine the image. */
6275 fn_png_set_background (png_ptr
, image_bg
,
6276 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
6279 /* Image does not contain a background color with which
6280 to combine the image data via an alpha channel. Use
6281 the frame's background instead. */
6282 #ifdef HAVE_X_WINDOWS
6284 png_color_16 frame_background
;
6286 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6287 x_query_color (f
, &color
);
6289 bzero (&frame_background
, sizeof frame_background
);
6290 frame_background
.red
= color
.red
>> 8;
6291 frame_background
.green
= color
.green
>> 8;
6292 frame_background
.blue
= color
.blue
>> 8;
6293 #endif /* HAVE_X_WINDOWS */
6297 png_color_16 frame_background
;
6298 color
= FRAME_BACKGROUND_PIXEL (f
);
6299 #if 0 /* W32 TODO : Colormap support. */
6300 x_query_color (f
, &color
);
6302 bzero (&frame_background
, sizeof frame_background
);
6303 frame_background
.red
= GetRValue (color
);
6304 frame_background
.green
= GetGValue (color
);
6305 frame_background
.blue
= GetBValue (color
);
6306 #endif /* HAVE_NTGUI */
6309 unsigned long color
;
6310 png_color_16 frame_background
;
6311 color
= FRAME_BACKGROUND_PIXEL (f
);
6312 #if 0 /* MAC/W32 TODO : Colormap support. */
6313 x_query_color (f
, &color
);
6315 bzero (&frame_background
, sizeof frame_background
);
6316 frame_background
.red
= RED_FROM_ULONG (color
);
6317 frame_background
.green
= GREEN_FROM_ULONG (color
);
6318 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6321 fn_png_set_background (png_ptr
, &frame_background
,
6322 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6326 /* Update info structure. */
6327 fn_png_read_update_info (png_ptr
, info_ptr
);
6329 /* Get number of channels. Valid values are 1 for grayscale images
6330 and images with a palette, 2 for grayscale images with transparency
6331 information (alpha channel), 3 for RGB images, and 4 for RGB
6332 images with alpha channel, i.e. RGBA. If conversions above were
6333 sufficient we should only have 3 or 4 channels here. */
6334 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6335 xassert (channels
== 3 || channels
== 4);
6337 /* Number of bytes needed for one row of the image. */
6338 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6340 /* Allocate memory for the image. */
6341 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6342 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6343 for (i
= 0; i
< height
; ++i
)
6344 rows
[i
] = pixels
+ i
* row_bytes
;
6346 /* Read the entire image. */
6347 fn_png_read_image (png_ptr
, rows
);
6348 fn_png_read_end (png_ptr
, info_ptr
);
6355 /* Create the X image and pixmap. */
6356 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6360 /* Create an image and pixmap serving as mask if the PNG image
6361 contains an alpha channel. */
6364 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6365 &mask_img
, &img
->mask
))
6367 x_destroy_x_image (ximg
);
6368 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6369 img
->pixmap
= NO_PIXMAP
;
6373 /* Fill the X image and mask from PNG data. */
6374 init_color_table ();
6376 for (y
= 0; y
< height
; ++y
)
6378 png_byte
*p
= rows
[y
];
6380 for (x
= 0; x
< width
; ++x
)
6387 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6388 /* An alpha channel, aka mask channel, associates variable
6389 transparency with an image. Where other image formats
6390 support binary transparency---fully transparent or fully
6391 opaque---PNG allows up to 254 levels of partial transparency.
6392 The PNG library implements partial transparency by combining
6393 the image with a specified background color.
6395 I'm not sure how to handle this here nicely: because the
6396 background on which the image is displayed may change, for
6397 real alpha channel support, it would be necessary to create
6398 a new image for each possible background.
6400 What I'm doing now is that a mask is created if we have
6401 boolean transparency information. Otherwise I'm using
6402 the frame's background color to combine the image with. */
6407 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6413 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6414 /* Set IMG's background color from the PNG image, unless the user
6418 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6420 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6421 img
->background_valid
= 1;
6425 #ifdef COLOR_TABLE_SUPPORT
6426 /* Remember colors allocated for this image. */
6427 img
->colors
= colors_in_color_table (&img
->ncolors
);
6428 free_color_table ();
6429 #endif /* COLOR_TABLE_SUPPORT */
6432 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6437 img
->height
= height
;
6439 /* Maybe fill in the background field while we have ximg handy.
6440 Casting avoids a GCC warning. */
6441 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6443 /* Put the image into the pixmap, then free the X image and its buffer. */
6444 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6445 x_destroy_x_image (ximg
);
6447 /* Same for the mask. */
6450 /* Fill in the background_transparent field while we have the
6451 mask handy. Casting avoids a GCC warning. */
6452 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6454 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6455 x_destroy_x_image (mask_img
);
6462 #else /* HAVE_PNG */
6471 if (MyCGImageCreateWithPNGDataProvider
)
6472 return image_load_quartz2d (f
, img
, 1);
6475 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6479 #endif /* !HAVE_PNG */
6483 /***********************************************************************
6485 ***********************************************************************/
6487 #if defined (HAVE_JPEG) || defined (MAC_OS)
6489 static int jpeg_image_p
P_ ((Lisp_Object object
));
6490 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6492 /* The symbol `jpeg' identifying images of this type. */
6496 /* Indices of image specification fields in gs_format, below. */
6498 enum jpeg_keyword_index
6507 JPEG_HEURISTIC_MASK
,
6513 /* Vector of image_keyword structures describing the format
6514 of valid user-defined image specifications. */
6516 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6518 {":type", IMAGE_SYMBOL_VALUE
, 1},
6519 {":data", IMAGE_STRING_VALUE
, 0},
6520 {":file", IMAGE_STRING_VALUE
, 0},
6521 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6522 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6523 {":relief", IMAGE_INTEGER_VALUE
, 0},
6524 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6525 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6526 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6527 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6530 /* Structure describing the image type `jpeg'. */
6532 static struct image_type jpeg_type
=
6541 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6544 jpeg_image_p (object
)
6547 struct image_keyword fmt
[JPEG_LAST
];
6549 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6551 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6554 /* Must specify either the :data or :file keyword. */
6555 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6558 #endif /* HAVE_JPEG || MAC_OS */
6562 /* Work around a warning about HAVE_STDLIB_H being redefined in
6564 #ifdef HAVE_STDLIB_H
6565 #define HAVE_STDLIB_H_1
6566 #undef HAVE_STDLIB_H
6567 #endif /* HAVE_STLIB_H */
6569 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6570 /* In older releases of the jpeg library, jpeglib.h will define boolean
6571 differently depending on __WIN32__, so make sure it is defined. */
6575 #include <jpeglib.h>
6579 #ifdef HAVE_STLIB_H_1
6580 #define HAVE_STDLIB_H 1
6585 /* JPEG library details. */
6586 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6587 DEF_IMGLIB_FN (jpeg_start_decompress
);
6588 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6589 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6590 DEF_IMGLIB_FN (jpeg_read_header
);
6591 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6592 DEF_IMGLIB_FN (jpeg_std_error
);
6593 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6596 init_jpeg_functions (Lisp_Object libraries
)
6600 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6603 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6604 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6605 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6606 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6607 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6608 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6609 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6610 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6614 /* Wrapper since we can't directly assign the function pointer
6615 to another function pointer that was declared more completely easily. */
6617 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
6618 j_decompress_ptr cinfo
;
6621 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6626 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6627 #define fn_jpeg_start_decompress jpeg_start_decompress
6628 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6629 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6630 #define fn_jpeg_read_header jpeg_read_header
6631 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6632 #define fn_jpeg_std_error jpeg_std_error
6633 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6635 #endif /* HAVE_NTGUI */
6637 struct my_jpeg_error_mgr
6639 struct jpeg_error_mgr pub
;
6640 jmp_buf setjmp_buffer
;
6645 my_error_exit (cinfo
)
6648 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6649 longjmp (mgr
->setjmp_buffer
, 1);
6653 /* Init source method for JPEG data source manager. Called by
6654 jpeg_read_header() before any data is actually read. See
6655 libjpeg.doc from the JPEG lib distribution. */
6658 our_common_init_source (cinfo
)
6659 j_decompress_ptr cinfo
;
6664 /* Method to terminate data source. Called by
6665 jpeg_finish_decompress() after all data has been processed. */
6668 our_common_term_source (cinfo
)
6669 j_decompress_ptr cinfo
;
6674 /* Fill input buffer method for JPEG data source manager. Called
6675 whenever more data is needed. We read the whole image in one step,
6676 so this only adds a fake end of input marker at the end. */
6679 our_memory_fill_input_buffer (cinfo
)
6680 j_decompress_ptr cinfo
;
6682 /* Insert a fake EOI marker. */
6683 struct jpeg_source_mgr
*src
= cinfo
->src
;
6684 static JOCTET buffer
[2];
6686 buffer
[0] = (JOCTET
) 0xFF;
6687 buffer
[1] = (JOCTET
) JPEG_EOI
;
6689 src
->next_input_byte
= buffer
;
6690 src
->bytes_in_buffer
= 2;
6695 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6696 is the JPEG data source manager. */
6699 our_memory_skip_input_data (cinfo
, num_bytes
)
6700 j_decompress_ptr cinfo
;
6703 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6707 if (num_bytes
> src
->bytes_in_buffer
)
6708 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6710 src
->bytes_in_buffer
-= num_bytes
;
6711 src
->next_input_byte
+= num_bytes
;
6716 /* Set up the JPEG lib for reading an image from DATA which contains
6717 LEN bytes. CINFO is the decompression info structure created for
6718 reading the image. */
6721 jpeg_memory_src (cinfo
, data
, len
)
6722 j_decompress_ptr cinfo
;
6726 struct jpeg_source_mgr
*src
;
6728 if (cinfo
->src
== NULL
)
6730 /* First time for this JPEG object? */
6731 cinfo
->src
= (struct jpeg_source_mgr
*)
6732 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6733 sizeof (struct jpeg_source_mgr
));
6734 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6735 src
->next_input_byte
= data
;
6738 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6739 src
->init_source
= our_common_init_source
;
6740 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6741 src
->skip_input_data
= our_memory_skip_input_data
;
6742 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6743 src
->term_source
= our_common_term_source
;
6744 src
->bytes_in_buffer
= len
;
6745 src
->next_input_byte
= data
;
6749 struct jpeg_stdio_mgr
6751 struct jpeg_source_mgr mgr
;
6758 /* Size of buffer to read JPEG from file.
6759 Not too big, as we want to use alloc_small. */
6760 #define JPEG_STDIO_BUFFER_SIZE 8192
6763 /* Fill input buffer method for JPEG data source manager. Called
6764 whenever more data is needed. The data is read from a FILE *. */
6767 our_stdio_fill_input_buffer (cinfo
)
6768 j_decompress_ptr cinfo
;
6770 struct jpeg_stdio_mgr
*src
;
6772 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6777 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6779 src
->mgr
.bytes_in_buffer
= bytes
;
6782 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6784 src
->buffer
[0] = (JOCTET
) 0xFF;
6785 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6786 src
->mgr
.bytes_in_buffer
= 2;
6788 src
->mgr
.next_input_byte
= src
->buffer
;
6795 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6796 is the JPEG data source manager. */
6799 our_stdio_skip_input_data (cinfo
, num_bytes
)
6800 j_decompress_ptr cinfo
;
6803 struct jpeg_stdio_mgr
*src
;
6804 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6806 while (num_bytes
> 0 && !src
->finished
)
6808 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6810 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6811 src
->mgr
.next_input_byte
+= num_bytes
;
6816 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6817 src
->mgr
.bytes_in_buffer
= 0;
6818 src
->mgr
.next_input_byte
= NULL
;
6820 our_stdio_fill_input_buffer (cinfo
);
6826 /* Set up the JPEG lib for reading an image from a FILE *.
6827 CINFO is the decompression info structure created for
6828 reading the image. */
6831 jpeg_file_src (cinfo
, fp
)
6832 j_decompress_ptr cinfo
;
6835 struct jpeg_stdio_mgr
*src
;
6837 if (cinfo
->src
!= NULL
)
6838 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6841 /* First time for this JPEG object? */
6842 cinfo
->src
= (struct jpeg_source_mgr
*)
6843 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6844 sizeof (struct jpeg_stdio_mgr
));
6845 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6846 src
->buffer
= (JOCTET
*)
6847 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6848 JPEG_STDIO_BUFFER_SIZE
);
6853 src
->mgr
.init_source
= our_common_init_source
;
6854 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6855 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6856 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6857 src
->mgr
.term_source
= our_common_term_source
;
6858 src
->mgr
.bytes_in_buffer
= 0;
6859 src
->mgr
.next_input_byte
= NULL
;
6863 /* Load image IMG for use on frame F. Patterned after example.c
6864 from the JPEG lib. */
6871 struct jpeg_decompress_struct cinfo
;
6872 struct my_jpeg_error_mgr mgr
;
6873 Lisp_Object file
, specified_file
;
6874 Lisp_Object specified_data
;
6875 FILE * volatile fp
= NULL
;
6877 int row_stride
, x
, y
;
6878 XImagePtr ximg
= NULL
;
6880 unsigned long *colors
;
6882 struct gcpro gcpro1
;
6884 /* Open the JPEG file. */
6885 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6886 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6890 if (NILP (specified_data
))
6892 file
= x_find_image_file (specified_file
);
6893 if (!STRINGP (file
))
6895 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6900 fp
= fopen (SDATA (file
), "rb");
6903 image_error ("Cannot open `%s'", file
, Qnil
);
6909 /* Customize libjpeg's error handling to call my_error_exit when an
6910 error is detected. This function will perform a longjmp.
6911 Casting return value avoids a GCC warning on W32. */
6912 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
6913 mgr
.pub
.error_exit
= my_error_exit
;
6915 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6919 /* Called from my_error_exit. Display a JPEG error. */
6920 char buffer
[JMSG_LENGTH_MAX
];
6921 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6922 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6923 build_string (buffer
));
6926 /* Close the input file and destroy the JPEG object. */
6928 fclose ((FILE *) fp
);
6929 fn_jpeg_destroy_decompress (&cinfo
);
6931 /* If we already have an XImage, free that. */
6932 x_destroy_x_image (ximg
);
6934 /* Free pixmap and colors. */
6935 x_clear_image (f
, img
);
6941 /* Create the JPEG decompression object. Let it read from fp.
6942 Read the JPEG image header. */
6943 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6945 if (NILP (specified_data
))
6946 jpeg_file_src (&cinfo
, (FILE *) fp
);
6948 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6949 SBYTES (specified_data
));
6951 fn_jpeg_read_header (&cinfo
, 1);
6953 /* Customize decompression so that color quantization will be used.
6954 Start decompression. */
6955 cinfo
.quantize_colors
= 1;
6956 fn_jpeg_start_decompress (&cinfo
);
6957 width
= img
->width
= cinfo
.output_width
;
6958 height
= img
->height
= cinfo
.output_height
;
6960 if (!check_image_size (f
, width
, height
))
6962 image_error ("Invalid image size", Qnil
, Qnil
);
6963 longjmp (mgr
.setjmp_buffer
, 2);
6966 /* Create X image and pixmap. */
6967 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6968 longjmp (mgr
.setjmp_buffer
, 2);
6970 /* Allocate colors. When color quantization is used,
6971 cinfo.actual_number_of_colors has been set with the number of
6972 colors generated, and cinfo.colormap is a two-dimensional array
6973 of color indices in the range 0..cinfo.actual_number_of_colors.
6974 No more than 255 colors will be generated. */
6978 if (cinfo
.out_color_components
> 2)
6979 ir
= 0, ig
= 1, ib
= 2;
6980 else if (cinfo
.out_color_components
> 1)
6981 ir
= 0, ig
= 1, ib
= 0;
6983 ir
= 0, ig
= 0, ib
= 0;
6985 /* Use the color table mechanism because it handles colors that
6986 cannot be allocated nicely. Such colors will be replaced with
6987 a default color, and we don't have to care about which colors
6988 can be freed safely, and which can't. */
6989 init_color_table ();
6990 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6993 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6995 /* Multiply RGB values with 255 because X expects RGB values
6996 in the range 0..0xffff. */
6997 int r
= cinfo
.colormap
[ir
][i
] << 8;
6998 int g
= cinfo
.colormap
[ig
][i
] << 8;
6999 int b
= cinfo
.colormap
[ib
][i
] << 8;
7000 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7003 #ifdef COLOR_TABLE_SUPPORT
7004 /* Remember those colors actually allocated. */
7005 img
->colors
= colors_in_color_table (&img
->ncolors
);
7006 free_color_table ();
7007 #endif /* COLOR_TABLE_SUPPORT */
7011 row_stride
= width
* cinfo
.output_components
;
7012 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7014 for (y
= 0; y
< height
; ++y
)
7016 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7017 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7018 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7022 fn_jpeg_finish_decompress (&cinfo
);
7023 fn_jpeg_destroy_decompress (&cinfo
);
7025 fclose ((FILE *) fp
);
7027 /* Maybe fill in the background field while we have ximg handy. */
7028 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7029 /* Casting avoids a GCC warning. */
7030 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7032 /* Put the image into the pixmap. */
7033 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7034 x_destroy_x_image (ximg
);
7039 #else /* HAVE_JPEG */
7048 return image_load_quartz2d (f
, img
, 0);
7050 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7055 #endif /* !HAVE_JPEG */
7059 /***********************************************************************
7061 ***********************************************************************/
7063 #if defined (HAVE_TIFF) || defined (MAC_OS)
7065 static int tiff_image_p
P_ ((Lisp_Object object
));
7066 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7068 /* The symbol `tiff' identifying images of this type. */
7072 /* Indices of image specification fields in tiff_format, below. */
7074 enum tiff_keyword_index
7083 TIFF_HEURISTIC_MASK
,
7089 /* Vector of image_keyword structures describing the format
7090 of valid user-defined image specifications. */
7092 static struct image_keyword tiff_format
[TIFF_LAST
] =
7094 {":type", IMAGE_SYMBOL_VALUE
, 1},
7095 {":data", IMAGE_STRING_VALUE
, 0},
7096 {":file", IMAGE_STRING_VALUE
, 0},
7097 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7098 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7099 {":relief", IMAGE_INTEGER_VALUE
, 0},
7100 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7101 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7102 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7103 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7106 /* Structure describing the image type `tiff'. */
7108 static struct image_type tiff_type
=
7117 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7120 tiff_image_p (object
)
7123 struct image_keyword fmt
[TIFF_LAST
];
7124 bcopy (tiff_format
, fmt
, sizeof fmt
);
7126 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7129 /* Must specify either the :data or :file keyword. */
7130 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7133 #endif /* HAVE_TIFF || MAC_OS */
7141 /* TIFF library details. */
7142 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7143 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7144 DEF_IMGLIB_FN (TIFFOpen
);
7145 DEF_IMGLIB_FN (TIFFClientOpen
);
7146 DEF_IMGLIB_FN (TIFFGetField
);
7147 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7148 DEF_IMGLIB_FN (TIFFClose
);
7151 init_tiff_functions (Lisp_Object libraries
)
7155 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7158 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7159 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7160 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7161 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7162 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7163 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7164 LOAD_IMGLIB_FN (library
, TIFFClose
);
7170 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7171 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7172 #define fn_TIFFOpen TIFFOpen
7173 #define fn_TIFFClientOpen TIFFClientOpen
7174 #define fn_TIFFGetField TIFFGetField
7175 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7176 #define fn_TIFFClose TIFFClose
7178 #endif /* HAVE_NTGUI */
7181 /* Reading from a memory buffer for TIFF images Based on the PNG
7182 memory source, but we have to provide a lot of extra functions.
7185 We really only need to implement read and seek, but I am not
7186 convinced that the TIFF library is smart enough not to destroy
7187 itself if we only hand it the function pointers we need to
7192 unsigned char *bytes
;
7199 tiff_read_from_memory (data
, buf
, size
)
7204 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7206 if (size
> src
->len
- src
->index
)
7208 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7214 tiff_write_from_memory (data
, buf
, size
)
7223 tiff_seek_in_memory (data
, off
, whence
)
7228 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7233 case SEEK_SET
: /* Go from beginning of source. */
7237 case SEEK_END
: /* Go from end of source. */
7238 idx
= src
->len
+ off
;
7241 case SEEK_CUR
: /* Go from current position. */
7242 idx
= src
->index
+ off
;
7245 default: /* Invalid `whence'. */
7249 if (idx
> src
->len
|| idx
< 0)
7257 tiff_close_memory (data
)
7265 tiff_mmap_memory (data
, pbase
, psize
)
7270 /* It is already _IN_ memory. */
7275 tiff_unmap_memory (data
, base
, size
)
7280 /* We don't need to do this. */
7284 tiff_size_of_memory (data
)
7287 return ((tiff_memory_source
*) data
)->len
;
7292 tiff_error_handler (title
, format
, ap
)
7293 const char *title
, *format
;
7299 len
= sprintf (buf
, "TIFF error: %s ", title
);
7300 vsprintf (buf
+ len
, format
, ap
);
7301 add_to_log (buf
, Qnil
, Qnil
);
7306 tiff_warning_handler (title
, format
, ap
)
7307 const char *title
, *format
;
7313 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7314 vsprintf (buf
+ len
, format
, ap
);
7315 add_to_log (buf
, Qnil
, Qnil
);
7319 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7327 Lisp_Object file
, specified_file
;
7328 Lisp_Object specified_data
;
7330 int width
, height
, x
, y
;
7334 struct gcpro gcpro1
;
7335 tiff_memory_source memsrc
;
7337 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7338 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7342 fn_TIFFSetErrorHandler (tiff_error_handler
);
7343 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7345 if (NILP (specified_data
))
7347 /* Read from a file */
7348 file
= x_find_image_file (specified_file
);
7349 if (!STRINGP (file
))
7351 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7356 /* Try to open the image file. Casting return value avoids a
7357 GCC warning on W32. */
7358 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7361 image_error ("Cannot open `%s'", file
, Qnil
);
7368 /* Memory source! */
7369 memsrc
.bytes
= SDATA (specified_data
);
7370 memsrc
.len
= SBYTES (specified_data
);
7373 /* Casting return value avoids a GCC warning on W32. */
7374 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7375 (TIFFReadWriteProc
) tiff_read_from_memory
,
7376 (TIFFReadWriteProc
) tiff_write_from_memory
,
7377 tiff_seek_in_memory
,
7379 tiff_size_of_memory
,
7385 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7391 /* Get width and height of the image, and allocate a raster buffer
7392 of width x height 32-bit values. */
7393 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7394 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7396 if (!check_image_size (f
, width
, height
))
7398 image_error ("Invalid image size", Qnil
, Qnil
);
7403 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7405 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7406 fn_TIFFClose (tiff
);
7409 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7415 /* Create the X image and pixmap. */
7416 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7423 /* Initialize the color table. */
7424 init_color_table ();
7426 /* Process the pixel raster. Origin is in the lower-left corner. */
7427 for (y
= 0; y
< height
; ++y
)
7429 uint32
*row
= buf
+ y
* width
;
7431 for (x
= 0; x
< width
; ++x
)
7433 uint32 abgr
= row
[x
];
7434 int r
= TIFFGetR (abgr
) << 8;
7435 int g
= TIFFGetG (abgr
) << 8;
7436 int b
= TIFFGetB (abgr
) << 8;
7437 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7441 #ifdef COLOR_TABLE_SUPPORT
7442 /* Remember the colors allocated for the image. Free the color table. */
7443 img
->colors
= colors_in_color_table (&img
->ncolors
);
7444 free_color_table ();
7445 #endif /* COLOR_TABLE_SUPPORT */
7448 img
->height
= height
;
7450 /* Maybe fill in the background field while we have ximg handy. */
7451 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7452 /* Casting avoids a GCC warning on W32. */
7453 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7455 /* Put the image into the pixmap, then free the X image and its buffer. */
7456 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7457 x_destroy_x_image (ximg
);
7464 #else /* HAVE_TIFF */
7472 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7476 #endif /* !HAVE_TIFF */
7480 /***********************************************************************
7482 ***********************************************************************/
7484 #if defined (HAVE_GIF) || defined (MAC_OS)
7486 static int gif_image_p
P_ ((Lisp_Object object
));
7487 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7488 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7490 /* The symbol `gif' identifying images of this type. */
7494 /* Indices of image specification fields in gif_format, below. */
7496 enum gif_keyword_index
7512 /* Vector of image_keyword structures describing the format
7513 of valid user-defined image specifications. */
7515 static struct image_keyword gif_format
[GIF_LAST
] =
7517 {":type", IMAGE_SYMBOL_VALUE
, 1},
7518 {":data", IMAGE_STRING_VALUE
, 0},
7519 {":file", IMAGE_STRING_VALUE
, 0},
7520 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7521 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7522 {":relief", IMAGE_INTEGER_VALUE
, 0},
7523 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7524 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7525 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7526 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7527 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7530 /* Structure describing the image type `gif'. */
7532 static struct image_type gif_type
=
7541 /* Free X resources of GIF image IMG which is used on frame F. */
7544 gif_clear_image (f
, img
)
7548 /* IMG->data.ptr_val may contain extension data. */
7549 img
->data
.lisp_val
= Qnil
;
7550 x_clear_image (f
, img
);
7553 /* Return non-zero if OBJECT is a valid GIF image specification. */
7556 gif_image_p (object
)
7559 struct image_keyword fmt
[GIF_LAST
];
7560 bcopy (gif_format
, fmt
, sizeof fmt
);
7562 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7565 /* Must specify either the :data or :file keyword. */
7566 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7569 #endif /* HAVE_GIF || MAC_OS */
7573 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7574 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7575 Undefine before redefining to avoid a preprocessor warning. */
7579 /* avoid conflict with QuickdrawText.h */
7580 #define DrawText gif_DrawText
7581 #include <gif_lib.h>
7584 #else /* HAVE_NTGUI || MAC_OS */
7586 #include <gif_lib.h>
7588 #endif /* HAVE_NTGUI || MAC_OS */
7593 /* GIF library details. */
7594 DEF_IMGLIB_FN (DGifCloseFile
);
7595 DEF_IMGLIB_FN (DGifSlurp
);
7596 DEF_IMGLIB_FN (DGifOpen
);
7597 DEF_IMGLIB_FN (DGifOpenFileName
);
7600 init_gif_functions (Lisp_Object libraries
)
7604 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7607 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7608 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7609 LOAD_IMGLIB_FN (library
, DGifOpen
);
7610 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7616 #define fn_DGifCloseFile DGifCloseFile
7617 #define fn_DGifSlurp DGifSlurp
7618 #define fn_DGifOpen DGifOpen
7619 #define fn_DGifOpenFileName DGifOpenFileName
7621 #endif /* HAVE_NTGUI */
7623 /* Reading a GIF image from memory
7624 Based on the PNG memory stuff to a certain extent. */
7628 unsigned char *bytes
;
7634 /* Make the current memory source available to gif_read_from_memory.
7635 It's done this way because not all versions of libungif support
7636 a UserData field in the GifFileType structure. */
7637 static gif_memory_source
*current_gif_memory_src
;
7640 gif_read_from_memory (file
, buf
, len
)
7645 gif_memory_source
*src
= current_gif_memory_src
;
7647 if (len
> src
->len
- src
->index
)
7650 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7656 /* Load GIF image IMG for use on frame F. Value is non-zero if
7664 Lisp_Object file
, specified_file
;
7665 Lisp_Object specified_data
;
7666 int rc
, width
, height
, x
, y
, i
;
7668 ColorMapObject
*gif_color_map
;
7669 unsigned long pixel_colors
[256];
7671 struct gcpro gcpro1
;
7673 int ino
, image_height
, image_width
;
7674 gif_memory_source memsrc
;
7675 unsigned char *raster
;
7677 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7678 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7682 if (NILP (specified_data
))
7684 file
= x_find_image_file (specified_file
);
7685 if (!STRINGP (file
))
7687 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7692 /* Open the GIF file. Casting return value avoids a GCC warning
7694 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7697 image_error ("Cannot open `%s'", file
, Qnil
);
7704 /* Read from memory! */
7705 current_gif_memory_src
= &memsrc
;
7706 memsrc
.bytes
= SDATA (specified_data
);
7707 memsrc
.len
= SBYTES (specified_data
);
7710 /* Casting return value avoids a GCC warning on W32. */
7711 gif
= (GifFileType
*)fn_DGifOpen(&memsrc
, gif_read_from_memory
);
7714 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7720 /* Before reading entire contents, check the declared image size. */
7721 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7723 image_error ("Invalid image size", Qnil
, Qnil
);
7724 fn_DGifCloseFile (gif
);
7729 /* Read entire contents. */
7730 rc
= fn_DGifSlurp (gif
);
7731 if (rc
== GIF_ERROR
)
7733 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7734 fn_DGifCloseFile (gif
);
7739 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7740 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7741 if (ino
>= gif
->ImageCount
)
7743 image_error ("Invalid image number `%s' in image `%s'",
7745 fn_DGifCloseFile (gif
);
7750 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7751 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7752 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7753 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7754 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7755 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7757 width
= img
->width
= max (gif
->SWidth
,
7758 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7759 img
->corners
[RIGHT_CORNER
]));
7760 height
= img
->height
= max (gif
->SHeight
,
7761 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7762 img
->corners
[BOT_CORNER
]));
7764 if (!check_image_size (f
, width
, height
))
7766 image_error ("Invalid image size", Qnil
, Qnil
);
7767 fn_DGifCloseFile (gif
);
7772 /* Create the X image and pixmap. */
7773 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7775 fn_DGifCloseFile (gif
);
7780 /* Allocate colors. */
7781 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7783 gif_color_map
= gif
->SColorMap
;
7784 init_color_table ();
7785 bzero (pixel_colors
, sizeof pixel_colors
);
7787 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7789 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7790 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7791 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7792 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7795 #ifdef COLOR_TABLE_SUPPORT
7796 img
->colors
= colors_in_color_table (&img
->ncolors
);
7797 free_color_table ();
7798 #endif /* COLOR_TABLE_SUPPORT */
7800 /* Clear the part of the screen image that are not covered by
7801 the image from the GIF file. Full animated GIF support
7802 requires more than can be done here (see the gif89 spec,
7803 disposal methods). Let's simply assume that the part
7804 not covered by a sub-image is in the frame's background color. */
7805 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7806 for (x
= 0; x
< width
; ++x
)
7807 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7809 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7810 for (x
= 0; x
< width
; ++x
)
7811 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7813 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7815 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7816 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7817 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7818 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7821 /* Read the GIF image into the X image. We use a local variable
7822 `raster' here because RasterBits below is a char *, and invites
7823 problems with bytes >= 0x80. */
7824 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7826 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7828 static int interlace_start
[] = {0, 4, 2, 1};
7829 static int interlace_increment
[] = {8, 8, 4, 2};
7831 int row
= interlace_start
[0];
7835 for (y
= 0; y
< image_height
; y
++)
7837 if (row
>= image_height
)
7839 row
= interlace_start
[++pass
];
7840 while (row
>= image_height
)
7841 row
= interlace_start
[++pass
];
7844 for (x
= 0; x
< image_width
; x
++)
7846 int i
= raster
[(y
* image_width
) + x
];
7847 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7848 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7851 row
+= interlace_increment
[pass
];
7856 for (y
= 0; y
< image_height
; ++y
)
7857 for (x
= 0; x
< image_width
; ++x
)
7859 int i
= raster
[y
* image_width
+ x
];
7860 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7861 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7865 /* Save GIF image extension data for `image-extension-data'.
7866 Format is (count IMAGES FUNCTION "BYTES" ...). */
7867 img
->data
.lisp_val
= Qnil
;
7868 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
7870 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
7871 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
7872 /* Append (... FUNCTION "BYTES") */
7873 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
7874 Fcons (make_number (ext
->Function
),
7875 img
->data
.lisp_val
));
7876 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
7878 if (gif
->ImageCount
> 1)
7879 img
->data
.lisp_val
= Fcons (Qcount
,
7880 Fcons (make_number (gif
->ImageCount
),
7881 img
->data
.lisp_val
));
7883 fn_DGifCloseFile (gif
);
7885 /* Maybe fill in the background field while we have ximg handy. */
7886 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7887 /* Casting avoids a GCC warning. */
7888 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7890 /* Put the image into the pixmap, then free the X image and its buffer. */
7891 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7892 x_destroy_x_image (ximg
);
7898 #else /* !HAVE_GIF */
7906 Lisp_Object specified_file
, file
;
7907 Lisp_Object specified_data
;
7909 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
7917 Lisp_Object specified_bg
;
7922 TimeScale time_scale
;
7923 TimeValue time
, duration
;
7928 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7929 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7931 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7934 if (NILP (specified_data
))
7936 /* Read from a file */
7940 err
= find_image_fsspec (specified_file
, &file
, &fss
);
7944 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7949 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
7950 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
7954 if (!graphic_p
&& !movie_p
)
7956 if (prefer_graphic_p
)
7957 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
7958 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
7961 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
7962 CloseMovieFile (refnum
);
7965 image_error ("Error reading `%s'", file
, Qnil
);
7971 /* Memory source! */
7973 long file_type_atom
[3];
7975 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
7978 image_error ("Cannot allocate data handle for `%s'",
7983 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
7984 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
7985 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
7986 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
7989 err
= PtrAndHand ("\p", dref
, 1);
7991 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
7994 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
7997 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
7998 &movie_p
, &prefer_graphic_p
, 0);
8002 if (!graphic_p
&& !movie_p
)
8004 if (prefer_graphic_p
)
8008 DisposeHandle (dref
);
8009 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8013 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8014 HandleDataHandlerSubType
);
8015 DisposeHandle (dref
);
8020 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8021 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8022 track
= GetMovieIndTrack (movie
, 1);
8023 media
= GetTrackMedia (track
);
8024 nsamples
= GetMediaSampleCount (media
);
8025 if (ino
>= nsamples
)
8027 image_error ("Invalid image number `%s' in image `%s'",
8031 time_scale
= GetMediaTimeScale (media
);
8033 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8034 if (!STRINGP (specified_bg
) ||
8035 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8037 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8038 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8039 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8040 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8042 GetMovieBox (movie
, &rect
);
8043 width
= img
->width
= rect
.right
- rect
.left
;
8044 height
= img
->height
= rect
.bottom
- rect
.top
;
8045 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8048 GetGWorld (&old_port
, &old_gdh
);
8049 SetGWorld (ximg
, NULL
);
8050 bg_color
.red
= color
.red
;
8051 bg_color
.green
= color
.green
;
8052 bg_color
.blue
= color
.blue
;
8053 RGBBackColor (&bg_color
);
8054 SetGWorld (old_port
, old_gdh
);
8055 SetMovieActive (movie
, 1);
8056 SetMovieGWorld (movie
, ximg
, NULL
);
8057 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8058 SetMovieTimeValue (movie
, time
);
8059 MoviesTask (movie
, 0L);
8060 DisposeTrackMedia (media
);
8061 DisposeMovieTrack (track
);
8062 DisposeMovie (movie
);
8066 /* Save GIF image extension data for `image-extension-data'.
8067 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8069 Lisp_Object gce
= make_uninit_string (4);
8070 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8072 /* Fill the delay time field. */
8073 SSET (gce
, 1, centisec
& 0xff);
8074 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8075 /* We don't know about other fields. */
8079 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8080 make_number (0xf9), gce
);
8083 /* Maybe fill in the background field while we have ximg handy. */
8084 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8085 IMAGE_BACKGROUND (img
, f
, ximg
);
8087 /* Put the image into the pixmap. */
8088 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8089 x_destroy_x_image (ximg
);
8093 image_error ("Cannot open `%s'", file
, Qnil
);
8096 DisposeTrackMedia (media
);
8098 DisposeMovieTrack (track
);
8100 DisposeMovie (movie
);
8107 #endif /* HAVE_GIF */
8111 /***********************************************************************
8113 ***********************************************************************/
8115 #ifdef HAVE_X_WINDOWS
8116 #define HAVE_GHOSTSCRIPT 1
8117 #endif /* HAVE_X_WINDOWS */
8119 /* The symbol `postscript' identifying images of this type. */
8121 Lisp_Object Qpostscript
;
8123 #ifdef HAVE_GHOSTSCRIPT
8125 static int gs_image_p
P_ ((Lisp_Object object
));
8126 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8127 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8129 /* Keyword symbols. */
8131 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8133 /* Indices of image specification fields in gs_format, below. */
8135 enum gs_keyword_index
8153 /* Vector of image_keyword structures describing the format
8154 of valid user-defined image specifications. */
8156 static struct image_keyword gs_format
[GS_LAST
] =
8158 {":type", IMAGE_SYMBOL_VALUE
, 1},
8159 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8160 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8161 {":file", IMAGE_STRING_VALUE
, 1},
8162 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8163 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8164 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8165 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8166 {":relief", IMAGE_INTEGER_VALUE
, 0},
8167 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8168 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8169 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8170 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8173 /* Structure describing the image type `ghostscript'. */
8175 static struct image_type gs_type
=
8185 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8188 gs_clear_image (f
, img
)
8192 /* IMG->data.ptr_val may contain a recorded colormap. */
8193 xfree (img
->data
.ptr_val
);
8194 x_clear_image (f
, img
);
8198 /* Return non-zero if OBJECT is a valid Ghostscript image
8205 struct image_keyword fmt
[GS_LAST
];
8209 bcopy (gs_format
, fmt
, sizeof fmt
);
8211 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8214 /* Bounding box must be a list or vector containing 4 integers. */
8215 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8218 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8219 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8224 else if (VECTORP (tem
))
8226 if (XVECTOR (tem
)->size
!= 4)
8228 for (i
= 0; i
< 4; ++i
)
8229 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8239 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8248 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8249 struct gcpro gcpro1
, gcpro2
;
8251 double in_width
, in_height
;
8252 Lisp_Object pixel_colors
= Qnil
;
8254 /* Compute pixel size of pixmap needed from the given size in the
8255 image specification. Sizes in the specification are in pt. 1 pt
8256 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8258 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8259 in_width
= XFASTINT (pt_width
) / 72.0;
8260 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8261 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8262 in_height
= XFASTINT (pt_height
) / 72.0;
8263 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8265 if (!check_image_size (f
, img
->width
, img
->height
))
8267 image_error ("Invalid image size", Qnil
, Qnil
);
8271 /* Create the pixmap. */
8272 xassert (img
->pixmap
== NO_PIXMAP
);
8274 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8276 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8277 img
->width
, img
->height
,
8278 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8283 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8287 /* Call the loader to fill the pixmap. It returns a process object
8288 if successful. We do not record_unwind_protect here because
8289 other places in redisplay like calling window scroll functions
8290 don't either. Let the Lisp loader use `unwind-protect' instead. */
8291 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8293 sprintf (buffer
, "%lu %lu",
8294 (unsigned long) FRAME_X_WINDOW (f
),
8295 (unsigned long) img
->pixmap
);
8296 window_and_pixmap_id
= build_string (buffer
);
8298 sprintf (buffer
, "%lu %lu",
8299 FRAME_FOREGROUND_PIXEL (f
),
8300 FRAME_BACKGROUND_PIXEL (f
));
8301 pixel_colors
= build_string (buffer
);
8303 XSETFRAME (frame
, f
);
8304 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8306 loader
= intern ("gs-load-image");
8308 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8309 make_number (img
->width
),
8310 make_number (img
->height
),
8311 window_and_pixmap_id
,
8314 return PROCESSP (img
->data
.lisp_val
);
8318 /* Kill the Ghostscript process that was started to fill PIXMAP on
8319 frame F. Called from XTread_socket when receiving an event
8320 telling Emacs that Ghostscript has finished drawing. */
8323 x_kill_gs_process (pixmap
, f
)
8327 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8331 /* Find the image containing PIXMAP. */
8332 for (i
= 0; i
< c
->used
; ++i
)
8333 if (c
->images
[i
]->pixmap
== pixmap
)
8336 /* Should someone in between have cleared the image cache, for
8337 instance, give up. */
8341 /* Kill the GS process. We should have found PIXMAP in the image
8342 cache and its image should contain a process object. */
8344 xassert (PROCESSP (img
->data
.lisp_val
));
8345 Fkill_process (img
->data
.lisp_val
, Qnil
);
8346 img
->data
.lisp_val
= Qnil
;
8348 #if defined (HAVE_X_WINDOWS)
8350 /* On displays with a mutable colormap, figure out the colors
8351 allocated for the image by looking at the pixels of an XImage for
8353 class = FRAME_X_VISUAL (f
)->class;
8354 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8360 /* Try to get an XImage for img->pixmep. */
8361 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8362 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8367 /* Initialize the color table. */
8368 init_color_table ();
8370 /* For each pixel of the image, look its color up in the
8371 color table. After having done so, the color table will
8372 contain an entry for each color used by the image. */
8373 for (y
= 0; y
< img
->height
; ++y
)
8374 for (x
= 0; x
< img
->width
; ++x
)
8376 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8377 lookup_pixel_color (f
, pixel
);
8380 /* Record colors in the image. Free color table and XImage. */
8381 #ifdef COLOR_TABLE_SUPPORT
8382 img
->colors
= colors_in_color_table (&img
->ncolors
);
8383 free_color_table ();
8385 XDestroyImage (ximg
);
8387 #if 0 /* This doesn't seem to be the case. If we free the colors
8388 here, we get a BadAccess later in x_clear_image when
8389 freeing the colors. */
8390 /* We have allocated colors once, but Ghostscript has also
8391 allocated colors on behalf of us. So, to get the
8392 reference counts right, free them once. */
8394 x_free_colors (f
, img
->colors
, img
->ncolors
);
8398 image_error ("Cannot get X image of `%s'; colors will not be freed",
8403 #endif /* HAVE_X_WINDOWS */
8405 /* Now that we have the pixmap, compute mask and transform the
8406 image if requested. */
8408 postprocess_image (f
, img
);
8412 #endif /* HAVE_GHOSTSCRIPT */
8415 /***********************************************************************
8417 ***********************************************************************/
8421 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8422 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8426 return valid_image_p (spec
) ? Qt
: Qnil
;
8430 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8436 if (valid_image_p (spec
))
8437 id
= lookup_image (SELECTED_FRAME (), spec
);
8440 return make_number (id
);
8443 #endif /* GLYPH_DEBUG != 0 */
8446 /***********************************************************************
8448 ***********************************************************************/
8451 /* Image types that rely on external libraries are loaded dynamically
8452 if the library is available. */
8453 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8454 define_image_type (image_type, init_lib_fn (libraries))
8456 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8457 define_image_type (image_type, 1)
8458 #endif /* HAVE_NTGUI */
8460 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8461 doc
: /* Initialize image library implementing image type TYPE.
8462 Return non-nil if TYPE is a supported image type.
8464 Image types pbm and xbm are prebuilt; other types are loaded here.
8465 Libraries to load are specified in alist LIBRARIES (usually, the value
8466 of `image-library-alist', which see). */)
8468 Lisp_Object type
, libraries
;
8472 /* Don't try to reload the library. */
8473 tested
= Fassq (type
, Vimage_type_cache
);
8475 return XCDR (tested
);
8477 #if defined (HAVE_XPM) || defined (MAC_OS)
8478 if (EQ (type
, Qxpm
))
8479 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8482 #if defined (HAVE_JPEG) || defined (MAC_OS)
8483 if (EQ (type
, Qjpeg
))
8484 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8487 #if defined (HAVE_TIFF) || defined (MAC_OS)
8488 if (EQ (type
, Qtiff
))
8489 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8492 #if defined (HAVE_GIF) || defined (MAC_OS)
8493 if (EQ (type
, Qgif
))
8494 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8497 #if defined (HAVE_PNG) || defined (MAC_OS)
8498 if (EQ (type
, Qpng
))
8499 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8502 #ifdef HAVE_GHOSTSCRIPT
8503 if (EQ (type
, Qpostscript
))
8504 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8507 /* If the type is not recognized, avoid testing it ever again. */
8508 CACHE_IMAGE_TYPE (type
, Qnil
);
8515 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8517 /* Initialize this only once, since that's what we do with Vimage_types
8518 and they are supposed to be in sync. Initializing here gives correct
8519 operation on GNU/Linux of calling dump-emacs after loading some images. */
8522 /* Must be defined now becase we're going to update it below, while
8523 defining the supported image types. */
8524 DEFVAR_LISP ("image-types", &Vimage_types
,
8525 doc
: /* List of potentially supported image types.
8526 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
8527 To check whether it is really supported, use `image-type-available-p'. */);
8528 Vimage_types
= Qnil
;
8530 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8531 doc
: /* Alist of image types vs external libraries needed to display them.
8533 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8534 representing a supported image type, and the rest are strings giving
8535 alternate filenames for the corresponding external libraries.
8537 Emacs tries to load the libraries in the order they appear on the
8538 list; if none is loaded, the running session of Emacs won't
8539 support the image type. Types 'pbm and 'xbm don't need to be
8540 listed; they're always supported. */);
8541 Vimage_library_alist
= Qnil
;
8542 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8544 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8545 doc
: /* Maximum size of images.
8546 Emacs will not load an image into memory if its pixel width or
8547 pixel height exceeds this limit.
8549 If the value is an integer, it directly specifies the maximum
8550 image height and width, measured in pixels. If it is a floating
8551 point number, it specifies the maximum image height and width
8552 as a ratio to the frame height and width. If the value is
8553 non-numeric, there is no explicit limit on the size of images. */);
8554 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
8556 Vimage_type_cache
= Qnil
;
8557 staticpro (&Vimage_type_cache
);
8559 Qpbm
= intern ("pbm");
8561 ADD_IMAGE_TYPE(Qpbm
);
8563 Qxbm
= intern ("xbm");
8565 ADD_IMAGE_TYPE(Qxbm
);
8567 define_image_type (&xbm_type
, 1);
8568 define_image_type (&pbm_type
, 1);
8570 QCascent
= intern (":ascent");
8571 staticpro (&QCascent
);
8572 QCmargin
= intern (":margin");
8573 staticpro (&QCmargin
);
8574 QCrelief
= intern (":relief");
8575 staticpro (&QCrelief
);
8576 QCconversion
= intern (":conversion");
8577 staticpro (&QCconversion
);
8578 QCcolor_symbols
= intern (":color-symbols");
8579 staticpro (&QCcolor_symbols
);
8580 QCheuristic_mask
= intern (":heuristic-mask");
8581 staticpro (&QCheuristic_mask
);
8582 QCindex
= intern (":index");
8583 staticpro (&QCindex
);
8584 QCmatrix
= intern (":matrix");
8585 staticpro (&QCmatrix
);
8586 QCcolor_adjustment
= intern (":color-adjustment");
8587 staticpro (&QCcolor_adjustment
);
8588 QCmask
= intern (":mask");
8589 staticpro (&QCmask
);
8591 Qlaplace
= intern ("laplace");
8592 staticpro (&Qlaplace
);
8593 Qemboss
= intern ("emboss");
8594 staticpro (&Qemboss
);
8595 Qedge_detection
= intern ("edge-detection");
8596 staticpro (&Qedge_detection
);
8597 Qheuristic
= intern ("heuristic");
8598 staticpro (&Qheuristic
);
8600 Qpostscript
= intern ("postscript");
8601 staticpro (&Qpostscript
);
8602 #ifdef HAVE_GHOSTSCRIPT
8603 ADD_IMAGE_TYPE(Qpostscript
);
8604 QCloader
= intern (":loader");
8605 staticpro (&QCloader
);
8606 QCbounding_box
= intern (":bounding-box");
8607 staticpro (&QCbounding_box
);
8608 QCpt_width
= intern (":pt-width");
8609 staticpro (&QCpt_width
);
8610 QCpt_height
= intern (":pt-height");
8611 staticpro (&QCpt_height
);
8612 #endif /* HAVE_GHOSTSCRIPT */
8614 #if defined (HAVE_XPM) || defined (MAC_OS)
8615 Qxpm
= intern ("xpm");
8617 ADD_IMAGE_TYPE(Qxpm
);
8620 #if defined (HAVE_JPEG) || defined (MAC_OS)
8621 Qjpeg
= intern ("jpeg");
8623 ADD_IMAGE_TYPE(Qjpeg
);
8626 #if defined (HAVE_TIFF) || defined (MAC_OS)
8627 Qtiff
= intern ("tiff");
8629 ADD_IMAGE_TYPE(Qtiff
);
8632 #if defined (HAVE_GIF) || defined (MAC_OS)
8633 Qgif
= intern ("gif");
8635 ADD_IMAGE_TYPE(Qgif
);
8638 #if defined (HAVE_PNG) || defined (MAC_OS)
8639 Qpng
= intern ("png");
8641 ADD_IMAGE_TYPE(Qpng
);
8644 defsubr (&Sinit_image_library
);
8645 defsubr (&Sclear_image_cache
);
8646 defsubr (&Simage_size
);
8647 defsubr (&Simage_mask_p
);
8648 defsubr (&Simage_extension_data
);
8652 defsubr (&Slookup_image
);
8655 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8656 doc
: /* Non-nil means always draw a cross over disabled images.
8657 Disabled images are those having an `:conversion disabled' property.
8658 A cross is always drawn on black & white displays. */);
8659 cross_disabled_images
= 0;
8661 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8662 doc
: /* List of directories to search for window system bitmap files. */);
8663 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8665 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8666 doc
: /* Time after which cached images are removed from the cache.
8667 When an image has not been displayed this many seconds, remove it
8668 from the image cache. Value must be an integer or nil with nil
8669 meaning don't clear the cache. */);
8670 Vimage_cache_eviction_delay
= make_number (30 * 60);
8676 #if defined (MAC_OSX) && TARGET_API_MAC_CARBON
8677 init_image_func_pointer ();
8681 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8682 (do not change this comment) */