1 /* Functions for image support on window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000,01,02,03,04
3 Free Software Foundation.
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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, 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"
46 #include <sys/types.h>
49 #define COLOR_TABLE_SUPPORT 1
51 typedef struct x_bitmap_record Bitmap_Record
;
52 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
53 #define NO_PIXMAP None
55 #define RGB_PIXEL_COLOR unsigned long
57 #define PIX_MASK_RETAIN(f) 0
58 #define PIX_MASK_DRAW(f) 1
59 #endif /* HAVE_X_WINDOWS */
65 /* W32_TODO : Color tables on W32. */
66 #undef COLOR_TABLE_SUPPORT
68 typedef struct w32_bitmap_record Bitmap_Record
;
69 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
72 #define RGB_PIXEL_COLOR COLORREF
74 #define PIX_MASK_RETAIN(f) 0
75 #define PIX_MASK_DRAW(f) 1
77 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
78 #define x_defined_color w32_defined_color
79 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
80 #endif /* HAVE_NTGUI */
90 #include <QuickTime/QuickTime.h>
91 #else /* not MAC_OSX */
94 #include <TextUtils.h>
95 #endif /* not MAC_OSX */
97 /* MAC_TODO : Color tables on Mac. */
98 #undef COLOR_TABLE_SUPPORT
100 #define ZPixmap 0 /* arbitrary */
101 typedef struct mac_bitmap_record Bitmap_Record
;
103 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
106 #define RGB_PIXEL_COLOR unsigned long
108 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
109 #define x_defined_color mac_defined_color
110 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
111 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
112 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
117 /* Search path for bitmap files. */
119 Lisp_Object Vx_bitmap_file_path
;
122 static void x_disable_image
P_ ((struct frame
*, struct image
*));
123 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
126 static void init_color_table
P_ ((void));
127 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
128 #ifdef COLOR_TABLE_SUPPORT
129 static void free_color_table
P_ ((void));
130 static unsigned long *colors_in_color_table
P_ ((int *n
));
131 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
134 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
135 id, which is just an int that this section returns. Bitmaps are
136 reference counted so they can be shared among frames.
138 Bitmap indices are guaranteed to be > 0, so a negative number can
139 be used to indicate no bitmap.
141 If you use x_create_bitmap_from_data, then you must keep track of
142 the bitmaps yourself. That is, creating a bitmap from the same
143 data more than once will not be caught. */
148 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
149 Display
*display
; /* not used */
151 int x
, y
; /* not used */
152 unsigned int width
, height
; /* not used */
153 unsigned long plane_mask
; /* not used */
154 int format
; /* not used */
157 xassert (x
== 0 && y
== 0);
160 SetRect (&ri
, 0, 0, width
, height
);
161 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
163 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
166 LockPixels (GetGWorldPixMap (pixmap
));
172 XPutPixel (ximage
, x
, y
, pixel
)
181 GetGWorld (&old_port
, &old_gdh
);
182 SetGWorld (ximage
, NULL
);
184 color
.red
= RED16_FROM_ULONG (pixel
);
185 color
.green
= GREEN16_FROM_ULONG (pixel
);
186 color
.blue
= BLUE16_FROM_ULONG (pixel
);
187 SetCPixel (x
, y
, &color
);
189 SetGWorld (old_port
, old_gdh
);
193 XGetPixel (ximage
, x
, y
)
201 GetGWorld (&old_port
, &old_gdh
);
202 SetGWorld (ximage
, NULL
);
204 GetCPixel (x
, y
, &color
);
206 SetGWorld (old_port
, old_gdh
);
207 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
214 UnlockPixels (GetGWorldPixMap (ximg
));
219 /* Functions to access the contents of a bitmap, given an id. */
222 x_bitmap_height (f
, id
)
226 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
230 x_bitmap_width (f
, id
)
234 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
237 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
239 x_bitmap_pixmap (f
, id
)
243 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
247 #ifdef HAVE_X_WINDOWS
249 x_bitmap_mask (f
, id
)
253 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
257 /* Allocate a new bitmap record. Returns index of new record. */
260 x_allocate_bitmap_record (f
)
263 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
266 if (dpyinfo
->bitmaps
== NULL
)
268 dpyinfo
->bitmaps_size
= 10;
270 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
271 dpyinfo
->bitmaps_last
= 1;
275 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
276 return ++dpyinfo
->bitmaps_last
;
278 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
279 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
282 dpyinfo
->bitmaps_size
*= 2;
284 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
285 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
286 return ++dpyinfo
->bitmaps_last
;
289 /* Add one reference to the reference count of the bitmap with id ID. */
292 x_reference_bitmap (f
, id
)
296 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
299 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
302 x_create_bitmap_from_data (f
, bits
, width
, height
)
305 unsigned int width
, height
;
307 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
310 #ifdef HAVE_X_WINDOWS
312 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
313 bits
, width
, height
);
316 #endif /* HAVE_X_WINDOWS */
320 bitmap
= CreateBitmap (width
, height
,
321 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
322 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
326 #endif /* HAVE_NTGUI */
329 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
334 id
= x_allocate_bitmap_record (f
);
336 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
337 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
339 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
342 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
343 dpyinfo
->bitmaps
[id
- 1].height
= height
;
344 dpyinfo
->bitmaps
[id
- 1].width
= width
;
345 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
347 #ifdef HAVE_X_WINDOWS
348 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
349 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
350 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
351 #endif /* HAVE_X_WINDOWS */
354 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
355 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
356 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
357 #endif /* HAVE_NTGUI */
362 /* Create bitmap from file FILE for frame F. */
365 x_create_bitmap_from_file (f
, file
)
370 return -1; /* MAC_TODO : bitmap support */
374 return -1; /* W32_TODO : bitmap support */
375 #endif /* HAVE_NTGUI */
377 #ifdef HAVE_X_WINDOWS
378 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
379 unsigned int width
, height
;
381 int xhot
, yhot
, result
, id
;
386 /* Look for an existing bitmap with the same name. */
387 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
389 if (dpyinfo
->bitmaps
[id
].refcount
390 && dpyinfo
->bitmaps
[id
].file
391 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
393 ++dpyinfo
->bitmaps
[id
].refcount
;
398 /* Search bitmap-file-path for the file, if appropriate. */
399 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
404 filename
= (char *) SDATA (found
);
406 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
407 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
408 if (result
!= BitmapSuccess
)
411 id
= x_allocate_bitmap_record (f
);
412 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
413 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
414 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
415 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
416 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
417 dpyinfo
->bitmaps
[id
- 1].height
= height
;
418 dpyinfo
->bitmaps
[id
- 1].width
= width
;
419 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
422 #endif /* HAVE_X_WINDOWS */
428 Free_Bitmap_Record (dpyinfo
, bm
)
429 Display_Info
*dpyinfo
;
432 #ifdef HAVE_X_WINDOWS
433 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
435 XFreePixmap (dpyinfo
->display
, bm
->mask
);
436 #endif /* HAVE_X_WINDOWS */
439 DeleteObject (bm
->pixmap
);
440 #endif /* HAVE_NTGUI */
443 xfree (bm
->bitmap_data
); /* Added ++kfs */
444 bm
->bitmap_data
= NULL
;
454 /* Remove reference to bitmap with id number ID. */
457 x_destroy_bitmap (f
, id
)
461 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
465 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
467 if (--bm
->refcount
== 0)
470 Free_Bitmap_Record (dpyinfo
, bm
);
476 /* Free all the bitmaps for the display specified by DPYINFO. */
479 x_destroy_all_bitmaps (dpyinfo
)
480 Display_Info
*dpyinfo
;
483 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
485 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
486 if (bm
->refcount
> 0)
487 Free_Bitmap_Record (dpyinfo
, bm
);
489 dpyinfo
->bitmaps_last
= 0;
493 #ifdef HAVE_X_WINDOWS
495 /* Useful functions defined in the section
496 `Image type independent image structures' below. */
498 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
499 unsigned long height
));
501 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
502 int depth
, XImagePtr
*ximg
,
505 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
508 /* Create a mask of a bitmap. Note is this not a perfect mask.
509 It's nicer with some borders in this context */
512 x_create_bitmap_mask (f
, id
)
517 XImagePtr ximg
, mask_img
;
518 unsigned long width
, height
;
521 unsigned long x
, y
, xp
, xm
, yp
, ym
;
524 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
529 pixmap
= x_bitmap_pixmap (f
, id
);
530 width
= x_bitmap_width (f
, id
);
531 height
= x_bitmap_height (f
, id
);
534 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
543 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
548 XDestroyImage (ximg
);
552 bg
= four_corners_best (ximg
, width
, height
);
554 for (y
= 0; y
< ximg
->height
; ++y
)
556 for (x
= 0; x
< ximg
->width
; ++x
)
558 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
559 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
560 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
561 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
562 if (XGetPixel (ximg
, x
, y
) == bg
563 && XGetPixel (ximg
, x
, yp
) == bg
564 && XGetPixel (ximg
, x
, ym
) == bg
565 && XGetPixel (ximg
, xp
, y
) == bg
566 && XGetPixel (ximg
, xp
, yp
) == bg
567 && XGetPixel (ximg
, xp
, ym
) == bg
568 && XGetPixel (ximg
, xm
, y
) == bg
569 && XGetPixel (ximg
, xm
, yp
) == bg
570 && XGetPixel (ximg
, xm
, ym
) == bg
)
571 XPutPixel (mask_img
, x
, y
, 0);
573 XPutPixel (mask_img
, x
, y
, 1);
577 xassert (interrupt_input_blocked
);
578 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
579 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
581 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
583 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
584 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
586 XDestroyImage (ximg
);
587 x_destroy_x_image (mask_img
);
592 #endif /* HAVE_X_WINDOWS */
595 /***********************************************************************
597 ***********************************************************************/
599 /* Value is the number of elements of vector VECTOR. */
601 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
603 /* List of supported image types. Use define_image_type to add new
604 types. Use lookup_image_type to find a type for a given symbol. */
606 static struct image_type
*image_types
;
608 /* The symbol `xbm' which is used as the type symbol for XBM images. */
614 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
615 extern Lisp_Object QCdata
, QCtype
;
616 extern Lisp_Object Qcenter
;
617 Lisp_Object QCascent
, QCmargin
, QCrelief
;
618 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
619 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
623 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
625 /* Time in seconds after which images should be removed from the cache
628 Lisp_Object Vimage_cache_eviction_delay
;
630 /* Function prototypes. */
632 static void define_image_type
P_ ((struct image_type
*type
));
633 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
634 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
635 static void x_laplace
P_ ((struct frame
*, struct image
*));
636 static void x_emboss
P_ ((struct frame
*, struct image
*));
637 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
641 /* Define a new image type from TYPE. This adds a copy of TYPE to
642 image_types and adds the symbol *TYPE->type to Vimage_types. */
645 define_image_type (type
)
646 struct image_type
*type
;
648 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
649 The initialized data segment is read-only. */
650 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
651 bcopy (type
, p
, sizeof *p
);
652 p
->next
= image_types
;
654 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
658 /* Look up image type SYMBOL, and return a pointer to its image_type
659 structure. Value is null if SYMBOL is not a known image type. */
661 static INLINE
struct image_type
*
662 lookup_image_type (symbol
)
665 struct image_type
*type
;
667 for (type
= image_types
; type
; type
= type
->next
)
668 if (EQ (symbol
, *type
->type
))
675 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
676 valid image specification is a list whose car is the symbol
677 `image', and whose rest is a property list. The property list must
678 contain a value for key `:type'. That value must be the name of a
679 supported image type. The rest of the property list depends on the
683 valid_image_p (object
)
692 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
693 if (EQ (XCAR (tem
), QCtype
))
696 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
698 struct image_type
*type
;
699 type
= lookup_image_type (XCAR (tem
));
701 valid_p
= type
->valid_p (object
);
712 /* Log error message with format string FORMAT and argument ARG.
713 Signaling an error, e.g. when an image cannot be loaded, is not a
714 good idea because this would interrupt redisplay, and the error
715 message display would lead to another redisplay. This function
716 therefore simply displays a message. */
719 image_error (format
, arg1
, arg2
)
721 Lisp_Object arg1
, arg2
;
723 add_to_log (format
, arg1
, arg2
);
728 /***********************************************************************
730 ***********************************************************************/
732 enum image_value_type
734 IMAGE_DONT_CHECK_VALUE_TYPE
,
736 IMAGE_STRING_OR_NIL_VALUE
,
738 IMAGE_POSITIVE_INTEGER_VALUE
,
739 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
740 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
743 IMAGE_FUNCTION_VALUE
,
748 /* Structure used when parsing image specifications. */
752 /* Name of keyword. */
755 /* The type of value allowed. */
756 enum image_value_type type
;
758 /* Non-zero means key must be present. */
761 /* Used to recognize duplicate keywords in a property list. */
764 /* The value that was found. */
769 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
771 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
774 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
775 has the format (image KEYWORD VALUE ...). One of the keyword/
776 value pairs must be `:type TYPE'. KEYWORDS is a vector of
777 image_keywords structures of size NKEYWORDS describing other
778 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
781 parse_image_spec (spec
, keywords
, nkeywords
, type
)
783 struct image_keyword
*keywords
;
794 while (CONSP (plist
))
796 Lisp_Object key
, value
;
798 /* First element of a pair must be a symbol. */
800 plist
= XCDR (plist
);
804 /* There must follow a value. */
807 value
= XCAR (plist
);
808 plist
= XCDR (plist
);
810 /* Find key in KEYWORDS. Error if not found. */
811 for (i
= 0; i
< nkeywords
; ++i
)
812 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
818 /* Record that we recognized the keyword. If a keywords
819 was found more than once, it's an error. */
820 keywords
[i
].value
= value
;
823 if (keywords
[i
].count
> 1)
826 /* Check type of value against allowed type. */
827 switch (keywords
[i
].type
)
829 case IMAGE_STRING_VALUE
:
830 if (!STRINGP (value
))
834 case IMAGE_STRING_OR_NIL_VALUE
:
835 if (!STRINGP (value
) && !NILP (value
))
839 case IMAGE_SYMBOL_VALUE
:
840 if (!SYMBOLP (value
))
844 case IMAGE_POSITIVE_INTEGER_VALUE
:
845 if (!INTEGERP (value
) || XINT (value
) <= 0)
849 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
850 if (INTEGERP (value
) && XINT (value
) >= 0)
853 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
854 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
858 case IMAGE_ASCENT_VALUE
:
859 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
861 else if (INTEGERP (value
)
863 && XINT (value
) <= 100)
867 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
868 if (!INTEGERP (value
) || XINT (value
) < 0)
872 case IMAGE_DONT_CHECK_VALUE_TYPE
:
875 case IMAGE_FUNCTION_VALUE
:
876 value
= indirect_function (value
);
879 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
883 case IMAGE_NUMBER_VALUE
:
884 if (!INTEGERP (value
) && !FLOATP (value
))
888 case IMAGE_INTEGER_VALUE
:
889 if (!INTEGERP (value
))
893 case IMAGE_BOOL_VALUE
:
894 if (!NILP (value
) && !EQ (value
, Qt
))
903 if (EQ (key
, QCtype
) && !EQ (type
, value
))
907 /* Check that all mandatory fields are present. */
908 for (i
= 0; i
< nkeywords
; ++i
)
909 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
916 /* Return the value of KEY in image specification SPEC. Value is nil
917 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
918 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
921 image_spec_value (spec
, key
, found
)
922 Lisp_Object spec
, key
;
927 xassert (valid_image_p (spec
));
929 for (tail
= XCDR (spec
);
930 CONSP (tail
) && CONSP (XCDR (tail
));
931 tail
= XCDR (XCDR (tail
)))
933 if (EQ (XCAR (tail
), key
))
937 return XCAR (XCDR (tail
));
947 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
948 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
949 PIXELS non-nil means return the size in pixels, otherwise return the
950 size in canonical character units.
951 FRAME is the frame on which the image will be displayed. FRAME nil
952 or omitted means use the selected frame. */)
953 (spec
, pixels
, frame
)
954 Lisp_Object spec
, pixels
, frame
;
959 if (valid_image_p (spec
))
961 struct frame
*f
= check_x_frame (frame
);
962 int id
= lookup_image (f
, spec
);
963 struct image
*img
= IMAGE_FROM_ID (f
, id
);
964 int width
= img
->width
+ 2 * img
->hmargin
;
965 int height
= img
->height
+ 2 * img
->vmargin
;
968 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
969 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
971 size
= Fcons (make_number (width
), make_number (height
));
974 error ("Invalid image specification");
980 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
981 doc
: /* Return t if image SPEC has a mask bitmap.
982 FRAME is the frame on which the image will be displayed. FRAME nil
983 or omitted means use the selected frame. */)
985 Lisp_Object spec
, frame
;
990 if (valid_image_p (spec
))
992 struct frame
*f
= check_x_frame (frame
);
993 int id
= lookup_image (f
, spec
);
994 struct image
*img
= IMAGE_FROM_ID (f
, id
);
999 error ("Invalid image specification");
1005 /***********************************************************************
1006 Image type independent image structures
1007 ***********************************************************************/
1009 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1010 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1013 /* Allocate and return a new image structure for image specification
1014 SPEC. SPEC has a hash value of HASH. */
1016 static struct image
*
1017 make_image (spec
, hash
)
1021 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1023 xassert (valid_image_p (spec
));
1024 bzero (img
, sizeof *img
);
1025 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1026 xassert (img
->type
!= NULL
);
1028 img
->data
.lisp_val
= Qnil
;
1029 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1035 /* Free image IMG which was used on frame F, including its resources. */
1044 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1046 /* Remove IMG from the hash table of its cache. */
1048 img
->prev
->next
= img
->next
;
1050 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1053 img
->next
->prev
= img
->prev
;
1055 c
->images
[img
->id
] = NULL
;
1057 /* Free resources, then free IMG. */
1058 img
->type
->free (f
, img
);
1064 /* Prepare image IMG for display on frame F. Must be called before
1065 drawing an image. */
1068 prepare_image_for_display (f
, img
)
1074 /* We're about to display IMG, so set its timestamp to `now'. */
1076 img
->timestamp
= EMACS_SECS (t
);
1078 /* If IMG doesn't have a pixmap yet, load it now, using the image
1079 type dependent loader function. */
1080 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1081 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1085 /* Value is the number of pixels for the ascent of image IMG when
1086 drawn in face FACE. */
1089 image_ascent (img
, face
, slice
)
1092 struct glyph_slice
*slice
;
1097 if (slice
->height
== img
->height
)
1098 height
= img
->height
+ img
->vmargin
;
1099 else if (slice
->y
== 0)
1100 height
= slice
->height
+ img
->vmargin
;
1102 height
= slice
->height
;
1104 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1109 /* W32 specific version. Why?. ++kfs */
1110 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1111 - FONT_BASE(face
->font
)) / 2;
1113 /* This expression is arranged so that if the image can't be
1114 exactly centered, it will be moved slightly up. This is
1115 because a typical font is `top-heavy' (due to the presence
1116 uppercase letters), so the image placement should err towards
1117 being top-heavy too. It also just generally looks better. */
1118 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1119 #endif /* HAVE_NTGUI */
1122 ascent
= height
/ 2;
1125 ascent
= (int) (height
* img
->ascent
/ 100.0);
1131 /* Image background colors. */
1133 /* Find the "best" corner color of a bitmap.
1134 On W32, XIMG is assumed to a device context with the bitmap selected. */
1136 static RGB_PIXEL_COLOR
1137 four_corners_best (ximg
, width
, height
)
1138 XImagePtr_or_DC ximg
;
1139 unsigned long width
, height
;
1141 RGB_PIXEL_COLOR corners
[4], best
;
1144 /* Get the colors at the corners of ximg. */
1145 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1146 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1147 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1148 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1150 /* Choose the most frequently found color as background. */
1151 for (i
= best_count
= 0; i
< 4; ++i
)
1155 for (j
= n
= 0; j
< 4; ++j
)
1156 if (corners
[i
] == corners
[j
])
1160 best
= corners
[i
], best_count
= n
;
1166 /* Portability macros */
1170 #define Destroy_Image(img_dc, prev) \
1171 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1173 #define Free_Pixmap(display, pixmap) \
1174 DeleteObject (pixmap)
1178 #define Destroy_Image(ximg, dummy) \
1179 XDestroyImage (ximg)
1181 #define Free_Pixmap(display, pixmap) \
1182 XFreePixmap (display, pixmap)
1184 #endif /* HAVE_NTGUI */
1187 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1188 it is guessed heuristically. If non-zero, XIMG is an existing
1189 XImage object (or device context with the image selected on W32) to
1190 use for the heuristic. */
1193 image_background (img
, f
, ximg
)
1196 XImagePtr_or_DC ximg
;
1198 if (! img
->background_valid
)
1199 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1201 int free_ximg
= !ximg
;
1204 #endif /* HAVE_NTGUI */
1209 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1210 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1212 HDC frame_dc
= get_frame_dc (f
);
1213 ximg
= CreateCompatibleDC (frame_dc
);
1214 release_frame_dc (f
, frame_dc
);
1215 prev
= SelectObject (ximg
, img
->pixmap
);
1216 #endif /* !HAVE_NTGUI */
1219 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1222 Destroy_Image (ximg
, prev
);
1224 img
->background_valid
= 1;
1227 return img
->background
;
1230 /* Return the `background_transparent' field of IMG. If IMG doesn't
1231 have one yet, it is guessed heuristically. If non-zero, MASK is an
1232 existing XImage object to use for the heuristic. */
1235 image_background_transparent (img
, f
, mask
)
1238 XImagePtr_or_DC mask
;
1240 if (! img
->background_transparent_valid
)
1241 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1245 int free_mask
= !mask
;
1248 #endif /* HAVE_NTGUI */
1253 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1254 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1256 HDC frame_dc
= get_frame_dc (f
);
1257 mask
= CreateCompatibleDC (frame_dc
);
1258 release_frame_dc (f
, frame_dc
);
1259 prev
= SelectObject (mask
, img
->mask
);
1260 #endif /* HAVE_NTGUI */
1263 img
->background_transparent
1264 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN (f
));
1267 Destroy_Image (mask
, prev
);
1270 img
->background_transparent
= 0;
1272 img
->background_transparent_valid
= 1;
1275 return img
->background_transparent
;
1279 /***********************************************************************
1280 Helper functions for X image types
1281 ***********************************************************************/
1283 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1285 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1286 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1288 Lisp_Object color_name
,
1289 unsigned long dflt
));
1292 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1293 free the pixmap if any. MASK_P non-zero means clear the mask
1294 pixmap if any. COLORS_P non-zero means free colors allocated for
1295 the image, if any. */
1298 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1301 int pixmap_p
, mask_p
, colors_p
;
1303 if (pixmap_p
&& img
->pixmap
)
1305 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1306 img
->pixmap
= NO_PIXMAP
;
1307 img
->background_valid
= 0;
1310 if (mask_p
&& img
->mask
)
1312 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1313 img
->mask
= NO_PIXMAP
;
1314 img
->background_transparent_valid
= 0;
1317 if (colors_p
&& img
->ncolors
)
1319 /* MAC_TODO: color table support. */
1320 /* W32_TODO: color table support. */
1321 #ifdef HAVE_X_WINDOWS
1322 x_free_colors (f
, img
->colors
, img
->ncolors
);
1323 #endif /* HAVE_X_WINDOWS */
1324 xfree (img
->colors
);
1330 /* Free X resources of image IMG which is used on frame F. */
1333 x_clear_image (f
, img
)
1338 x_clear_image_1 (f
, img
, 1, 1, 1);
1343 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1344 cannot be allocated, use DFLT. Add a newly allocated color to
1345 IMG->colors, so that it can be freed again. Value is the pixel
1348 static unsigned long
1349 x_alloc_image_color (f
, img
, color_name
, dflt
)
1352 Lisp_Object color_name
;
1356 unsigned long result
;
1358 xassert (STRINGP (color_name
));
1360 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1362 /* This isn't called frequently so we get away with simply
1363 reallocating the color vector to the needed size, here. */
1366 (unsigned long *) xrealloc (img
->colors
,
1367 img
->ncolors
* sizeof *img
->colors
);
1368 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1369 result
= color
.pixel
;
1379 /***********************************************************************
1381 ***********************************************************************/
1383 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1384 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1386 /* Return a new, initialized image cache that is allocated from the
1387 heap. Call free_image_cache to free an image cache. */
1389 struct image_cache
*
1392 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1395 bzero (c
, sizeof *c
);
1397 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1398 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1399 c
->buckets
= (struct image
**) xmalloc (size
);
1400 bzero (c
->buckets
, size
);
1405 /* Free image cache of frame F. Be aware that X frames share images
1409 free_image_cache (f
)
1412 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1417 /* Cache should not be referenced by any frame when freed. */
1418 xassert (c
->refcount
== 0);
1420 for (i
= 0; i
< c
->used
; ++i
)
1421 free_image (f
, c
->images
[i
]);
1425 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1430 /* Clear image cache of frame F. FORCE_P non-zero means free all
1431 images. FORCE_P zero means clear only images that haven't been
1432 displayed for some time. Should be called from time to time to
1433 reduce the number of loaded images. If image-eviction-seconds is
1434 non-nil, this frees images in the cache which weren't displayed for
1435 at least that many seconds. */
1438 clear_image_cache (f
, force_p
)
1442 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1444 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1451 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1453 /* Block input so that we won't be interrupted by a SIGIO
1454 while being in an inconsistent state. */
1457 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1459 struct image
*img
= c
->images
[i
];
1461 && (force_p
|| img
->timestamp
< old
))
1463 free_image (f
, img
);
1468 /* We may be clearing the image cache because, for example,
1469 Emacs was iconified for a longer period of time. In that
1470 case, current matrices may still contain references to
1471 images freed above. So, clear these matrices. */
1474 Lisp_Object tail
, frame
;
1476 FOR_EACH_FRAME (tail
, frame
)
1478 struct frame
*f
= XFRAME (frame
);
1479 if (FRAME_WINDOW_P (f
)
1480 && FRAME_X_IMAGE_CACHE (f
) == c
)
1481 clear_current_matrices (f
);
1484 ++windows_or_buffers_changed
;
1492 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1494 doc
: /* Clear the image cache of FRAME.
1495 FRAME nil or omitted means use the selected frame.
1496 FRAME t means clear the image caches of all frames. */)
1504 FOR_EACH_FRAME (tail
, frame
)
1505 if (FRAME_WINDOW_P (XFRAME (frame
)))
1506 clear_image_cache (XFRAME (frame
), 1);
1509 clear_image_cache (check_x_frame (frame
), 1);
1515 /* Compute masks and transform image IMG on frame F, as specified
1516 by the image's specification, */
1519 postprocess_image (f
, img
)
1523 /* Manipulation of the image's mask. */
1526 Lisp_Object conversion
, spec
;
1531 /* `:heuristic-mask t'
1533 means build a mask heuristically.
1534 `:heuristic-mask (R G B)'
1535 `:mask (heuristic (R G B))'
1536 means build a mask from color (R G B) in the
1539 means remove a mask, if any. */
1541 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1543 x_build_heuristic_mask (f
, img
, mask
);
1548 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1550 if (EQ (mask
, Qheuristic
))
1551 x_build_heuristic_mask (f
, img
, Qt
);
1552 else if (CONSP (mask
)
1553 && EQ (XCAR (mask
), Qheuristic
))
1555 if (CONSP (XCDR (mask
)))
1556 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1558 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1560 else if (NILP (mask
) && found_p
&& img
->mask
)
1562 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1563 img
->mask
= NO_PIXMAP
;
1568 /* Should we apply an image transformation algorithm? */
1569 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1570 if (EQ (conversion
, Qdisabled
))
1571 x_disable_image (f
, img
);
1572 else if (EQ (conversion
, Qlaplace
))
1574 else if (EQ (conversion
, Qemboss
))
1576 else if (CONSP (conversion
)
1577 && EQ (XCAR (conversion
), Qedge_detection
))
1580 tem
= XCDR (conversion
);
1582 x_edge_detection (f
, img
,
1583 Fplist_get (tem
, QCmatrix
),
1584 Fplist_get (tem
, QCcolor_adjustment
));
1590 /* Return the id of image with Lisp specification SPEC on frame F.
1591 SPEC must be a valid Lisp image specification (see valid_image_p). */
1594 lookup_image (f
, spec
)
1598 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1600 /* Work around a problem with MinGW builds of graphics libraries
1601 not honoring calling conventions. */
1607 struct gcpro gcpro1
;
1610 /* F must be a window-system frame, and SPEC must be a valid image
1612 xassert (FRAME_WINDOW_P (f
));
1613 xassert (valid_image_p (spec
));
1617 /* Look up SPEC in the hash table of the image cache. */
1618 hash
= sxhash (spec
, 0);
1619 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1621 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1622 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1625 /* If not found, create a new image and cache it. */
1628 extern Lisp_Object Qpostscript
;
1631 img
= make_image (spec
, hash
);
1632 cache_image (f
, img
);
1633 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1635 /* If we can't load the image, and we don't have a width and
1636 height, use some arbitrary width and height so that we can
1637 draw a rectangle for it. */
1638 if (img
->load_failed_p
)
1642 value
= image_spec_value (spec
, QCwidth
, NULL
);
1643 img
->width
= (INTEGERP (value
)
1644 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1645 value
= image_spec_value (spec
, QCheight
, NULL
);
1646 img
->height
= (INTEGERP (value
)
1647 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1651 /* Handle image type independent image attributes
1652 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1653 `:background COLOR'. */
1654 Lisp_Object ascent
, margin
, relief
, bg
;
1656 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1657 if (INTEGERP (ascent
))
1658 img
->ascent
= XFASTINT (ascent
);
1659 else if (EQ (ascent
, Qcenter
))
1660 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1662 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1663 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1664 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1665 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1666 && INTEGERP (XCDR (margin
)))
1668 if (XINT (XCAR (margin
)) > 0)
1669 img
->hmargin
= XFASTINT (XCAR (margin
));
1670 if (XINT (XCDR (margin
)) > 0)
1671 img
->vmargin
= XFASTINT (XCDR (margin
));
1674 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1675 if (INTEGERP (relief
))
1677 img
->relief
= XINT (relief
);
1678 img
->hmargin
+= abs (img
->relief
);
1679 img
->vmargin
+= abs (img
->relief
);
1682 if (! img
->background_valid
)
1684 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1688 = x_alloc_image_color (f
, img
, bg
,
1689 FRAME_BACKGROUND_PIXEL (f
));
1690 img
->background_valid
= 1;
1694 /* Do image transformations and compute masks, unless we
1695 don't have the image yet. */
1696 if (!EQ (*img
->type
->type
, Qpostscript
))
1697 postprocess_image (f
, img
);
1703 /* We're using IMG, so set its timestamp to `now'. */
1704 EMACS_GET_TIME (now
);
1705 img
->timestamp
= EMACS_SECS (now
);
1709 /* Value is the image id. */
1714 /* Cache image IMG in the image cache of frame F. */
1717 cache_image (f
, img
)
1721 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1724 /* Find a free slot in c->images. */
1725 for (i
= 0; i
< c
->used
; ++i
)
1726 if (c
->images
[i
] == NULL
)
1729 /* If no free slot found, maybe enlarge c->images. */
1730 if (i
== c
->used
&& c
->used
== c
->size
)
1733 c
->images
= (struct image
**) xrealloc (c
->images
,
1734 c
->size
* sizeof *c
->images
);
1737 /* Add IMG to c->images, and assign IMG an id. */
1743 /* Add IMG to the cache's hash table. */
1744 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1745 img
->next
= c
->buckets
[i
];
1747 img
->next
->prev
= img
;
1749 c
->buckets
[i
] = img
;
1753 /* Call FN on every image in the image cache of frame F. Used to mark
1754 Lisp Objects in the image cache. */
1757 forall_images_in_image_cache (f
, fn
)
1759 void (*fn
) P_ ((struct image
*img
));
1761 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1763 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1767 for (i
= 0; i
< c
->used
; ++i
)
1776 /***********************************************************************
1777 X / MAC / W32 support code
1778 ***********************************************************************/
1782 /* Macro for defining functions that will be loaded from image DLLs. */
1783 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1785 /* Macro for loading those image functions from the library. */
1786 #define LOAD_IMGLIB_FN(lib,func) { \
1787 fn_##func = (void *) GetProcAddress (lib, #func); \
1788 if (!fn_##func) return 0; \
1791 #endif /* HAVE_NTGUI */
1793 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
1794 XImagePtr
*, Pixmap
*));
1795 static void x_destroy_x_image
P_ ((XImagePtr
));
1796 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
1799 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1800 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1801 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1802 via xmalloc. Print error messages via image_error if an error
1803 occurs. Value is non-zero if successful.
1805 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1806 should indicate the bit depth of the image. */
1809 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
1811 int width
, height
, depth
;
1815 #ifdef HAVE_X_WINDOWS
1816 Display
*display
= FRAME_X_DISPLAY (f
);
1817 Window window
= FRAME_X_WINDOW (f
);
1818 Screen
*screen
= FRAME_X_SCREEN (f
);
1820 xassert (interrupt_input_blocked
);
1823 depth
= DefaultDepthOfScreen (screen
);
1824 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
1825 depth
, ZPixmap
, 0, NULL
, width
, height
,
1826 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
1829 image_error ("Unable to allocate X image", Qnil
, Qnil
);
1833 /* Allocate image raster. */
1834 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
1836 /* Allocate a pixmap of the same size. */
1837 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1838 if (*pixmap
== NO_PIXMAP
)
1840 x_destroy_x_image (*ximg
);
1842 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1847 #endif /* HAVE_X_WINDOWS */
1851 BITMAPINFOHEADER
*header
;
1853 int scanline_width_bits
;
1855 int palette_colors
= 0;
1860 if (depth
!= 1 && depth
!= 4 && depth
!= 8
1861 && depth
!= 16 && depth
!= 24 && depth
!= 32)
1863 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
1867 scanline_width_bits
= width
* depth
;
1868 remainder
= scanline_width_bits
% 32;
1871 scanline_width_bits
+= 32 - remainder
;
1873 /* Bitmaps with a depth less than 16 need a palette. */
1874 /* BITMAPINFO structure already contains the first RGBQUAD. */
1876 palette_colors
= 1 << depth
- 1;
1878 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
1881 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
1885 header
= &((*ximg
)->info
.bmiHeader
);
1886 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
1887 header
->biSize
= sizeof (*header
);
1888 header
->biWidth
= width
;
1889 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
1890 header
->biPlanes
= 1;
1891 header
->biBitCount
= depth
;
1892 header
->biCompression
= BI_RGB
;
1893 header
->biClrUsed
= palette_colors
;
1895 /* TODO: fill in palette. */
1898 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
1899 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
1900 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
1901 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
1902 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
1903 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
1904 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
1905 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
1908 hdc
= get_frame_dc (f
);
1910 /* Create a DIBSection and raster array for the bitmap,
1911 and store its handle in *pixmap. */
1912 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
1913 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
1914 &((*ximg
)->data
), NULL
, 0);
1916 /* Realize display palette and garbage all frames. */
1917 release_frame_dc (f
, hdc
);
1919 if (*pixmap
== NULL
)
1921 DWORD err
= GetLastError();
1922 Lisp_Object errcode
;
1923 /* All system errors are < 10000, so the following is safe. */
1924 XSETINT (errcode
, (int) err
);
1925 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
1926 x_destroy_x_image (*ximg
);
1932 #endif /* HAVE_NTGUI */
1935 Display
*display
= FRAME_X_DISPLAY (f
);
1936 Window window
= FRAME_X_WINDOW (f
);
1938 xassert (interrupt_input_blocked
);
1940 /* Allocate a pixmap of the same size. */
1941 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1942 if (*pixmap
== NO_PIXMAP
)
1944 x_destroy_x_image (*ximg
);
1946 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1950 LockPixels (GetGWorldPixMap (*pixmap
));
1958 /* Destroy XImage XIMG. Free XIMG->data. */
1961 x_destroy_x_image (ximg
)
1964 xassert (interrupt_input_blocked
);
1967 #ifdef HAVE_X_WINDOWS
1970 XDestroyImage (ximg
);
1971 #endif /* HAVE_X_WINDOWS */
1973 /* Data will be freed by DestroyObject. */
1976 #endif /* HAVE_NTGUI */
1978 XDestroyImage (ximg
);
1984 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
1985 are width and height of both the image and pixmap. */
1988 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
1994 #ifdef HAVE_X_WINDOWS
1997 xassert (interrupt_input_blocked
);
1998 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
1999 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2000 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2001 #endif /* HAVE_X_WINDOWS */
2004 #if 0 /* I don't think this is necessary looking at where it is used. */
2005 HDC hdc
= get_frame_dc (f
);
2006 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2007 release_frame_dc (f
, hdc
);
2009 #endif /* HAVE_NTGUI */
2012 xassert (ximg
== pixmap
);
2017 /***********************************************************************
2019 ***********************************************************************/
2021 static unsigned char *slurp_file
P_ ((char *, int *));
2024 /* Find image file FILE. Look in data-directory, then
2025 x-bitmap-file-path. Value is the full name of the file found, or
2026 nil if not found. */
2029 x_find_image_file (file
)
2032 Lisp_Object file_found
, search_path
;
2033 struct gcpro gcpro1
, gcpro2
;
2037 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2038 GCPRO2 (file_found
, search_path
);
2040 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2041 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2053 /* Read FILE into memory. Value is a pointer to a buffer allocated
2054 with xmalloc holding FILE's contents. Value is null if an error
2055 occurred. *SIZE is set to the size of the file. */
2057 static unsigned char *
2058 slurp_file (file
, size
)
2063 unsigned char *buf
= NULL
;
2066 if (stat (file
, &st
) == 0
2067 && (fp
= fopen (file
, "rb")) != NULL
2068 && (buf
= (char *) xmalloc (st
.st_size
),
2069 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2092 /***********************************************************************
2093 MAC Image Load Functions
2094 ***********************************************************************/
2096 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2099 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2103 find_image_fsspec (specified_file
, file
, fss
)
2104 Lisp_Object specified_file
, *file
;
2107 #if TARGET_API_MAC_CARBON
2110 Str255 mac_pathname
;
2114 *file
= x_find_image_file (specified_file
);
2115 if (!STRINGP (*file
))
2116 return fnfErr
; /* file or directory not found;
2117 incomplete pathname */
2118 /* Try to open the image file. */
2119 #if TARGET_API_MAC_CARBON
2120 err
= FSPathMakeRef (SDATA (*file
), &fsr
, NULL
);
2122 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
2124 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
2126 c2pstr (mac_pathname
);
2127 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
2133 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2141 GraphicsImportComponent gi
;
2144 short draw_all_pixels
;
2145 Lisp_Object specified_bg
;
2150 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2154 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2159 /* read from file system spec */
2160 err
= GraphicsImportSetDataFile (gi
, fss
);
2163 image_error ("Cannot set fsspec to graphics importer for '%s'",
2170 /* read from data handle */
2171 err
= GraphicsImportSetDataHandle (gi
, dh
);
2174 image_error ("Cannot set data handle to graphics importer for `%s'",
2179 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
2182 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2185 width
= img
->width
= rect
.right
- rect
.left
;
2186 height
= img
->height
= rect
.bottom
- rect
.top
;
2187 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2189 /* Don't check the error code here. It may have an undocumented
2193 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2197 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2199 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2200 if (!STRINGP (specified_bg
) ||
2201 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2203 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2204 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2205 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2206 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2210 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2212 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2217 GetGWorld (&old_port
, &old_gdh
);
2218 SetGWorld (ximg
, NULL
);
2219 bg_color
.red
= color
.red
;
2220 bg_color
.green
= color
.green
;
2221 bg_color
.blue
= color
.blue
;
2222 RGBBackColor (&bg_color
);
2223 #if TARGET_API_MAC_CARBON
2224 GetPortBounds (ximg
, &rect
);
2227 EraseRect (&(ximg
->portRect
));
2229 SetGWorld (old_port
, old_gdh
);
2231 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2232 GraphicsImportDraw (gi
);
2233 CloseComponent (gi
);
2235 /* Maybe fill in the background field while we have ximg handy. */
2236 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2237 IMAGE_BACKGROUND (img
, f
, ximg
);
2239 /* Put the image into the pixmap. */
2240 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2241 x_destroy_x_image (ximg
);
2245 CloseComponent (gi
);
2250 /* Load an image using the QuickTime Graphics Importer.
2251 Note: The alpha channel does not work for PNG images. */
2253 image_load_quicktime (f
, img
, type
)
2258 Lisp_Object specified_file
;
2259 Lisp_Object specified_data
;
2262 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2263 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2265 if (NILP (specified_data
))
2267 /* Read from a file */
2271 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2275 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2277 image_error ("Cannot open `%s'", file
, Qnil
);
2280 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2284 /* Memory source! */
2288 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2291 image_error ("Cannot allocate data handle for `%s'",
2295 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2303 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2304 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2305 So don't use this function directly but determine at runtime
2306 whether it exists. */
2307 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2308 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2309 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2313 init_image_func_pointer ()
2315 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2317 MyCGImageCreateWithPNGDataProvider
2318 = (CGImageCreateWithPNGDataProviderProcType
)
2319 NSAddressOfSymbol (NSLookupAndBindSymbol
2320 ("_CGImageCreateWithPNGDataProvider"));
2323 MyCGImageCreateWithPNGDataProvider
= NULL
;
2328 image_load_quartz2d (f
, img
, png_p
)
2333 Lisp_Object file
, specified_file
;
2334 Lisp_Object specified_data
, specified_bg
;
2335 struct gcpro gcpro1
;
2336 CGDataProviderRef source
;
2340 XImagePtr ximg
= NULL
;
2341 CGContextRef context
;
2344 /* Open the file. */
2345 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2346 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2351 if (NILP (specified_data
))
2356 file
= x_find_image_file (specified_file
);
2357 if (!STRINGP (file
))
2359 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2363 path
= CFStringCreateWithCString (NULL
, SDATA (file
),
2364 kCFStringEncodingUTF8
);
2365 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2366 kCFURLPOSIXPathStyle
, 0);
2368 source
= CGDataProviderCreateWithURL (url
);
2372 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2373 SBYTES (specified_data
), NULL
);
2376 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2377 kCGRenderingIntentDefault
);
2379 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2380 kCGRenderingIntentDefault
);
2382 CGDataProviderRelease (source
);
2386 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2392 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2393 if (!STRINGP (specified_bg
) ||
2394 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2396 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2397 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2398 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2399 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2402 width
= img
->width
= CGImageGetWidth (image
);
2403 height
= img
->height
= CGImageGetHeight (image
);
2404 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2406 CGImageRelease (image
);
2410 rectangle
= CGRectMake (0, 0, width
, height
);
2411 QDBeginCGContext (ximg
, &context
);
2414 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2415 color
.green
/ 65535.0,
2416 color
.blue
/ 65535.0, 1.0);
2417 CGContextFillRect (context
, rectangle
);
2419 CGContextDrawImage (context
, rectangle
, image
);
2420 QDEndCGContext (ximg
, &context
);
2421 CGImageRelease (image
);
2423 /* Maybe fill in the background field while we have ximg handy. */
2424 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2425 IMAGE_BACKGROUND (img
, f
, ximg
);
2427 /* Put the image into the pixmap. */
2428 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2429 x_destroy_x_image (ximg
);
2438 /***********************************************************************
2440 ***********************************************************************/
2442 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2443 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2444 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2445 unsigned char *, unsigned char *));
2446 static int xbm_image_p
P_ ((Lisp_Object object
));
2447 static int xbm_read_bitmap_data
P_ ((unsigned char *, unsigned char *,
2448 int *, int *, unsigned char **));
2449 static int xbm_file_p
P_ ((Lisp_Object
));
2452 /* Indices of image specification fields in xbm_format, below. */
2454 enum xbm_keyword_index
2472 /* Vector of image_keyword structures describing the format
2473 of valid XBM image specifications. */
2475 static struct image_keyword xbm_format
[XBM_LAST
] =
2477 {":type", IMAGE_SYMBOL_VALUE
, 1},
2478 {":file", IMAGE_STRING_VALUE
, 0},
2479 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2480 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2481 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2482 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2483 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2484 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2485 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2486 {":relief", IMAGE_INTEGER_VALUE
, 0},
2487 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2488 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2489 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2492 /* Structure describing the image type XBM. */
2494 static struct image_type xbm_type
=
2503 /* Tokens returned from xbm_scan. */
2512 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2513 A valid specification is a list starting with the symbol `image'
2514 The rest of the list is a property list which must contain an
2517 If the specification specifies a file to load, it must contain
2518 an entry `:file FILENAME' where FILENAME is a string.
2520 If the specification is for a bitmap loaded from memory it must
2521 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2522 WIDTH and HEIGHT are integers > 0. DATA may be:
2524 1. a string large enough to hold the bitmap data, i.e. it must
2525 have a size >= (WIDTH + 7) / 8 * HEIGHT
2527 2. a bool-vector of size >= WIDTH * HEIGHT
2529 3. a vector of strings or bool-vectors, one for each line of the
2532 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2533 may not be specified in this case because they are defined in the
2536 Both the file and data forms may contain the additional entries
2537 `:background COLOR' and `:foreground COLOR'. If not present,
2538 foreground and background of the frame on which the image is
2539 displayed is used. */
2542 xbm_image_p (object
)
2545 struct image_keyword kw
[XBM_LAST
];
2547 bcopy (xbm_format
, kw
, sizeof kw
);
2548 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2551 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2553 if (kw
[XBM_FILE
].count
)
2555 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2558 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2560 /* In-memory XBM file. */
2561 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2569 /* Entries for `:width', `:height' and `:data' must be present. */
2570 if (!kw
[XBM_WIDTH
].count
2571 || !kw
[XBM_HEIGHT
].count
2572 || !kw
[XBM_DATA
].count
)
2575 data
= kw
[XBM_DATA
].value
;
2576 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2577 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2579 /* Check type of data, and width and height against contents of
2585 /* Number of elements of the vector must be >= height. */
2586 if (XVECTOR (data
)->size
< height
)
2589 /* Each string or bool-vector in data must be large enough
2590 for one line of the image. */
2591 for (i
= 0; i
< height
; ++i
)
2593 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2598 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2601 else if (BOOL_VECTOR_P (elt
))
2603 if (XBOOL_VECTOR (elt
)->size
< width
)
2610 else if (STRINGP (data
))
2613 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2616 else if (BOOL_VECTOR_P (data
))
2618 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2629 /* Scan a bitmap file. FP is the stream to read from. Value is
2630 either an enumerator from enum xbm_token, or a character for a
2631 single-character token, or 0 at end of file. If scanning an
2632 identifier, store the lexeme of the identifier in SVAL. If
2633 scanning a number, store its value in *IVAL. */
2636 xbm_scan (s
, end
, sval
, ival
)
2637 unsigned char **s
, *end
;
2645 /* Skip white space. */
2646 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2651 else if (isdigit (c
))
2653 int value
= 0, digit
;
2655 if (c
== '0' && *s
< end
)
2658 if (c
== 'x' || c
== 'X')
2665 else if (c
>= 'a' && c
<= 'f')
2666 digit
= c
- 'a' + 10;
2667 else if (c
>= 'A' && c
<= 'F')
2668 digit
= c
- 'A' + 10;
2671 value
= 16 * value
+ digit
;
2674 else if (isdigit (c
))
2678 && (c
= *(*s
)++, isdigit (c
)))
2679 value
= 8 * value
+ c
- '0';
2686 && (c
= *(*s
)++, isdigit (c
)))
2687 value
= 10 * value
+ c
- '0';
2695 else if (isalpha (c
) || c
== '_')
2699 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2706 else if (c
== '/' && **s
== '*')
2708 /* C-style comment. */
2710 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2724 /* Create a Windows bitmap from X bitmap data. */
2726 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2728 static unsigned char swap_nibble
[16]
2729 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2730 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2731 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2732 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2734 unsigned char *bits
, *p
;
2737 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2738 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2739 bits
= (unsigned char *) alloca (height
* w2
);
2740 bzero (bits
, height
* w2
);
2741 for (i
= 0; i
< height
; i
++)
2744 for (j
= 0; j
< w1
; j
++)
2746 /* Bitswap XBM bytes to match how Windows does things. */
2747 unsigned char c
= *data
++;
2748 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2749 | (swap_nibble
[(c
>>4) & 0xf]));
2752 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2757 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
2760 COLORREF foreground
, background
;
2762 HDC hdc
, old_img_dc
, new_img_dc
;
2763 HGDIOBJ old_prev
, new_prev
;
2766 hdc
= get_frame_dc (f
);
2767 old_img_dc
= CreateCompatibleDC (hdc
);
2768 new_img_dc
= CreateCompatibleDC (hdc
);
2769 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2770 release_frame_dc (f
, hdc
);
2771 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2772 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2773 SetTextColor (new_img_dc
, foreground
);
2774 SetBkColor (new_img_dc
, background
);
2776 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2779 SelectObject (old_img_dc
, old_prev
);
2780 SelectObject (new_img_dc
, new_prev
);
2781 DeleteDC (old_img_dc
);
2782 DeleteDC (new_img_dc
);
2783 DeleteObject (img
->pixmap
);
2784 if (new_pixmap
== 0)
2785 fprintf (stderr
, "Failed to convert image to color.\n");
2787 img
->pixmap
= new_pixmap
;
2790 #define XBM_BIT_SHUFFLE(b) (~(b))
2794 #define XBM_BIT_SHUFFLE(b) (b)
2796 #endif /* HAVE_NTGUI */
2800 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
2804 RGB_PIXEL_COLOR fg
, bg
;
2805 int non_default_colors
;
2809 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2811 /* If colors were specified, transfer the bitmap to a color one. */
2812 if (non_default_colors
)
2813 convert_mono_to_color_image (f
, img
, fg
, bg
);
2816 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2819 img
->width
, img
->height
,
2821 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2822 #endif /* HAVE_NTGUI */
2827 /* Replacement for XReadBitmapFileData which isn't available under old
2828 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2829 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2830 the image. Return in *DATA the bitmap data allocated with xmalloc.
2831 Value is non-zero if successful. DATA null means just test if
2832 CONTENTS looks like an in-memory XBM file. */
2835 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
2836 unsigned char *contents
, *end
;
2837 int *width
, *height
;
2838 unsigned char **data
;
2840 unsigned char *s
= contents
;
2841 char buffer
[BUFSIZ
];
2844 int bytes_per_line
, i
, nbytes
;
2850 LA1 = xbm_scan (&s, end, buffer, &value)
2852 #define expect(TOKEN) \
2853 if (LA1 != (TOKEN)) \
2858 #define expect_ident(IDENT) \
2859 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2864 *width
= *height
= -1;
2867 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2869 /* Parse defines for width, height and hot-spots. */
2873 expect_ident ("define");
2874 expect (XBM_TK_IDENT
);
2876 if (LA1
== XBM_TK_NUMBER
);
2878 char *p
= strrchr (buffer
, '_');
2879 p
= p
? p
+ 1 : buffer
;
2880 if (strcmp (p
, "width") == 0)
2882 else if (strcmp (p
, "height") == 0)
2885 expect (XBM_TK_NUMBER
);
2888 if (*width
< 0 || *height
< 0)
2890 else if (data
== NULL
)
2893 /* Parse bits. Must start with `static'. */
2894 expect_ident ("static");
2895 if (LA1
== XBM_TK_IDENT
)
2897 if (strcmp (buffer
, "unsigned") == 0)
2900 expect_ident ("char");
2902 else if (strcmp (buffer
, "short") == 0)
2906 if (*width
% 16 && *width
% 16 < 9)
2909 else if (strcmp (buffer
, "char") == 0)
2917 expect (XBM_TK_IDENT
);
2923 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
2924 nbytes
= bytes_per_line
* *height
;
2925 p
= *data
= (char *) xmalloc (nbytes
);
2929 for (i
= 0; i
< nbytes
; i
+= 2)
2932 expect (XBM_TK_NUMBER
);
2934 *p
++ = XBM_BIT_SHUFFLE (val
);
2935 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
2936 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
2938 if (LA1
== ',' || LA1
== '}')
2946 for (i
= 0; i
< nbytes
; ++i
)
2949 expect (XBM_TK_NUMBER
);
2951 *p
++ = XBM_BIT_SHUFFLE (val
);
2953 if (LA1
== ',' || LA1
== '}')
2978 /* Load XBM image IMG which will be displayed on frame F from buffer
2979 CONTENTS. END is the end of the buffer. Value is non-zero if
2983 xbm_load_image (f
, img
, contents
, end
)
2986 unsigned char *contents
, *end
;
2989 unsigned char *data
;
2992 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
2995 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
2996 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
2997 int non_default_colors
= 0;
3000 xassert (img
->width
> 0 && img
->height
> 0);
3002 /* Get foreground and background colors, maybe allocate colors. */
3003 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3006 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3007 non_default_colors
= 1;
3009 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3012 background
= x_alloc_image_color (f
, img
, value
, background
);
3013 img
->background
= background
;
3014 img
->background_valid
= 1;
3015 non_default_colors
= 1;
3018 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3019 foreground
, background
,
3020 non_default_colors
);
3023 if (img
->pixmap
== NO_PIXMAP
)
3025 x_clear_image (f
, img
);
3026 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3032 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3038 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3045 return (STRINGP (data
)
3046 && xbm_read_bitmap_data (SDATA (data
),
3053 /* Fill image IMG which is used on frame F with pixmap data. Value is
3054 non-zero if successful. */
3062 Lisp_Object file_name
;
3064 xassert (xbm_image_p (img
->spec
));
3066 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3067 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3068 if (STRINGP (file_name
))
3071 unsigned char *contents
;
3073 struct gcpro gcpro1
;
3075 file
= x_find_image_file (file_name
);
3077 if (!STRINGP (file
))
3079 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3084 contents
= slurp_file (SDATA (file
), &size
);
3085 if (contents
== NULL
)
3087 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3092 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3097 struct image_keyword fmt
[XBM_LAST
];
3099 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3100 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3101 int non_default_colors
= 0;
3104 int in_memory_file_p
= 0;
3106 /* See if data looks like an in-memory XBM file. */
3107 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3108 in_memory_file_p
= xbm_file_p (data
);
3110 /* Parse the image specification. */
3111 bcopy (xbm_format
, fmt
, sizeof fmt
);
3112 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3115 /* Get specified width, and height. */
3116 if (!in_memory_file_p
)
3118 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3119 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3120 xassert (img
->width
> 0 && img
->height
> 0);
3123 /* Get foreground and background colors, maybe allocate colors. */
3124 if (fmt
[XBM_FOREGROUND
].count
3125 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3127 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3129 non_default_colors
= 1;
3132 if (fmt
[XBM_BACKGROUND
].count
3133 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3135 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3137 non_default_colors
= 1;
3140 if (in_memory_file_p
)
3141 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3150 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3152 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3153 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3155 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3157 bcopy (SDATA (line
), p
, nbytes
);
3159 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3162 else if (STRINGP (data
))
3163 bits
= SDATA (data
);
3165 bits
= XBOOL_VECTOR (data
)->data
;
3167 /* Create the pixmap. */
3169 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3170 foreground
, background
,
3171 non_default_colors
);
3176 image_error ("Unable to create pixmap for XBM image `%s'",
3178 x_clear_image (f
, img
);
3188 /***********************************************************************
3190 ***********************************************************************/
3192 #if defined (HAVE_XPM) || defined (MAC_OS)
3194 static int xpm_image_p
P_ ((Lisp_Object object
));
3195 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3196 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3198 #endif /* HAVE_XPM || MAC_OS */
3202 /* Indicate to xpm.h that we don't have Xlib. */
3204 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3205 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3206 #define XColor xpm_XColor
3207 #define XImage xpm_XImage
3208 #define Display xpm_Display
3209 #define PIXEL_ALREADY_TYPEDEFED
3210 #include "X11/xpm.h"
3215 #undef PIXEL_ALREADY_TYPEDEFED
3217 #include "X11/xpm.h"
3218 #endif /* HAVE_NTGUI */
3219 #endif /* HAVE_XPM */
3221 #if defined (HAVE_XPM) || defined (MAC_OS)
3222 /* The symbol `xpm' identifying XPM-format images. */
3226 /* Indices of image specification fields in xpm_format, below. */
3228 enum xpm_keyword_index
3244 /* Vector of image_keyword structures describing the format
3245 of valid XPM image specifications. */
3247 static struct image_keyword xpm_format
[XPM_LAST
] =
3249 {":type", IMAGE_SYMBOL_VALUE
, 1},
3250 {":file", IMAGE_STRING_VALUE
, 0},
3251 {":data", IMAGE_STRING_VALUE
, 0},
3252 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3253 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3254 {":relief", IMAGE_INTEGER_VALUE
, 0},
3255 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3256 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3257 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3258 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3259 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3262 /* Structure describing the image type XPM. */
3264 static struct image_type xpm_type
=
3273 #ifdef HAVE_X_WINDOWS
3275 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3276 functions for allocating image colors. Our own functions handle
3277 color allocation failures more gracefully than the ones on the XPM
3280 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3281 #define ALLOC_XPM_COLORS
3283 #endif /* HAVE_X_WINDOWS */
3285 #ifdef ALLOC_XPM_COLORS
3287 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3288 static void xpm_free_color_cache
P_ ((void));
3289 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3290 static int xpm_color_bucket
P_ ((char *));
3291 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3294 /* An entry in a hash table used to cache color definitions of named
3295 colors. This cache is necessary to speed up XPM image loading in
3296 case we do color allocations ourselves. Without it, we would need
3297 a call to XParseColor per pixel in the image. */
3299 struct xpm_cached_color
3301 /* Next in collision chain. */
3302 struct xpm_cached_color
*next
;
3304 /* Color definition (RGB and pixel color). */
3311 /* The hash table used for the color cache, and its bucket vector
3314 #define XPM_COLOR_CACHE_BUCKETS 1001
3315 struct xpm_cached_color
**xpm_color_cache
;
3317 /* Initialize the color cache. */
3320 xpm_init_color_cache (f
, attrs
)
3322 XpmAttributes
*attrs
;
3324 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3325 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3326 memset (xpm_color_cache
, 0, nbytes
);
3327 init_color_table ();
3329 if (attrs
->valuemask
& XpmColorSymbols
)
3334 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3335 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3336 attrs
->colorsymbols
[i
].value
, &color
))
3338 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3340 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3345 /* Free the color cache. */
3348 xpm_free_color_cache ()
3350 struct xpm_cached_color
*p
, *next
;
3353 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3354 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3360 xfree (xpm_color_cache
);
3361 xpm_color_cache
= NULL
;
3362 free_color_table ();
3365 /* Return the bucket index for color named COLOR_NAME in the color
3369 xpm_color_bucket (color_name
)
3375 for (s
= color_name
; *s
; ++s
)
3377 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3381 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3382 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3385 static struct xpm_cached_color
*
3386 xpm_cache_color (f
, color_name
, color
, bucket
)
3393 struct xpm_cached_color
*p
;
3396 bucket
= xpm_color_bucket (color_name
);
3398 nbytes
= sizeof *p
+ strlen (color_name
);
3399 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3400 strcpy (p
->name
, color_name
);
3402 p
->next
= xpm_color_cache
[bucket
];
3403 xpm_color_cache
[bucket
] = p
;
3407 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3408 return the cached definition in *COLOR. Otherwise, make a new
3409 entry in the cache and allocate the color. Value is zero if color
3410 allocation failed. */
3413 xpm_lookup_color (f
, color_name
, color
)
3418 struct xpm_cached_color
*p
;
3419 int h
= xpm_color_bucket (color_name
);
3421 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3422 if (strcmp (p
->name
, color_name
) == 0)
3427 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3430 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3432 p
= xpm_cache_color (f
, color_name
, color
, h
);
3434 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3435 with transparency, and it's useful. */
3436 else if (strcmp ("opaque", color_name
) == 0)
3438 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3439 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3440 p
= xpm_cache_color (f
, color_name
, color
, h
);
3447 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3448 CLOSURE is a pointer to the frame on which we allocate the
3449 color. Return in *COLOR the allocated color. Value is non-zero
3453 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3460 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3464 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3465 is a pointer to the frame on which we allocate the color. Value is
3466 non-zero if successful. */
3469 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3479 #endif /* ALLOC_XPM_COLORS */
3484 /* XPM library details. */
3486 DEF_IMGLIB_FN (XpmFreeAttributes
);
3487 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3488 DEF_IMGLIB_FN (XpmReadFileToImage
);
3489 DEF_IMGLIB_FN (XImageFree
);
3493 init_xpm_functions (void)
3497 if (!(library
= LoadLibrary ("libXpm.dll")))
3500 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3501 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3502 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3503 LOAD_IMGLIB_FN (library
, XImageFree
);
3507 #endif /* HAVE_NTGUI */
3510 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3511 for XPM images. Such a list must consist of conses whose car and
3515 xpm_valid_color_symbols_p (color_symbols
)
3516 Lisp_Object color_symbols
;
3518 while (CONSP (color_symbols
))
3520 Lisp_Object sym
= XCAR (color_symbols
);
3522 || !STRINGP (XCAR (sym
))
3523 || !STRINGP (XCDR (sym
)))
3525 color_symbols
= XCDR (color_symbols
);
3528 return NILP (color_symbols
);
3532 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3535 xpm_image_p (object
)
3538 struct image_keyword fmt
[XPM_LAST
];
3539 bcopy (xpm_format
, fmt
, sizeof fmt
);
3540 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3541 /* Either `:file' or `:data' must be present. */
3542 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3543 /* Either no `:color-symbols' or it's a list of conses
3544 whose car and cdr are strings. */
3545 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3546 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3549 #endif /* HAVE_XPM || MAC_OS */
3551 /* Load image IMG which will be displayed on frame F. Value is
3552 non-zero if successful. */
3562 XpmAttributes attrs
;
3563 Lisp_Object specified_file
, color_symbols
;
3566 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3567 #endif /* HAVE_NTGUI */
3569 /* Configure the XPM lib. Use the visual of frame F. Allocate
3570 close colors. Return colors allocated. */
3571 bzero (&attrs
, sizeof attrs
);
3574 attrs
.visual
= FRAME_X_VISUAL (f
);
3575 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3576 attrs
.valuemask
|= XpmVisual
;
3577 attrs
.valuemask
|= XpmColormap
;
3578 #endif /* HAVE_NTGUI */
3580 #ifdef ALLOC_XPM_COLORS
3581 /* Allocate colors with our own functions which handle
3582 failing color allocation more gracefully. */
3583 attrs
.color_closure
= f
;
3584 attrs
.alloc_color
= xpm_alloc_color
;
3585 attrs
.free_colors
= xpm_free_colors
;
3586 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3587 #else /* not ALLOC_XPM_COLORS */
3588 /* Let the XPM lib allocate colors. */
3589 attrs
.valuemask
|= XpmReturnAllocPixels
;
3590 #ifdef XpmAllocCloseColors
3591 attrs
.alloc_close_colors
= 1;
3592 attrs
.valuemask
|= XpmAllocCloseColors
;
3593 #else /* not XpmAllocCloseColors */
3594 attrs
.closeness
= 600;
3595 attrs
.valuemask
|= XpmCloseness
;
3596 #endif /* not XpmAllocCloseColors */
3597 #endif /* ALLOC_XPM_COLORS */
3599 /* If image specification contains symbolic color definitions, add
3600 these to `attrs'. */
3601 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3602 if (CONSP (color_symbols
))
3605 XpmColorSymbol
*xpm_syms
;
3608 attrs
.valuemask
|= XpmColorSymbols
;
3610 /* Count number of symbols. */
3611 attrs
.numsymbols
= 0;
3612 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3615 /* Allocate an XpmColorSymbol array. */
3616 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3617 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3618 bzero (xpm_syms
, size
);
3619 attrs
.colorsymbols
= xpm_syms
;
3621 /* Fill the color symbol array. */
3622 for (tail
= color_symbols
, i
= 0;
3624 ++i
, tail
= XCDR (tail
))
3626 Lisp_Object name
= XCAR (XCAR (tail
));
3627 Lisp_Object color
= XCDR (XCAR (tail
));
3628 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3629 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3630 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3631 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3635 /* Create a pixmap for the image, either from a file, or from a
3636 string buffer containing data in the same format as an XPM file. */
3637 #ifdef ALLOC_XPM_COLORS
3638 xpm_init_color_cache (f
, &attrs
);
3641 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3645 HDC frame_dc
= get_frame_dc (f
);
3646 hdc
= CreateCompatibleDC (frame_dc
);
3647 release_frame_dc (f
, frame_dc
);
3649 #endif /* HAVE_NTGUI */
3651 if (STRINGP (specified_file
))
3653 Lisp_Object file
= x_find_image_file (specified_file
);
3654 if (!STRINGP (file
))
3656 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3661 /* XpmReadFileToPixmap is not available in the Windows port of
3662 libxpm. But XpmReadFileToImage almost does what we want. */
3663 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3664 &xpm_image
, &xpm_mask
,
3667 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3668 SDATA (file
), &img
->pixmap
, &img
->mask
,
3670 #endif /* HAVE_NTGUI */
3674 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3676 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3677 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3678 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3679 &xpm_image
, &xpm_mask
,
3682 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3684 &img
->pixmap
, &img
->mask
,
3686 #endif /* HAVE_NTGUI */
3689 if (rc
== XpmSuccess
)
3691 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3692 img
->colors
= colors_in_color_table (&img
->ncolors
);
3693 #else /* not ALLOC_XPM_COLORS */
3697 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3698 plus some duplicate attributes. */
3699 if (xpm_image
&& xpm_image
->bitmap
)
3701 img
->pixmap
= xpm_image
->bitmap
;
3702 /* XImageFree in libXpm frees XImage struct without destroying
3703 the bitmap, which is what we want. */
3704 fn_XImageFree (xpm_image
);
3706 if (xpm_mask
&& xpm_mask
->bitmap
)
3708 /* The mask appears to be inverted compared with what we expect.
3709 TODO: invert our expectations. See other places where we
3710 have to invert bits because our idea of masks is backwards. */
3712 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3714 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3715 SelectObject (hdc
, old_obj
);
3717 img
->mask
= xpm_mask
->bitmap
;
3718 fn_XImageFree (xpm_mask
);
3723 #endif /* HAVE_NTGUI */
3725 /* Remember allocated colors. */
3726 img
->ncolors
= attrs
.nalloc_pixels
;
3727 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3728 * sizeof *img
->colors
);
3729 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3731 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3732 #ifdef DEBUG_X_COLORS
3733 register_color (img
->colors
[i
]);
3736 #endif /* not ALLOC_XPM_COLORS */
3738 img
->width
= attrs
.width
;
3739 img
->height
= attrs
.height
;
3740 xassert (img
->width
> 0 && img
->height
> 0);
3742 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3744 fn_XpmFreeAttributes (&attrs
);
3746 XpmFreeAttributes (&attrs
);
3747 #endif /* HAVE_NTGUI */
3753 #endif /* HAVE_NTGUI */
3758 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3761 case XpmFileInvalid
:
3762 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3766 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3769 case XpmColorFailed
:
3770 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3774 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3779 #ifdef ALLOC_XPM_COLORS
3780 xpm_free_color_cache ();
3782 return rc
== XpmSuccess
;
3785 #endif /* HAVE_XPM */
3789 /* XPM support functions for Mac OS where libxpm is not available.
3790 Only XPM version 3 (without any extensions) is supported. */
3792 static int xpm_scan
P_ ((unsigned char **, unsigned char *,
3793 unsigned char **, int *));
3794 static Lisp_Object xpm_make_color_table_v
3795 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3796 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3797 static void xpm_put_color_table_v
P_ ((Lisp_Object
, unsigned char *,
3799 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3800 unsigned char *, int));
3801 static Lisp_Object xpm_make_color_table_h
3802 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3803 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3804 static void xpm_put_color_table_h
P_ ((Lisp_Object
, unsigned char *,
3806 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3807 unsigned char *, int));
3808 static int xpm_str_to_color_key
P_ ((char *));
3809 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3810 unsigned char *, unsigned char *));
3812 /* Tokens returned from xpm_scan. */
3821 /* Scan an XPM data and return a character (< 256) or a token defined
3822 by enum xpm_token above. *S and END are the start (inclusive) and
3823 the end (exclusive) addresses of the data, respectively. Advance
3824 *S while scanning. If token is either XPM_TK_IDENT or
3825 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3826 length of the corresponding token, respectively. */
3829 xpm_scan (s
, end
, beg
, len
)
3830 unsigned char **s
, *end
, **beg
;
3837 /* Skip white-space. */
3838 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3841 /* gnus-pointer.xpm uses '-' in its identifier.
3842 sb-dir-plus.xpm uses '+' in its identifier. */
3843 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
3847 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
3850 return XPM_TK_IDENT
;
3855 while (*s
< end
&& **s
!= '"')
3860 return XPM_TK_STRING
;
3864 if (*s
< end
&& **s
== '*')
3866 /* C-style comment. */
3870 while (*s
< end
&& *(*s
)++ != '*')
3873 while (*s
< end
&& **s
!= '/');
3887 /* Functions for color table lookup in XPM data. A Key is a string
3888 specifying the color of each pixel in XPM data. A value is either
3889 an integer that specifies a pixel color, Qt that specifies
3890 transparency, or Qnil for the unspecified color. If the length of
3891 the key string is one, a vector is used as a table. Otherwise, a
3892 hash table is used. */
3895 xpm_make_color_table_v (put_func
, get_func
)
3896 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3897 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3899 *put_func
= xpm_put_color_table_v
;
3900 *get_func
= xpm_get_color_table_v
;
3901 return Fmake_vector (make_number (256), Qnil
);
3905 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
3906 Lisp_Object color_table
;
3907 unsigned char *chars_start
;
3911 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
3915 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
3916 Lisp_Object color_table
;
3917 unsigned char *chars_start
;
3920 return XVECTOR (color_table
)->contents
[*chars_start
];
3924 xpm_make_color_table_h (put_func
, get_func
)
3925 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3926 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3928 *put_func
= xpm_put_color_table_h
;
3929 *get_func
= xpm_get_color_table_h
;
3930 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
3931 make_float (DEFAULT_REHASH_SIZE
),
3932 make_float (DEFAULT_REHASH_THRESHOLD
),
3937 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
3938 Lisp_Object color_table
;
3939 unsigned char *chars_start
;
3943 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
3945 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
3947 hash_lookup (table
, chars
, &hash_code
);
3948 hash_put (table
, chars
, color
, hash_code
);
3952 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
3953 Lisp_Object color_table
;
3954 unsigned char *chars_start
;
3957 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
3958 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
3961 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
3964 enum xpm_color_key
{
3972 static char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
3975 xpm_str_to_color_key (s
)
3981 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
3983 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
3989 xpm_load_image (f
, img
, contents
, end
)
3992 unsigned char *contents
, *end
;
3994 unsigned char *s
= contents
, *beg
, *str
;
3995 unsigned char buffer
[BUFSIZ
];
3996 int width
, height
, x
, y
;
3997 int num_colors
, chars_per_pixel
;
3999 void (*put_color_table
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4000 Lisp_Object (*get_color_table
) (Lisp_Object
, unsigned char *, int);
4001 Lisp_Object frame
, color_symbols
, color_table
;
4002 int best_key
, have_mask
= 0;
4003 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4006 LA1 = xpm_scan (&s, end, &beg, &len)
4008 #define expect(TOKEN) \
4009 if (LA1 != (TOKEN)) \
4014 #define expect_ident(IDENT) \
4015 if (LA1 == XPM_TK_IDENT \
4016 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4021 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4025 expect_ident ("static");
4026 expect_ident ("char");
4028 expect (XPM_TK_IDENT
);
4033 expect (XPM_TK_STRING
);
4036 memcpy (buffer
, beg
, len
);
4038 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4039 &num_colors
, &chars_per_pixel
) != 4
4040 || width
<= 0 || height
<= 0
4041 || num_colors
<= 0 || chars_per_pixel
<= 0)
4045 XSETFRAME (frame
, f
);
4046 if (!NILP (Fxw_display_color_p (frame
)))
4047 best_key
= XPM_COLOR_KEY_C
;
4048 else if (!NILP (Fx_display_grayscale_p (frame
)))
4049 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4050 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4052 best_key
= XPM_COLOR_KEY_M
;
4054 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4055 if (chars_per_pixel
== 1)
4056 color_table
= xpm_make_color_table_v (&put_color_table
,
4059 color_table
= xpm_make_color_table_h (&put_color_table
,
4062 while (num_colors
-- > 0)
4064 unsigned char *color
, *max_color
;
4065 int key
, next_key
, max_key
= 0;
4066 Lisp_Object symbol_color
= Qnil
, color_val
;
4069 expect (XPM_TK_STRING
);
4070 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4072 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4073 buffer
[len
- chars_per_pixel
] = '\0';
4075 str
= strtok (buffer
, " \t");
4078 key
= xpm_str_to_color_key (str
);
4083 color
= strtok (NULL
, " \t");
4087 while (str
= strtok (NULL
, " \t"))
4089 next_key
= xpm_str_to_color_key (str
);
4092 color
[strlen (color
)] = ' ';
4095 if (key
== XPM_COLOR_KEY_S
)
4097 if (NILP (symbol_color
))
4098 symbol_color
= build_string (color
);
4100 else if (max_key
< key
&& key
<= best_key
)
4110 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4112 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4114 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4115 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4117 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4119 color_val
= make_number (cdef
.pixel
);
4121 if (NILP (color_val
) && max_key
> 0)
4122 if (xstricmp (max_color
, "None") == 0)
4124 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4125 color_val
= make_number (cdef
.pixel
);
4126 if (!NILP (color_val
))
4127 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4132 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4133 &ximg
, &img
->pixmap
)
4134 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4135 &mask_img
, &img
->mask
))
4137 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4141 for (y
= 0; y
< height
; y
++)
4143 expect (XPM_TK_STRING
);
4145 if (len
< width
* chars_per_pixel
)
4147 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4149 Lisp_Object color_val
=
4150 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4152 XPutPixel (ximg
, x
, y
,
4153 (INTEGERP (color_val
) ? XINT (color_val
)
4154 : FRAME_FOREGROUND_PIXEL (f
)));
4155 XPutPixel (mask_img
, x
, y
,
4156 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW (f
)
4157 : (have_mask
= 1, PIX_MASK_RETAIN (f
))));
4164 img
->height
= height
;
4166 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4167 x_destroy_x_image (ximg
);
4170 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4171 x_destroy_x_image (mask_img
);
4175 x_destroy_x_image (mask_img
);
4176 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4177 img
->mask
= NO_PIXMAP
;
4183 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4185 x_destroy_x_image (ximg
);
4186 x_destroy_x_image (mask_img
);
4187 x_clear_image (f
, img
);
4201 Lisp_Object file_name
;
4203 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4204 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4205 if (STRINGP (file_name
))
4208 unsigned char *contents
;
4210 struct gcpro gcpro1
;
4212 file
= x_find_image_file (file_name
);
4214 if (!STRINGP (file
))
4216 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4221 contents
= slurp_file (SDATA (file
), &size
);
4222 if (contents
== NULL
)
4224 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4229 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4237 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4238 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4239 SDATA (data
) + SBYTES (data
));
4249 /***********************************************************************
4251 ***********************************************************************/
4253 #ifdef COLOR_TABLE_SUPPORT
4255 /* An entry in the color table mapping an RGB color to a pixel color. */
4260 unsigned long pixel
;
4262 /* Next in color table collision list. */
4263 struct ct_color
*next
;
4266 /* The bucket vector size to use. Must be prime. */
4270 /* Value is a hash of the RGB color given by R, G, and B. */
4272 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4274 /* The color hash table. */
4276 struct ct_color
**ct_table
;
4278 /* Number of entries in the color table. */
4280 int ct_colors_allocated
;
4282 /* Initialize the color table. */
4287 int size
= CT_SIZE
* sizeof (*ct_table
);
4288 ct_table
= (struct ct_color
**) xmalloc (size
);
4289 bzero (ct_table
, size
);
4290 ct_colors_allocated
= 0;
4294 /* Free memory associated with the color table. */
4300 struct ct_color
*p
, *next
;
4302 for (i
= 0; i
< CT_SIZE
; ++i
)
4303 for (p
= ct_table
[i
]; p
; p
= next
)
4314 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4315 entry for that color already is in the color table, return the
4316 pixel color of that entry. Otherwise, allocate a new color for R,
4317 G, B, and make an entry in the color table. */
4319 static unsigned long
4320 lookup_rgb_color (f
, r
, g
, b
)
4324 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4325 int i
= hash
% CT_SIZE
;
4327 Display_Info
*dpyinfo
;
4329 /* Handle TrueColor visuals specially, which improves performance by
4330 two orders of magnitude. Freeing colors on TrueColor visuals is
4331 a nop, and pixel colors specify RGB values directly. See also
4332 the Xlib spec, chapter 3.1. */
4333 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4334 if (dpyinfo
->red_bits
> 0)
4336 unsigned long pr
, pg
, pb
;
4338 /* Apply gamma-correction like normal color allocation does. */
4342 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4343 gamma_correct (f
, &color
);
4344 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4347 /* Scale down RGB values to the visual's bits per RGB, and shift
4348 them to the right position in the pixel color. Note that the
4349 original RGB values are 16-bit values, as usual in X. */
4350 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4351 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4352 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4354 /* Assemble the pixel color. */
4355 return pr
| pg
| pb
;
4358 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4359 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4365 #ifdef HAVE_X_WINDOWS
4374 cmap
= FRAME_X_COLORMAP (f
);
4375 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4378 ++ct_colors_allocated
;
4379 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4383 p
->pixel
= color
.pixel
;
4384 p
->next
= ct_table
[i
];
4388 return FRAME_FOREGROUND_PIXEL (f
);
4393 color
= PALETTERGB (r
, g
, b
);
4395 color
= RGB_TO_ULONG (r
, g
, b
);
4396 #endif /* HAVE_NTGUI */
4397 ++ct_colors_allocated
;
4398 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4403 p
->next
= ct_table
[i
];
4405 #endif /* HAVE_X_WINDOWS */
4413 /* Look up pixel color PIXEL which is used on frame F in the color
4414 table. If not already present, allocate it. Value is PIXEL. */
4416 static unsigned long
4417 lookup_pixel_color (f
, pixel
)
4419 unsigned long pixel
;
4421 int i
= pixel
% CT_SIZE
;
4424 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4425 if (p
->pixel
== pixel
)
4434 #ifdef HAVE_X_WINDOWS
4435 cmap
= FRAME_X_COLORMAP (f
);
4436 color
.pixel
= pixel
;
4437 x_query_color (f
, &color
);
4438 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4441 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4442 color
.pixel
= pixel
;
4443 XQueryColor (NULL
, cmap
, &color
);
4444 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4446 #endif /* HAVE_X_WINDOWS */
4450 ++ct_colors_allocated
;
4452 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4457 p
->next
= ct_table
[i
];
4461 return FRAME_FOREGROUND_PIXEL (f
);
4467 /* Value is a vector of all pixel colors contained in the color table,
4468 allocated via xmalloc. Set *N to the number of colors. */
4470 static unsigned long *
4471 colors_in_color_table (n
)
4476 unsigned long *colors
;
4478 if (ct_colors_allocated
== 0)
4485 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4487 *n
= ct_colors_allocated
;
4489 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4490 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4491 colors
[j
++] = p
->pixel
;
4497 #else /* COLOR_TABLE_SUPPORT */
4499 static unsigned long
4500 lookup_rgb_color (f
, r
, g
, b
)
4504 unsigned long pixel
;
4507 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4508 gamma_correct (f
, &pixel
);
4512 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4513 #endif /* HAVE_NTGUI */
4522 #endif /* COLOR_TABLE_SUPPORT */
4525 /***********************************************************************
4527 ***********************************************************************/
4529 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4530 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4531 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4534 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4535 #endif /* HAVE_NTGUI */
4537 /* Non-zero means draw a cross on images having `:conversion
4540 int cross_disabled_images
;
4542 /* Edge detection matrices for different edge-detection
4545 static int emboss_matrix
[9] = {
4547 2, -1, 0, /* y - 1 */
4549 0, 1, -2 /* y + 1 */
4552 static int laplace_matrix
[9] = {
4554 1, 0, 0, /* y - 1 */
4556 0, 0, -1 /* y + 1 */
4559 /* Value is the intensity of the color whose red/green/blue values
4562 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4565 /* On frame F, return an array of XColor structures describing image
4566 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4567 non-zero means also fill the red/green/blue members of the XColor
4568 structures. Value is a pointer to the array of XColors structures,
4569 allocated with xmalloc; it must be freed by the caller. */
4572 x_to_xcolors (f
, img
, rgb_p
)
4579 XImagePtr_or_DC ximg
;
4583 #endif /* HAVE_NTGUI */
4585 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4588 /* Get the X image IMG->pixmap. */
4589 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4590 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4592 /* Load the image into a memory device context. */
4593 hdc
= get_frame_dc (f
);
4594 ximg
= CreateCompatibleDC (hdc
);
4595 release_frame_dc (f
, hdc
);
4596 prev
= SelectObject (ximg
, img
->pixmap
);
4597 #endif /* HAVE_NTGUI */
4599 /* Fill the `pixel' members of the XColor array. I wished there
4600 were an easy and portable way to circumvent XGetPixel. */
4602 for (y
= 0; y
< img
->height
; ++y
)
4606 #ifdef HAVE_X_WINDOWS
4607 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4608 p
->pixel
= XGetPixel (ximg
, x
, y
);
4610 x_query_colors (f
, row
, img
->width
);
4614 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4616 /* W32_TODO: palette support needed here? */
4617 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4621 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4622 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4623 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4626 p
->red
= 256 * GetRValue (p
->pixel
);
4627 p
->green
= 256 * GetGValue (p
->pixel
);
4628 p
->blue
= 256 * GetBValue (p
->pixel
);
4629 #endif /* HAVE_NTGUI */
4632 #endif /* HAVE_X_WINDOWS */
4635 Destroy_Image (ximg
, prev
);
4642 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4643 created with CreateDIBSection, with the pointer to the bit values
4644 stored in ximg->data. */
4646 static void XPutPixel (ximg
, x
, y
, color
)
4651 int width
= ximg
->info
.bmiHeader
.biWidth
;
4652 int height
= ximg
->info
.bmiHeader
.biHeight
;
4653 unsigned char * pixel
;
4655 /* True color images. */
4656 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4658 int rowbytes
= width
* 3;
4659 /* Ensure scanlines are aligned on 4 byte boundaries. */
4661 rowbytes
+= 4 - (rowbytes
% 4);
4663 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4664 /* Windows bitmaps are in BGR order. */
4665 *pixel
= GetBValue (color
);
4666 *(pixel
+ 1) = GetGValue (color
);
4667 *(pixel
+ 2) = GetRValue (color
);
4669 /* Monochrome images. */
4670 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4672 int rowbytes
= width
/ 8;
4673 /* Ensure scanlines are aligned on 4 byte boundaries. */
4675 rowbytes
+= 4 - (rowbytes
% 4);
4676 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4677 /* Filter out palette info. */
4678 if (color
& 0x00ffffff)
4679 *pixel
= *pixel
| (1 << x
% 8);
4681 *pixel
= *pixel
& ~(1 << x
% 8);
4684 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4687 #endif /* HAVE_NTGUI */
4689 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4690 RGB members are set. F is the frame on which this all happens.
4691 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4694 x_from_xcolors (f
, img
, colors
)
4704 init_color_table ();
4706 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4709 for (y
= 0; y
< img
->height
; ++y
)
4710 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4712 unsigned long pixel
;
4713 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4714 XPutPixel (oimg
, x
, y
, pixel
);
4718 x_clear_image_1 (f
, img
, 1, 0, 1);
4720 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4721 x_destroy_x_image (oimg
);
4722 img
->pixmap
= pixmap
;
4723 #ifdef COLOR_TABLE_SUPPORT
4724 img
->colors
= colors_in_color_table (&img
->ncolors
);
4725 free_color_table ();
4726 #endif /* COLOR_TABLE_SUPPORT */
4730 /* On frame F, perform edge-detection on image IMG.
4732 MATRIX is a nine-element array specifying the transformation
4733 matrix. See emboss_matrix for an example.
4735 COLOR_ADJUST is a color adjustment added to each pixel of the
4739 x_detect_edges (f
, img
, matrix
, color_adjust
)
4742 int matrix
[9], color_adjust
;
4744 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4748 for (i
= sum
= 0; i
< 9; ++i
)
4749 sum
+= abs (matrix
[i
]);
4751 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4753 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4755 for (y
= 0; y
< img
->height
; ++y
)
4757 p
= COLOR (new, 0, y
);
4758 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4759 p
= COLOR (new, img
->width
- 1, y
);
4760 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4763 for (x
= 1; x
< img
->width
- 1; ++x
)
4765 p
= COLOR (new, x
, 0);
4766 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4767 p
= COLOR (new, x
, img
->height
- 1);
4768 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4771 for (y
= 1; y
< img
->height
- 1; ++y
)
4773 p
= COLOR (new, 1, y
);
4775 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4777 int r
, g
, b
, y1
, x1
;
4780 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4781 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4784 XColor
*t
= COLOR (colors
, x1
, y1
);
4785 r
+= matrix
[i
] * t
->red
;
4786 g
+= matrix
[i
] * t
->green
;
4787 b
+= matrix
[i
] * t
->blue
;
4790 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4791 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4792 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4793 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4798 x_from_xcolors (f
, img
, new);
4804 /* Perform the pre-defined `emboss' edge-detection on image IMG
4812 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4816 /* Transform image IMG which is used on frame F with a Laplace
4817 edge-detection algorithm. The result is an image that can be used
4818 to draw disabled buttons, for example. */
4825 x_detect_edges (f
, img
, laplace_matrix
, 45000);
4829 /* Perform edge-detection on image IMG on frame F, with specified
4830 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4832 MATRIX must be either
4834 - a list of at least 9 numbers in row-major form
4835 - a vector of at least 9 numbers
4837 COLOR_ADJUST nil means use a default; otherwise it must be a
4841 x_edge_detection (f
, img
, matrix
, color_adjust
)
4844 Lisp_Object matrix
, color_adjust
;
4852 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
4853 ++i
, matrix
= XCDR (matrix
))
4854 trans
[i
] = XFLOATINT (XCAR (matrix
));
4856 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
4858 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
4859 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
4862 if (NILP (color_adjust
))
4863 color_adjust
= make_number (0xffff / 2);
4865 if (i
== 9 && NUMBERP (color_adjust
))
4866 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
4870 /* Transform image IMG on frame F so that it looks disabled. */
4873 x_disable_image (f
, img
)
4877 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4879 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
4881 int n_planes
= dpyinfo
->n_planes
;
4882 #endif /* HAVE_NTGUI */
4886 /* Color (or grayscale). Convert to gray, and equalize. Just
4887 drawing such images with a stipple can look very odd, so
4888 we're using this method instead. */
4889 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4891 const int h
= 15000;
4892 const int l
= 30000;
4894 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
4898 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
4899 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
4900 p
->red
= p
->green
= p
->blue
= i2
;
4903 x_from_xcolors (f
, img
, colors
);
4906 /* Draw a cross over the disabled image, if we must or if we
4908 if (n_planes
< 2 || cross_disabled_images
)
4911 Display
*dpy
= FRAME_X_DISPLAY (f
);
4915 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4916 #define MaskForeground(f) PIX_MASK_DRAW (f)
4918 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4919 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4922 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
4923 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
4924 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
4925 img
->width
- 1, img
->height
- 1);
4926 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
4932 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
4933 XSetForeground (dpy
, gc
, MaskForeground (f
));
4934 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
4935 img
->width
- 1, img
->height
- 1);
4936 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
4944 hdc
= get_frame_dc (f
);
4945 bmpdc
= CreateCompatibleDC (hdc
);
4946 release_frame_dc (f
, hdc
);
4948 prev
= SelectObject (bmpdc
, img
->pixmap
);
4950 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
4951 MoveToEx (bmpdc
, 0, 0, NULL
);
4952 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4953 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4954 LineTo (bmpdc
, img
->width
- 1, 0);
4958 SelectObject (bmpdc
, img
->mask
);
4959 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
4960 MoveToEx (bmpdc
, 0, 0, NULL
);
4961 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4962 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4963 LineTo (bmpdc
, img
->width
- 1, 0);
4965 SelectObject (bmpdc
, prev
);
4967 #endif /* HAVE_NTGUI */
4972 /* Build a mask for image IMG which is used on frame F. FILE is the
4973 name of an image file, for error messages. HOW determines how to
4974 determine the background color of IMG. If it is a list '(R G B)',
4975 with R, G, and B being integers >= 0, take that as the color of the
4976 background. Otherwise, determine the background color of IMG
4977 heuristically. Value is non-zero if successful. */
4980 x_build_heuristic_mask (f
, img
, how
)
4985 XImagePtr_or_DC ximg
;
4993 #endif /* HAVE_NTGUI */
4994 int x
, y
, rc
, use_img_background
;
4995 unsigned long bg
= 0;
4999 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5000 img
->mask
= NO_PIXMAP
;
5001 img
->background_transparent_valid
= 0;
5005 /* Create an image and pixmap serving as mask. */
5006 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5007 &mask_img
, &img
->mask
);
5011 /* Get the X image of IMG->pixmap. */
5012 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5013 img
->width
, img
->height
,
5016 /* Create the bit array serving as mask. */
5017 row_width
= (img
->width
+ 7) / 8;
5018 mask_img
= xmalloc (row_width
* img
->height
);
5019 bzero (mask_img
, row_width
* img
->height
);
5021 /* Create a memory device context for IMG->pixmap. */
5022 frame_dc
= get_frame_dc (f
);
5023 ximg
= CreateCompatibleDC (frame_dc
);
5024 release_frame_dc (f
, frame_dc
);
5025 prev
= SelectObject (ximg
, img
->pixmap
);
5026 #endif /* HAVE_NTGUI */
5028 /* Determine the background color of ximg. If HOW is `(R G B)'
5029 take that as color. Otherwise, use the image's background color. */
5030 use_img_background
= 1;
5036 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5038 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5042 if (i
== 3 && NILP (how
))
5044 char color_name
[30];
5045 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5048 0x00ffffff & /* Filter out palette info. */
5049 #endif /* HAVE_NTGUI */
5050 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5051 use_img_background
= 0;
5055 if (use_img_background
)
5056 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
5058 /* Set all bits in mask_img to 1 whose color in ximg is different
5059 from the background color bg. */
5061 for (y
= 0; y
< img
->height
; ++y
)
5062 for (x
= 0; x
< img
->width
; ++x
)
5063 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5064 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
)));
5066 /* Fill in the background_transparent field while we have the mask handy. */
5067 image_background_transparent (img
, f
, mask_img
);
5069 /* Put mask_img into img->mask. */
5070 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5071 x_destroy_x_image (mask_img
);
5074 for (y
= 0; y
< img
->height
; ++y
)
5075 for (x
= 0; x
< img
->width
; ++x
)
5077 COLORREF p
= GetPixel (ximg
, x
, y
);
5079 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5082 /* Create the mask image. */
5083 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5085 /* Fill in the background_transparent field while we have the mask handy. */
5086 SelectObject (ximg
, img
->mask
);
5087 image_background_transparent (img
, f
, ximg
);
5089 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5091 #endif /* HAVE_NTGUI */
5093 Destroy_Image (ximg
, prev
);
5099 /***********************************************************************
5100 PBM (mono, gray, color)
5101 ***********************************************************************/
5103 static int pbm_image_p
P_ ((Lisp_Object object
));
5104 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5105 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5107 /* The symbol `pbm' identifying images of this type. */
5111 /* Indices of image specification fields in gs_format, below. */
5113 enum pbm_keyword_index
5129 /* Vector of image_keyword structures describing the format
5130 of valid user-defined image specifications. */
5132 static struct image_keyword pbm_format
[PBM_LAST
] =
5134 {":type", IMAGE_SYMBOL_VALUE
, 1},
5135 {":file", IMAGE_STRING_VALUE
, 0},
5136 {":data", IMAGE_STRING_VALUE
, 0},
5137 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5138 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5139 {":relief", IMAGE_INTEGER_VALUE
, 0},
5140 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5141 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5142 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5143 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5144 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5147 /* Structure describing the image type `pbm'. */
5149 static struct image_type pbm_type
=
5159 /* Return non-zero if OBJECT is a valid PBM image specification. */
5162 pbm_image_p (object
)
5165 struct image_keyword fmt
[PBM_LAST
];
5167 bcopy (pbm_format
, fmt
, sizeof fmt
);
5169 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5172 /* Must specify either :data or :file. */
5173 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5177 /* Scan a decimal number from *S and return it. Advance *S while
5178 reading the number. END is the end of the string. Value is -1 at
5182 pbm_scan_number (s
, end
)
5183 unsigned char **s
, *end
;
5185 int c
= 0, val
= -1;
5189 /* Skip white-space. */
5190 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5195 /* Skip comment to end of line. */
5196 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5199 else if (isdigit (c
))
5201 /* Read decimal number. */
5203 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5204 val
= 10 * val
+ c
- '0';
5216 #if 0 /* Unused. ++kfs */
5218 /* Read FILE into memory. Value is a pointer to a buffer allocated
5219 with xmalloc holding FILE's contents. Value is null if an error
5220 occurred. *SIZE is set to the size of the file. */
5223 pbm_read_file (file
, size
)
5231 if (stat (SDATA (file
), &st
) == 0
5232 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5233 && (buf
= (char *) xmalloc (st
.st_size
),
5234 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5253 #endif /* HAVE_NTGUI */
5255 /* Load PBM image IMG for use on frame F. */
5263 int width
, height
, max_color_idx
= 0;
5265 Lisp_Object file
, specified_file
;
5266 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5267 struct gcpro gcpro1
;
5268 unsigned char *contents
= NULL
;
5269 unsigned char *end
, *p
;
5272 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5276 if (STRINGP (specified_file
))
5278 file
= x_find_image_file (specified_file
);
5279 if (!STRINGP (file
))
5281 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5286 contents
= slurp_file (SDATA (file
), &size
);
5287 if (contents
== NULL
)
5289 image_error ("Error reading `%s'", file
, Qnil
);
5295 end
= contents
+ size
;
5300 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5302 end
= p
+ SBYTES (data
);
5305 /* Check magic number. */
5306 if (end
- p
< 2 || *p
++ != 'P')
5308 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5318 raw_p
= 0, type
= PBM_MONO
;
5322 raw_p
= 0, type
= PBM_GRAY
;
5326 raw_p
= 0, type
= PBM_COLOR
;
5330 raw_p
= 1, type
= PBM_MONO
;
5334 raw_p
= 1, type
= PBM_GRAY
;
5338 raw_p
= 1, type
= PBM_COLOR
;
5342 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5346 /* Read width, height, maximum color-component. Characters
5347 starting with `#' up to the end of a line are ignored. */
5348 width
= pbm_scan_number (&p
, end
);
5349 height
= pbm_scan_number (&p
, end
);
5351 if (type
!= PBM_MONO
)
5353 max_color_idx
= pbm_scan_number (&p
, end
);
5354 if (raw_p
&& max_color_idx
> 255)
5355 max_color_idx
= 255;
5360 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5363 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5364 &ximg
, &img
->pixmap
))
5367 /* Initialize the color hash table. */
5368 init_color_table ();
5370 if (type
== PBM_MONO
)
5373 struct image_keyword fmt
[PBM_LAST
];
5374 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5375 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5377 /* Parse the image specification. */
5378 bcopy (pbm_format
, fmt
, sizeof fmt
);
5379 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5381 /* Get foreground and background colors, maybe allocate colors. */
5382 if (fmt
[PBM_FOREGROUND
].count
5383 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5384 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5385 if (fmt
[PBM_BACKGROUND
].count
5386 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5388 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5389 img
->background
= bg
;
5390 img
->background_valid
= 1;
5393 for (y
= 0; y
< height
; ++y
)
5394 for (x
= 0; x
< width
; ++x
)
5404 g
= pbm_scan_number (&p
, end
);
5406 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5411 for (y
= 0; y
< height
; ++y
)
5412 for (x
= 0; x
< width
; ++x
)
5416 if (type
== PBM_GRAY
)
5417 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5426 r
= pbm_scan_number (&p
, end
);
5427 g
= pbm_scan_number (&p
, end
);
5428 b
= pbm_scan_number (&p
, end
);
5431 if (r
< 0 || g
< 0 || b
< 0)
5433 x_destroy_x_image (ximg
);
5434 image_error ("Invalid pixel value in image `%s'",
5439 /* RGB values are now in the range 0..max_color_idx.
5440 Scale this to the range 0..0xffff supported by X. */
5441 r
= (double) r
* 65535 / max_color_idx
;
5442 g
= (double) g
* 65535 / max_color_idx
;
5443 b
= (double) b
* 65535 / max_color_idx
;
5444 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5448 #ifdef COLOR_TABLE_SUPPORT
5449 /* Store in IMG->colors the colors allocated for the image, and
5450 free the color table. */
5451 img
->colors
= colors_in_color_table (&img
->ncolors
);
5452 free_color_table ();
5453 #endif /* COLOR_TABLE_SUPPORT */
5456 img
->height
= height
;
5458 /* Maybe fill in the background field while we have ximg handy. */
5460 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5461 IMAGE_BACKGROUND (img
, f
, ximg
);
5463 /* Put the image into a pixmap. */
5464 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5465 x_destroy_x_image (ximg
);
5467 /* X and W32 versions did it here, MAC version above. ++kfs
5469 img->height = height; */
5477 /***********************************************************************
5479 ***********************************************************************/
5481 #if defined (HAVE_PNG) || defined (MAC_OS)
5483 /* Function prototypes. */
5485 static int png_image_p
P_ ((Lisp_Object object
));
5486 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5488 /* The symbol `png' identifying images of this type. */
5492 /* Indices of image specification fields in png_format, below. */
5494 enum png_keyword_index
5509 /* Vector of image_keyword structures describing the format
5510 of valid user-defined image specifications. */
5512 static struct image_keyword png_format
[PNG_LAST
] =
5514 {":type", IMAGE_SYMBOL_VALUE
, 1},
5515 {":data", IMAGE_STRING_VALUE
, 0},
5516 {":file", IMAGE_STRING_VALUE
, 0},
5517 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5518 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5519 {":relief", IMAGE_INTEGER_VALUE
, 0},
5520 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5521 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5522 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5523 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5526 /* Structure describing the image type `png'. */
5528 static struct image_type png_type
=
5537 /* Return non-zero if OBJECT is a valid PNG image specification. */
5540 png_image_p (object
)
5543 struct image_keyword fmt
[PNG_LAST
];
5544 bcopy (png_format
, fmt
, sizeof fmt
);
5546 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5549 /* Must specify either the :data or :file keyword. */
5550 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5553 #endif /* HAVE_PNG || MAC_OS */
5558 #if defined HAVE_LIBPNG_PNG_H
5559 # include <libpng/png.h>
5565 /* PNG library details. */
5567 DEF_IMGLIB_FN (png_get_io_ptr
);
5568 DEF_IMGLIB_FN (png_check_sig
);
5569 DEF_IMGLIB_FN (png_create_read_struct
);
5570 DEF_IMGLIB_FN (png_create_info_struct
);
5571 DEF_IMGLIB_FN (png_destroy_read_struct
);
5572 DEF_IMGLIB_FN (png_set_read_fn
);
5573 DEF_IMGLIB_FN (png_init_io
);
5574 DEF_IMGLIB_FN (png_set_sig_bytes
);
5575 DEF_IMGLIB_FN (png_read_info
);
5576 DEF_IMGLIB_FN (png_get_IHDR
);
5577 DEF_IMGLIB_FN (png_get_valid
);
5578 DEF_IMGLIB_FN (png_set_strip_16
);
5579 DEF_IMGLIB_FN (png_set_expand
);
5580 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5581 DEF_IMGLIB_FN (png_set_background
);
5582 DEF_IMGLIB_FN (png_get_bKGD
);
5583 DEF_IMGLIB_FN (png_read_update_info
);
5584 DEF_IMGLIB_FN (png_get_channels
);
5585 DEF_IMGLIB_FN (png_get_rowbytes
);
5586 DEF_IMGLIB_FN (png_read_image
);
5587 DEF_IMGLIB_FN (png_read_end
);
5588 DEF_IMGLIB_FN (png_error
);
5591 init_png_functions (void)
5595 /* Ensure zlib is loaded. Try debug version first. */
5596 if (!LoadLibrary ("zlibd.dll")
5597 && !LoadLibrary ("zlib.dll"))
5600 /* Try loading libpng under probable names. */
5601 if (!(library
= LoadLibrary ("libpng13d.dll"))
5602 && !(library
= LoadLibrary ("libpng13.dll"))
5603 && !(library
= LoadLibrary ("libpng12d.dll"))
5604 && !(library
= LoadLibrary ("libpng12.dll"))
5605 && !(library
= LoadLibrary ("libpng.dll")))
5608 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5609 LOAD_IMGLIB_FN (library
, png_check_sig
);
5610 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5611 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5612 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5613 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5614 LOAD_IMGLIB_FN (library
, png_init_io
);
5615 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5616 LOAD_IMGLIB_FN (library
, png_read_info
);
5617 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5618 LOAD_IMGLIB_FN (library
, png_get_valid
);
5619 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5620 LOAD_IMGLIB_FN (library
, png_set_expand
);
5621 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5622 LOAD_IMGLIB_FN (library
, png_set_background
);
5623 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5624 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5625 LOAD_IMGLIB_FN (library
, png_get_channels
);
5626 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5627 LOAD_IMGLIB_FN (library
, png_read_image
);
5628 LOAD_IMGLIB_FN (library
, png_read_end
);
5629 LOAD_IMGLIB_FN (library
, png_error
);
5634 #define fn_png_get_io_ptr png_get_io_ptr
5635 #define fn_png_check_sig png_check_sig
5636 #define fn_png_create_read_struct png_create_read_struct
5637 #define fn_png_create_info_struct png_create_info_struct
5638 #define fn_png_destroy_read_struct png_destroy_read_struct
5639 #define fn_png_set_read_fn png_set_read_fn
5640 #define fn_png_init_io png_init_io
5641 #define fn_png_set_sig_bytes png_set_sig_bytes
5642 #define fn_png_read_info png_read_info
5643 #define fn_png_get_IHDR png_get_IHDR
5644 #define fn_png_get_valid png_get_valid
5645 #define fn_png_set_strip_16 png_set_strip_16
5646 #define fn_png_set_expand png_set_expand
5647 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5648 #define fn_png_set_background png_set_background
5649 #define fn_png_get_bKGD png_get_bKGD
5650 #define fn_png_read_update_info png_read_update_info
5651 #define fn_png_get_channels png_get_channels
5652 #define fn_png_get_rowbytes png_get_rowbytes
5653 #define fn_png_read_image png_read_image
5654 #define fn_png_read_end png_read_end
5655 #define fn_png_error png_error
5657 #endif /* HAVE_NTGUI */
5659 /* Error and warning handlers installed when the PNG library
5663 my_png_error (png_ptr
, msg
)
5664 png_struct
*png_ptr
;
5667 xassert (png_ptr
!= NULL
);
5668 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5669 longjmp (png_ptr
->jmpbuf
, 1);
5674 my_png_warning (png_ptr
, msg
)
5675 png_struct
*png_ptr
;
5678 xassert (png_ptr
!= NULL
);
5679 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5682 /* Memory source for PNG decoding. */
5684 struct png_memory_storage
5686 unsigned char *bytes
; /* The data */
5687 size_t len
; /* How big is it? */
5688 int index
; /* Where are we? */
5692 /* Function set as reader function when reading PNG image from memory.
5693 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5694 bytes from the input to DATA. */
5697 /* Work around a problem with MinGW builds of graphics libraries
5698 not honoring calling conventions. */
5699 #pragma optimize("g", off)
5703 png_read_from_memory (png_ptr
, data
, length
)
5704 png_structp png_ptr
;
5708 struct png_memory_storage
*tbr
5709 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5711 if (length
> tbr
->len
- tbr
->index
)
5712 fn_png_error (png_ptr
, "Read error");
5714 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5715 tbr
->index
= tbr
->index
+ length
;
5719 /* Restore normal optimization, as specified on the command line. */
5720 #pragma optimize("", on)
5723 /* Load PNG image IMG for use on frame F. Value is non-zero if
5731 Lisp_Object file
, specified_file
;
5732 Lisp_Object specified_data
;
5734 XImagePtr ximg
, mask_img
= NULL
;
5735 struct gcpro gcpro1
;
5736 png_struct
*png_ptr
= NULL
;
5737 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5738 FILE *volatile fp
= NULL
;
5740 png_byte
* volatile pixels
= NULL
;
5741 png_byte
** volatile rows
= NULL
;
5742 png_uint_32 width
, height
;
5743 int bit_depth
, color_type
, interlace_type
;
5745 png_uint_32 row_bytes
;
5747 double screen_gamma
;
5748 struct png_memory_storage tbr
; /* Data to be read */
5750 /* Find out what file to load. */
5751 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5752 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5756 if (NILP (specified_data
))
5758 file
= x_find_image_file (specified_file
);
5759 if (!STRINGP (file
))
5761 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5766 /* Open the image file. */
5767 fp
= fopen (SDATA (file
), "rb");
5770 image_error ("Cannot open image file `%s'", file
, Qnil
);
5776 /* Check PNG signature. */
5777 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5778 || !fn_png_check_sig (sig
, sizeof sig
))
5780 image_error ("Not a PNG file: `%s'", file
, Qnil
);
5788 /* Read from memory. */
5789 tbr
.bytes
= SDATA (specified_data
);
5790 tbr
.len
= SBYTES (specified_data
);
5793 /* Check PNG signature. */
5794 if (tbr
.len
< sizeof sig
5795 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
5797 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
5802 /* Need to skip past the signature. */
5803 tbr
.bytes
+= sizeof (sig
);
5806 /* Initialize read and info structs for PNG lib. */
5807 png_ptr
= fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
5808 my_png_error
, my_png_warning
);
5811 if (fp
) fclose (fp
);
5816 info_ptr
= fn_png_create_info_struct (png_ptr
);
5819 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
5820 if (fp
) fclose (fp
);
5825 end_info
= fn_png_create_info_struct (png_ptr
);
5828 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
5829 if (fp
) fclose (fp
);
5834 /* Set error jump-back. We come back here when the PNG library
5835 detects an error. */
5836 if (setjmp (png_ptr
->jmpbuf
))
5840 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5843 if (fp
) fclose (fp
);
5848 /* Read image info. */
5849 if (!NILP (specified_data
))
5850 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
5852 fn_png_init_io (png_ptr
, fp
);
5854 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
5855 fn_png_read_info (png_ptr
, info_ptr
);
5856 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
5857 &interlace_type
, NULL
, NULL
);
5859 /* If image contains simply transparency data, we prefer to
5860 construct a clipping mask. */
5861 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
5866 /* This function is easier to write if we only have to handle
5867 one data format: RGB or RGBA with 8 bits per channel. Let's
5868 transform other formats into that format. */
5870 /* Strip more than 8 bits per channel. */
5871 if (bit_depth
== 16)
5872 fn_png_set_strip_16 (png_ptr
);
5874 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5876 fn_png_set_expand (png_ptr
);
5878 /* Convert grayscale images to RGB. */
5879 if (color_type
== PNG_COLOR_TYPE_GRAY
5880 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5881 fn_png_set_gray_to_rgb (png_ptr
);
5883 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
5885 #if 0 /* Avoid double gamma correction for PNG images. */
5886 { /* Tell the PNG lib to handle gamma correction for us. */
5889 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5890 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
5891 /* The libpng documentation says this is right in this case. */
5892 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5895 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
5896 /* Image contains gamma information. */
5897 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
5899 /* Use the standard default for the image gamma. */
5900 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5904 /* Handle alpha channel by combining the image with a background
5905 color. Do this only if a real alpha channel is supplied. For
5906 simple transparency, we prefer a clipping mask. */
5909 png_color_16
*image_bg
;
5910 Lisp_Object specified_bg
5911 = image_spec_value (img
->spec
, QCbackground
, NULL
);
5913 if (STRINGP (specified_bg
))
5914 /* The user specified `:background', use that. */
5916 /* W32 version incorrectly used COLORREF here!! ++kfs */
5918 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
5920 png_color_16 user_bg
;
5922 bzero (&user_bg
, sizeof user_bg
);
5923 user_bg
.red
= color
.red
>> 8;
5924 user_bg
.green
= color
.green
>> 8;
5925 user_bg
.blue
= color
.blue
>> 8;
5927 fn_png_set_background (png_ptr
, &user_bg
,
5928 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5931 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
5932 /* Image contains a background color with which to
5933 combine the image. */
5934 fn_png_set_background (png_ptr
, image_bg
,
5935 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
5938 /* Image does not contain a background color with which
5939 to combine the image data via an alpha channel. Use
5940 the frame's background instead. */
5941 #ifdef HAVE_X_WINDOWS
5943 png_color_16 frame_background
;
5945 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
5946 x_query_color (f
, &color
);
5948 bzero (&frame_background
, sizeof frame_background
);
5949 frame_background
.red
= color
.red
>> 8;
5950 frame_background
.green
= color
.green
>> 8;
5951 frame_background
.blue
= color
.blue
>> 8;
5952 #endif /* HAVE_X_WINDOWS */
5956 png_color_16 frame_background
;
5957 color
= FRAME_BACKGROUND_PIXEL (f
);
5958 #if 0 /* W32 TODO : Colormap support. */
5959 x_query_color (f
, &color
);
5961 bzero (&frame_background
, sizeof frame_background
);
5962 frame_background
.red
= GetRValue (color
);
5963 frame_background
.green
= GetGValue (color
);
5964 frame_background
.blue
= GetBValue (color
);
5965 #endif /* HAVE_NTGUI */
5968 unsigned long color
;
5969 png_color_16 frame_background
;
5970 color
= FRAME_BACKGROUND_PIXEL (f
);
5971 #if 0 /* MAC/W32 TODO : Colormap support. */
5972 x_query_color (f
, &color
);
5974 bzero (&frame_background
, sizeof frame_background
);
5975 frame_background
.red
= RED_FROM_ULONG (color
);
5976 frame_background
.green
= GREEN_FROM_ULONG (color
);
5977 frame_background
.blue
= BLUE_FROM_ULONG (color
);
5980 fn_png_set_background (png_ptr
, &frame_background
,
5981 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5985 /* Update info structure. */
5986 fn_png_read_update_info (png_ptr
, info_ptr
);
5988 /* Get number of channels. Valid values are 1 for grayscale images
5989 and images with a palette, 2 for grayscale images with transparency
5990 information (alpha channel), 3 for RGB images, and 4 for RGB
5991 images with alpha channel, i.e. RGBA. If conversions above were
5992 sufficient we should only have 3 or 4 channels here. */
5993 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
5994 xassert (channels
== 3 || channels
== 4);
5996 /* Number of bytes needed for one row of the image. */
5997 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
5999 /* Allocate memory for the image. */
6000 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6001 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6002 for (i
= 0; i
< height
; ++i
)
6003 rows
[i
] = pixels
+ i
* row_bytes
;
6005 /* Read the entire image. */
6006 fn_png_read_image (png_ptr
, rows
);
6007 fn_png_read_end (png_ptr
, info_ptr
);
6014 /* Create the X image and pixmap. */
6015 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6019 /* Create an image and pixmap serving as mask if the PNG image
6020 contains an alpha channel. */
6023 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6024 &mask_img
, &img
->mask
))
6026 x_destroy_x_image (ximg
);
6027 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6028 img
->pixmap
= NO_PIXMAP
;
6032 /* Fill the X image and mask from PNG data. */
6033 init_color_table ();
6035 for (y
= 0; y
< height
; ++y
)
6037 png_byte
*p
= rows
[y
];
6039 for (x
= 0; x
< width
; ++x
)
6046 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6047 /* An alpha channel, aka mask channel, associates variable
6048 transparency with an image. Where other image formats
6049 support binary transparency---fully transparent or fully
6050 opaque---PNG allows up to 254 levels of partial transparency.
6051 The PNG library implements partial transparency by combining
6052 the image with a specified background color.
6054 I'm not sure how to handle this here nicely: because the
6055 background on which the image is displayed may change, for
6056 real alpha channel support, it would be necessary to create
6057 a new image for each possible background.
6059 What I'm doing now is that a mask is created if we have
6060 boolean transparency information. Otherwise I'm using
6061 the frame's background color to combine the image with. */
6066 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
6072 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6073 /* Set IMG's background color from the PNG image, unless the user
6077 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6079 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6080 img
->background_valid
= 1;
6084 #ifdef COLOR_TABLE_SUPPORT
6085 /* Remember colors allocated for this image. */
6086 img
->colors
= colors_in_color_table (&img
->ncolors
);
6087 free_color_table ();
6088 #endif /* COLOR_TABLE_SUPPORT */
6091 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6096 img
->height
= height
;
6098 /* Maybe fill in the background field while we have ximg handy. */
6099 IMAGE_BACKGROUND (img
, f
, ximg
);
6101 /* Put the image into the pixmap, then free the X image and its buffer. */
6102 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6103 x_destroy_x_image (ximg
);
6105 /* Same for the mask. */
6108 /* Fill in the background_transparent field while we have the mask
6110 image_background_transparent (img
, f
, mask_img
);
6112 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6113 x_destroy_x_image (mask_img
);
6120 #else /* HAVE_PNG */
6129 if (MyCGImageCreateWithPNGDataProvider
)
6130 return image_load_quartz2d (f
, img
, 1);
6133 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6137 #endif /* !HAVE_PNG */
6141 /***********************************************************************
6143 ***********************************************************************/
6145 #if defined (HAVE_JPEG) || defined (MAC_OS)
6147 static int jpeg_image_p
P_ ((Lisp_Object object
));
6148 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6150 /* The symbol `jpeg' identifying images of this type. */
6154 /* Indices of image specification fields in gs_format, below. */
6156 enum jpeg_keyword_index
6165 JPEG_HEURISTIC_MASK
,
6171 /* Vector of image_keyword structures describing the format
6172 of valid user-defined image specifications. */
6174 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6176 {":type", IMAGE_SYMBOL_VALUE
, 1},
6177 {":data", IMAGE_STRING_VALUE
, 0},
6178 {":file", IMAGE_STRING_VALUE
, 0},
6179 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6180 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6181 {":relief", IMAGE_INTEGER_VALUE
, 0},
6182 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6183 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6184 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6185 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6188 /* Structure describing the image type `jpeg'. */
6190 static struct image_type jpeg_type
=
6199 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6202 jpeg_image_p (object
)
6205 struct image_keyword fmt
[JPEG_LAST
];
6207 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6209 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6212 /* Must specify either the :data or :file keyword. */
6213 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6216 #endif /* HAVE_JPEG || MAC_OS */
6220 /* Work around a warning about HAVE_STDLIB_H being redefined in
6222 #ifdef HAVE_STDLIB_H
6223 #define HAVE_STDLIB_H_1
6224 #undef HAVE_STDLIB_H
6225 #endif /* HAVE_STLIB_H */
6227 #include <jpeglib.h>
6231 #ifdef HAVE_STLIB_H_1
6232 #define HAVE_STDLIB_H 1
6237 /* JPEG library details. */
6238 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6239 DEF_IMGLIB_FN (jpeg_start_decompress
);
6240 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6241 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6242 DEF_IMGLIB_FN (jpeg_read_header
);
6243 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6244 DEF_IMGLIB_FN (jpeg_stdio_src
);
6245 DEF_IMGLIB_FN (jpeg_std_error
);
6246 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6249 init_jpeg_functions (void)
6253 if (!(library
= LoadLibrary ("libjpeg.dll"))
6254 && !(library
= LoadLibrary ("jpeg-62.dll"))
6255 && !(library
= LoadLibrary ("jpeg.dll")))
6258 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6259 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6260 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6261 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6262 LOAD_IMGLIB_FN (library
, jpeg_stdio_src
);
6263 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6264 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6265 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6266 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6270 /* Wrapper since we can't directly assign the function pointer
6271 to another function pointer that was declared more completely easily. */
6273 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
6274 j_decompress_ptr cinfo
;
6277 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6282 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6283 #define fn_jpeg_start_decompress jpeg_start_decompress
6284 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6285 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6286 #define fn_jpeg_read_header jpeg_read_header
6287 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6288 #define fn_jpeg_stdio_src jpeg_stdio_src
6289 #define fn_jpeg_std_error jpeg_std_error
6290 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6292 #endif /* HAVE_NTGUI */
6294 struct my_jpeg_error_mgr
6296 struct jpeg_error_mgr pub
;
6297 jmp_buf setjmp_buffer
;
6302 my_error_exit (cinfo
)
6305 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6306 longjmp (mgr
->setjmp_buffer
, 1);
6310 /* Init source method for JPEG data source manager. Called by
6311 jpeg_read_header() before any data is actually read. See
6312 libjpeg.doc from the JPEG lib distribution. */
6315 our_init_source (cinfo
)
6316 j_decompress_ptr cinfo
;
6321 /* Fill input buffer method for JPEG data source manager. Called
6322 whenever more data is needed. We read the whole image in one step,
6323 so this only adds a fake end of input marker at the end. */
6326 our_fill_input_buffer (cinfo
)
6327 j_decompress_ptr cinfo
;
6329 /* Insert a fake EOI marker. */
6330 struct jpeg_source_mgr
*src
= cinfo
->src
;
6331 static JOCTET buffer
[2];
6333 buffer
[0] = (JOCTET
) 0xFF;
6334 buffer
[1] = (JOCTET
) JPEG_EOI
;
6336 src
->next_input_byte
= buffer
;
6337 src
->bytes_in_buffer
= 2;
6342 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6343 is the JPEG data source manager. */
6346 our_skip_input_data (cinfo
, num_bytes
)
6347 j_decompress_ptr cinfo
;
6350 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6354 if (num_bytes
> src
->bytes_in_buffer
)
6355 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6357 src
->bytes_in_buffer
-= num_bytes
;
6358 src
->next_input_byte
+= num_bytes
;
6363 /* Method to terminate data source. Called by
6364 jpeg_finish_decompress() after all data has been processed. */
6367 our_term_source (cinfo
)
6368 j_decompress_ptr cinfo
;
6373 /* Set up the JPEG lib for reading an image from DATA which contains
6374 LEN bytes. CINFO is the decompression info structure created for
6375 reading the image. */
6378 jpeg_memory_src (cinfo
, data
, len
)
6379 j_decompress_ptr cinfo
;
6383 struct jpeg_source_mgr
*src
;
6385 if (cinfo
->src
== NULL
)
6387 /* First time for this JPEG object? */
6388 cinfo
->src
= (struct jpeg_source_mgr
*)
6389 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6390 sizeof (struct jpeg_source_mgr
));
6391 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6392 src
->next_input_byte
= data
;
6395 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6396 src
->init_source
= our_init_source
;
6397 src
->fill_input_buffer
= our_fill_input_buffer
;
6398 src
->skip_input_data
= our_skip_input_data
;
6399 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6400 src
->term_source
= our_term_source
;
6401 src
->bytes_in_buffer
= len
;
6402 src
->next_input_byte
= data
;
6406 /* Load image IMG for use on frame F. Patterned after example.c
6407 from the JPEG lib. */
6414 struct jpeg_decompress_struct cinfo
;
6415 struct my_jpeg_error_mgr mgr
;
6416 Lisp_Object file
, specified_file
;
6417 Lisp_Object specified_data
;
6418 FILE * volatile fp
= NULL
;
6420 int row_stride
, x
, y
;
6421 XImagePtr ximg
= NULL
;
6423 unsigned long *colors
;
6425 struct gcpro gcpro1
;
6427 /* Open the JPEG file. */
6428 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6429 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6433 if (NILP (specified_data
))
6435 file
= x_find_image_file (specified_file
);
6436 if (!STRINGP (file
))
6438 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6443 fp
= fopen (SDATA (file
), "rb");
6446 image_error ("Cannot open `%s'", file
, Qnil
);
6452 /* Customize libjpeg's error handling to call my_error_exit when an
6453 error is detected. This function will perform a longjmp. */
6454 cinfo
.err
= fn_jpeg_std_error (&mgr
.pub
);
6455 mgr
.pub
.error_exit
= my_error_exit
;
6457 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6461 /* Called from my_error_exit. Display a JPEG error. */
6462 char buffer
[JMSG_LENGTH_MAX
];
6463 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6464 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6465 build_string (buffer
));
6468 /* Close the input file and destroy the JPEG object. */
6470 fclose ((FILE *) fp
);
6471 fn_jpeg_destroy_decompress (&cinfo
);
6473 /* If we already have an XImage, free that. */
6474 x_destroy_x_image (ximg
);
6476 /* Free pixmap and colors. */
6477 x_clear_image (f
, img
);
6483 /* Create the JPEG decompression object. Let it read from fp.
6484 Read the JPEG image header. */
6485 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6487 if (NILP (specified_data
))
6488 fn_jpeg_stdio_src (&cinfo
, (FILE *) fp
);
6490 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6491 SBYTES (specified_data
));
6493 fn_jpeg_read_header (&cinfo
, TRUE
);
6495 /* Customize decompression so that color quantization will be used.
6496 Start decompression. */
6497 cinfo
.quantize_colors
= TRUE
;
6498 fn_jpeg_start_decompress (&cinfo
);
6499 width
= img
->width
= cinfo
.output_width
;
6500 height
= img
->height
= cinfo
.output_height
;
6502 /* Create X image and pixmap. */
6503 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6504 longjmp (mgr
.setjmp_buffer
, 2);
6506 /* Allocate colors. When color quantization is used,
6507 cinfo.actual_number_of_colors has been set with the number of
6508 colors generated, and cinfo.colormap is a two-dimensional array
6509 of color indices in the range 0..cinfo.actual_number_of_colors.
6510 No more than 255 colors will be generated. */
6514 if (cinfo
.out_color_components
> 2)
6515 ir
= 0, ig
= 1, ib
= 2;
6516 else if (cinfo
.out_color_components
> 1)
6517 ir
= 0, ig
= 1, ib
= 0;
6519 ir
= 0, ig
= 0, ib
= 0;
6521 /* Use the color table mechanism because it handles colors that
6522 cannot be allocated nicely. Such colors will be replaced with
6523 a default color, and we don't have to care about which colors
6524 can be freed safely, and which can't. */
6525 init_color_table ();
6526 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6529 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6531 /* Multiply RGB values with 255 because X expects RGB values
6532 in the range 0..0xffff. */
6533 int r
= cinfo
.colormap
[ir
][i
] << 8;
6534 int g
= cinfo
.colormap
[ig
][i
] << 8;
6535 int b
= cinfo
.colormap
[ib
][i
] << 8;
6536 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6539 #ifdef COLOR_TABLE_SUPPORT
6540 /* Remember those colors actually allocated. */
6541 img
->colors
= colors_in_color_table (&img
->ncolors
);
6542 free_color_table ();
6543 #endif /* COLOR_TABLE_SUPPORT */
6547 row_stride
= width
* cinfo
.output_components
;
6548 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6550 for (y
= 0; y
< height
; ++y
)
6552 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6553 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6554 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6558 fn_jpeg_finish_decompress (&cinfo
);
6559 fn_jpeg_destroy_decompress (&cinfo
);
6561 fclose ((FILE *) fp
);
6563 /* Maybe fill in the background field while we have ximg handy. */
6564 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6565 IMAGE_BACKGROUND (img
, f
, ximg
);
6567 /* Put the image into the pixmap. */
6568 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6569 x_destroy_x_image (ximg
);
6574 #else /* HAVE_JPEG */
6583 return image_load_quartz2d (f
, img
, 0);
6585 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
6590 #endif /* !HAVE_JPEG */
6594 /***********************************************************************
6596 ***********************************************************************/
6598 #if defined (HAVE_TIFF) || defined (MAC_OS)
6600 static int tiff_image_p
P_ ((Lisp_Object object
));
6601 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6603 /* The symbol `tiff' identifying images of this type. */
6607 /* Indices of image specification fields in tiff_format, below. */
6609 enum tiff_keyword_index
6618 TIFF_HEURISTIC_MASK
,
6624 /* Vector of image_keyword structures describing the format
6625 of valid user-defined image specifications. */
6627 static struct image_keyword tiff_format
[TIFF_LAST
] =
6629 {":type", IMAGE_SYMBOL_VALUE
, 1},
6630 {":data", IMAGE_STRING_VALUE
, 0},
6631 {":file", IMAGE_STRING_VALUE
, 0},
6632 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6633 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6634 {":relief", IMAGE_INTEGER_VALUE
, 0},
6635 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6636 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6637 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6638 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6641 /* Structure describing the image type `tiff'. */
6643 static struct image_type tiff_type
=
6652 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6655 tiff_image_p (object
)
6658 struct image_keyword fmt
[TIFF_LAST
];
6659 bcopy (tiff_format
, fmt
, sizeof fmt
);
6661 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6664 /* Must specify either the :data or :file keyword. */
6665 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6668 #endif /* HAVE_TIFF || MAC_OS */
6676 /* TIFF library details. */
6677 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6678 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6679 DEF_IMGLIB_FN (TIFFOpen
);
6680 DEF_IMGLIB_FN (TIFFClientOpen
);
6681 DEF_IMGLIB_FN (TIFFGetField
);
6682 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6683 DEF_IMGLIB_FN (TIFFClose
);
6686 init_tiff_functions (void)
6690 if (!(library
= LoadLibrary ("libtiff.dll")))
6693 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6694 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6695 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6696 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6697 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6698 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6699 LOAD_IMGLIB_FN (library
, TIFFClose
);
6705 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6706 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6707 #define fn_TIFFOpen TIFFOpen
6708 #define fn_TIFFClientOpen TIFFClientOpen
6709 #define fn_TIFFGetField TIFFGetField
6710 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6711 #define fn_TIFFClose TIFFClose
6713 #endif /* HAVE_NTGUI */
6716 /* Reading from a memory buffer for TIFF images Based on the PNG
6717 memory source, but we have to provide a lot of extra functions.
6720 We really only need to implement read and seek, but I am not
6721 convinced that the TIFF library is smart enough not to destroy
6722 itself if we only hand it the function pointers we need to
6727 unsigned char *bytes
;
6734 tiff_read_from_memory (data
, buf
, size
)
6739 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6741 if (size
> src
->len
- src
->index
)
6743 bcopy (src
->bytes
+ src
->index
, buf
, size
);
6749 tiff_write_from_memory (data
, buf
, size
)
6758 tiff_seek_in_memory (data
, off
, whence
)
6763 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6768 case SEEK_SET
: /* Go from beginning of source. */
6772 case SEEK_END
: /* Go from end of source. */
6773 idx
= src
->len
+ off
;
6776 case SEEK_CUR
: /* Go from current position. */
6777 idx
= src
->index
+ off
;
6780 default: /* Invalid `whence'. */
6784 if (idx
> src
->len
|| idx
< 0)
6792 tiff_close_memory (data
)
6800 tiff_mmap_memory (data
, pbase
, psize
)
6805 /* It is already _IN_ memory. */
6810 tiff_unmap_memory (data
, base
, size
)
6815 /* We don't need to do this. */
6819 tiff_size_of_memory (data
)
6822 return ((tiff_memory_source
*) data
)->len
;
6827 tiff_error_handler (title
, format
, ap
)
6828 const char *title
, *format
;
6834 len
= sprintf (buf
, "TIFF error: %s ", title
);
6835 vsprintf (buf
+ len
, format
, ap
);
6836 add_to_log (buf
, Qnil
, Qnil
);
6841 tiff_warning_handler (title
, format
, ap
)
6842 const char *title
, *format
;
6848 len
= sprintf (buf
, "TIFF warning: %s ", title
);
6849 vsprintf (buf
+ len
, format
, ap
);
6850 add_to_log (buf
, Qnil
, Qnil
);
6854 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6862 Lisp_Object file
, specified_file
;
6863 Lisp_Object specified_data
;
6865 int width
, height
, x
, y
;
6869 struct gcpro gcpro1
;
6870 tiff_memory_source memsrc
;
6872 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6873 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6877 fn_TIFFSetErrorHandler (tiff_error_handler
);
6878 fn_TIFFSetWarningHandler (tiff_warning_handler
);
6880 if (NILP (specified_data
))
6882 /* Read from a file */
6883 file
= x_find_image_file (specified_file
);
6884 if (!STRINGP (file
))
6886 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6891 /* Try to open the image file. */
6892 tiff
= fn_TIFFOpen (SDATA (file
), "r");
6895 image_error ("Cannot open `%s'", file
, Qnil
);
6902 /* Memory source! */
6903 memsrc
.bytes
= SDATA (specified_data
);
6904 memsrc
.len
= SBYTES (specified_data
);
6907 tiff
= fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
6908 (TIFFReadWriteProc
) tiff_read_from_memory
,
6909 (TIFFReadWriteProc
) tiff_write_from_memory
,
6910 tiff_seek_in_memory
,
6912 tiff_size_of_memory
,
6918 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
6924 /* Get width and height of the image, and allocate a raster buffer
6925 of width x height 32-bit values. */
6926 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
6927 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
6928 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
6930 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
6931 fn_TIFFClose (tiff
);
6934 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
6940 /* Create the X image and pixmap. */
6941 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6948 /* Initialize the color table. */
6949 init_color_table ();
6951 /* Process the pixel raster. Origin is in the lower-left corner. */
6952 for (y
= 0; y
< height
; ++y
)
6954 uint32
*row
= buf
+ y
* width
;
6956 for (x
= 0; x
< width
; ++x
)
6958 uint32 abgr
= row
[x
];
6959 int r
= TIFFGetR (abgr
) << 8;
6960 int g
= TIFFGetG (abgr
) << 8;
6961 int b
= TIFFGetB (abgr
) << 8;
6962 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
6966 #ifdef COLOR_TABLE_SUPPORT
6967 /* Remember the colors allocated for the image. Free the color table. */
6968 img
->colors
= colors_in_color_table (&img
->ncolors
);
6969 free_color_table ();
6970 #endif /* COLOR_TABLE_SUPPORT */
6973 img
->height
= height
;
6975 /* Maybe fill in the background field while we have ximg handy. */
6976 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6977 IMAGE_BACKGROUND (img
, f
, ximg
);
6979 /* Put the image into the pixmap, then free the X image and its buffer. */
6980 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6981 x_destroy_x_image (ximg
);
6988 #else /* HAVE_TIFF */
6996 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7000 #endif /* !HAVE_TIFF */
7004 /***********************************************************************
7006 ***********************************************************************/
7008 #if defined (HAVE_GIF) || defined (MAC_OS)
7010 static int gif_image_p
P_ ((Lisp_Object object
));
7011 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7013 /* The symbol `gif' identifying images of this type. */
7017 /* Indices of image specification fields in gif_format, below. */
7019 enum gif_keyword_index
7035 /* Vector of image_keyword structures describing the format
7036 of valid user-defined image specifications. */
7038 static struct image_keyword gif_format
[GIF_LAST
] =
7040 {":type", IMAGE_SYMBOL_VALUE
, 1},
7041 {":data", IMAGE_STRING_VALUE
, 0},
7042 {":file", IMAGE_STRING_VALUE
, 0},
7043 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7044 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7045 {":relief", IMAGE_INTEGER_VALUE
, 0},
7046 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7047 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7048 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7049 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7050 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7053 /* Structure describing the image type `gif'. */
7055 static struct image_type gif_type
=
7064 /* Return non-zero if OBJECT is a valid GIF image specification. */
7067 gif_image_p (object
)
7070 struct image_keyword fmt
[GIF_LAST
];
7071 bcopy (gif_format
, fmt
, sizeof fmt
);
7073 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7076 /* Must specify either the :data or :file keyword. */
7077 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7080 #endif /* HAVE_GIF || MAC_OS */
7084 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7085 /* avoid conflict with QuickdrawText.h */
7086 #define DrawText gif_DrawText
7087 #include <gif_lib.h>
7090 #else /* HAVE_NTGUI || MAC_OS */
7092 #include <gif_lib.h>
7094 #endif /* HAVE_NTGUI || MAC_OS */
7099 /* GIF library details. */
7100 DEF_IMGLIB_FN (DGifCloseFile
);
7101 DEF_IMGLIB_FN (DGifSlurp
);
7102 DEF_IMGLIB_FN (DGifOpen
);
7103 DEF_IMGLIB_FN (DGifOpenFileName
);
7106 init_gif_functions (void)
7110 if (!(library
= LoadLibrary ("libungif.dll")))
7113 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7114 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7115 LOAD_IMGLIB_FN (library
, DGifOpen
);
7116 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7122 #define fn_DGifCloseFile DGifCloseFile
7123 #define fn_DGifSlurp DGifSlurp
7124 #define fn_DGifOpen DGifOpen
7125 #define fn_DGifOpenFileName DGifOpenFileName
7127 #endif /* HAVE_NTGUI */
7129 /* Reading a GIF image from memory
7130 Based on the PNG memory stuff to a certain extent. */
7134 unsigned char *bytes
;
7140 /* Make the current memory source available to gif_read_from_memory.
7141 It's done this way because not all versions of libungif support
7142 a UserData field in the GifFileType structure. */
7143 static gif_memory_source
*current_gif_memory_src
;
7146 gif_read_from_memory (file
, buf
, len
)
7151 gif_memory_source
*src
= current_gif_memory_src
;
7153 if (len
> src
->len
- src
->index
)
7156 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7162 /* Load GIF image IMG for use on frame F. Value is non-zero if
7170 Lisp_Object file
, specified_file
;
7171 Lisp_Object specified_data
;
7172 int rc
, width
, height
, x
, y
, i
;
7174 ColorMapObject
*gif_color_map
;
7175 unsigned long pixel_colors
[256];
7177 struct gcpro gcpro1
;
7179 int ino
, image_left
, image_top
, image_width
, image_height
;
7180 gif_memory_source memsrc
;
7181 unsigned char *raster
;
7183 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7184 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7188 if (NILP (specified_data
))
7190 file
= x_find_image_file (specified_file
);
7191 if (!STRINGP (file
))
7193 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7198 /* Open the GIF file. */
7199 gif
= fn_DGifOpenFileName (SDATA (file
));
7202 image_error ("Cannot open `%s'", file
, Qnil
);
7209 /* Read from memory! */
7210 current_gif_memory_src
= &memsrc
;
7211 memsrc
.bytes
= SDATA (specified_data
);
7212 memsrc
.len
= SBYTES (specified_data
);
7215 gif
= fn_DGifOpen(&memsrc
, gif_read_from_memory
);
7218 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7224 /* Read entire contents. */
7225 rc
= fn_DGifSlurp (gif
);
7226 if (rc
== GIF_ERROR
)
7228 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7229 fn_DGifCloseFile (gif
);
7234 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7235 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7236 if (ino
>= gif
->ImageCount
)
7238 image_error ("Invalid image number `%s' in image `%s'",
7240 fn_DGifCloseFile (gif
);
7245 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
7246 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
7248 /* Create the X image and pixmap. */
7249 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7251 fn_DGifCloseFile (gif
);
7256 /* Allocate colors. */
7257 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7259 gif_color_map
= gif
->SColorMap
;
7260 init_color_table ();
7261 bzero (pixel_colors
, sizeof pixel_colors
);
7263 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7265 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7266 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7267 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7268 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7271 #ifdef COLOR_TABLE_SUPPORT
7272 img
->colors
= colors_in_color_table (&img
->ncolors
);
7273 free_color_table ();
7274 #endif /* COLOR_TABLE_SUPPORT */
7276 /* Clear the part of the screen image that are not covered by
7277 the image from the GIF file. Full animated GIF support
7278 requires more than can be done here (see the gif89 spec,
7279 disposal methods). Let's simply assume that the part
7280 not covered by a sub-image is in the frame's background color. */
7281 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
7282 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
7283 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7284 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7286 for (y
= 0; y
< image_top
; ++y
)
7287 for (x
= 0; x
< width
; ++x
)
7288 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7290 for (y
= image_top
+ image_height
; y
< height
; ++y
)
7291 for (x
= 0; x
< width
; ++x
)
7292 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7294 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
7296 for (x
= 0; x
< image_left
; ++x
)
7297 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7298 for (x
= image_left
+ image_width
; x
< width
; ++x
)
7299 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7302 /* Read the GIF image into the X image. We use a local variable
7303 `raster' here because RasterBits below is a char *, and invites
7304 problems with bytes >= 0x80. */
7305 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7307 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7309 static int interlace_start
[] = {0, 4, 2, 1};
7310 static int interlace_increment
[] = {8, 8, 4, 2};
7312 int row
= interlace_start
[0];
7316 for (y
= 0; y
< image_height
; y
++)
7318 if (row
>= image_height
)
7320 row
= interlace_start
[++pass
];
7321 while (row
>= image_height
)
7322 row
= interlace_start
[++pass
];
7325 for (x
= 0; x
< image_width
; x
++)
7327 int i
= raster
[(y
* image_width
) + x
];
7328 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
7332 row
+= interlace_increment
[pass
];
7337 for (y
= 0; y
< image_height
; ++y
)
7338 for (x
= 0; x
< image_width
; ++x
)
7340 int i
= raster
[y
* image_width
+ x
];
7341 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
7345 fn_DGifCloseFile (gif
);
7347 /* Maybe fill in the background field while we have ximg handy. */
7348 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7349 IMAGE_BACKGROUND (img
, f
, ximg
);
7351 /* Put the image into the pixmap, then free the X image and its buffer. */
7352 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7353 x_destroy_x_image (ximg
);
7367 Lisp_Object specified_file
, file
;
7368 Lisp_Object specified_data
;
7370 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
7378 Lisp_Object specified_bg
;
7384 struct gcpro gcpro1
;
7389 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7390 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7392 if (NILP (specified_data
))
7394 /* Read from a file */
7398 err
= find_image_fsspec (specified_file
, &file
, &fss
);
7402 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7407 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
7408 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
7412 if (!graphic_p
&& !movie_p
)
7414 if (prefer_graphic_p
)
7415 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
7416 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
7419 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
7420 CloseMovieFile (refnum
);
7423 image_error ("Error reading `%s'", file
, Qnil
);
7429 /* Memory source! */
7431 long file_type_atom
[3];
7433 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
7436 image_error ("Cannot allocate data handle for `%s'",
7441 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
7442 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
7443 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
7444 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
7447 err
= PtrAndHand ("\p", dref
, 1);
7449 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
7452 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
7455 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
7456 &movie_p
, &prefer_graphic_p
, 0);
7460 if (!graphic_p
&& !movie_p
)
7462 if (prefer_graphic_p
)
7466 DisposeHandle (dref
);
7467 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
7471 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
7472 HandleDataHandlerSubType
);
7473 DisposeHandle (dref
);
7478 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7479 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7480 track
= GetMovieIndTrack (movie
, 1);
7481 media
= GetTrackMedia (track
);
7482 nsamples
= GetMediaSampleCount (media
);
7483 if (ino
>= nsamples
)
7485 image_error ("Invalid image number `%s' in image `%s'",
7490 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7491 if (!STRINGP (specified_bg
) ||
7492 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
7494 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
7495 color
.red
= RED16_FROM_ULONG (color
.pixel
);
7496 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
7497 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
7499 GetMovieBox (movie
, &rect
);
7500 width
= img
->width
= rect
.right
- rect
.left
;
7501 height
= img
->height
= rect
.bottom
- rect
.top
;
7502 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7505 GetGWorld (&old_port
, &old_gdh
);
7506 SetGWorld (ximg
, NULL
);
7507 bg_color
.red
= color
.red
;
7508 bg_color
.green
= color
.green
;
7509 bg_color
.blue
= color
.blue
;
7510 RGBBackColor (&bg_color
);
7511 SetGWorld (old_port
, old_gdh
);
7512 SetMovieActive (movie
, TRUE
);
7513 SetMovieGWorld (movie
, ximg
, NULL
);
7514 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7515 SetMovieTimeValue (movie
, time
);
7516 MoviesTask (movie
, 0L);
7517 DisposeTrackMedia (media
);
7518 DisposeMovieTrack (track
);
7519 DisposeMovie (movie
);
7522 /* Maybe fill in the background field while we have ximg handy. */
7523 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7524 IMAGE_BACKGROUND (img
, f
, ximg
);
7526 /* Put the image into the pixmap. */
7527 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7528 x_destroy_x_image (ximg
);
7532 image_error ("Cannot open `%s'", file
, Qnil
);
7535 DisposeTrackMedia (media
);
7537 DisposeMovieTrack (track
);
7539 DisposeMovie (movie
);
7546 #endif /* HAVE_GIF */
7550 /***********************************************************************
7552 ***********************************************************************/
7554 #ifdef HAVE_X_WINDOWS
7555 #define HAVE_GHOSTSCRIPT 1
7556 #endif /* HAVE_X_WINDOWS */
7558 /* The symbol `postscript' identifying images of this type. */
7560 Lisp_Object Qpostscript
;
7562 #ifdef HAVE_GHOSTSCRIPT
7564 static int gs_image_p
P_ ((Lisp_Object object
));
7565 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
7566 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7568 /* Keyword symbols. */
7570 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
7572 /* Indices of image specification fields in gs_format, below. */
7574 enum gs_keyword_index
7592 /* Vector of image_keyword structures describing the format
7593 of valid user-defined image specifications. */
7595 static struct image_keyword gs_format
[GS_LAST
] =
7597 {":type", IMAGE_SYMBOL_VALUE
, 1},
7598 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7599 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7600 {":file", IMAGE_STRING_VALUE
, 1},
7601 {":loader", IMAGE_FUNCTION_VALUE
, 0},
7602 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
7603 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7604 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7605 {":relief", IMAGE_INTEGER_VALUE
, 0},
7606 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7607 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7608 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7609 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7612 /* Structure describing the image type `ghostscript'. */
7614 static struct image_type gs_type
=
7624 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7627 gs_clear_image (f
, img
)
7631 /* IMG->data.ptr_val may contain a recorded colormap. */
7632 xfree (img
->data
.ptr_val
);
7633 x_clear_image (f
, img
);
7637 /* Return non-zero if OBJECT is a valid Ghostscript image
7644 struct image_keyword fmt
[GS_LAST
];
7648 bcopy (gs_format
, fmt
, sizeof fmt
);
7650 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
7653 /* Bounding box must be a list or vector containing 4 integers. */
7654 tem
= fmt
[GS_BOUNDING_BOX
].value
;
7657 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
7658 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
7663 else if (VECTORP (tem
))
7665 if (XVECTOR (tem
)->size
!= 4)
7667 for (i
= 0; i
< 4; ++i
)
7668 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
7678 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7687 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
7688 struct gcpro gcpro1
, gcpro2
;
7690 double in_width
, in_height
;
7691 Lisp_Object pixel_colors
= Qnil
;
7693 /* Compute pixel size of pixmap needed from the given size in the
7694 image specification. Sizes in the specification are in pt. 1 pt
7695 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7697 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
7698 in_width
= XFASTINT (pt_width
) / 72.0;
7699 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
7700 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
7701 in_height
= XFASTINT (pt_height
) / 72.0;
7702 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
7704 /* Create the pixmap. */
7705 xassert (img
->pixmap
== NO_PIXMAP
);
7707 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7709 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7710 img
->width
, img
->height
,
7711 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
7716 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
7720 /* Call the loader to fill the pixmap. It returns a process object
7721 if successful. We do not record_unwind_protect here because
7722 other places in redisplay like calling window scroll functions
7723 don't either. Let the Lisp loader use `unwind-protect' instead. */
7724 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
7726 sprintf (buffer
, "%lu %lu",
7727 (unsigned long) FRAME_X_WINDOW (f
),
7728 (unsigned long) img
->pixmap
);
7729 window_and_pixmap_id
= build_string (buffer
);
7731 sprintf (buffer
, "%lu %lu",
7732 FRAME_FOREGROUND_PIXEL (f
),
7733 FRAME_BACKGROUND_PIXEL (f
));
7734 pixel_colors
= build_string (buffer
);
7736 XSETFRAME (frame
, f
);
7737 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
7739 loader
= intern ("gs-load-image");
7741 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
7742 make_number (img
->width
),
7743 make_number (img
->height
),
7744 window_and_pixmap_id
,
7747 return PROCESSP (img
->data
.lisp_val
);
7751 /* Kill the Ghostscript process that was started to fill PIXMAP on
7752 frame F. Called from XTread_socket when receiving an event
7753 telling Emacs that Ghostscript has finished drawing. */
7756 x_kill_gs_process (pixmap
, f
)
7760 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7764 /* Find the image containing PIXMAP. */
7765 for (i
= 0; i
< c
->used
; ++i
)
7766 if (c
->images
[i
]->pixmap
== pixmap
)
7769 /* Should someone in between have cleared the image cache, for
7770 instance, give up. */
7774 /* Kill the GS process. We should have found PIXMAP in the image
7775 cache and its image should contain a process object. */
7777 xassert (PROCESSP (img
->data
.lisp_val
));
7778 Fkill_process (img
->data
.lisp_val
, Qnil
);
7779 img
->data
.lisp_val
= Qnil
;
7781 #if defined (HAVE_X_WINDOWS)
7783 /* On displays with a mutable colormap, figure out the colors
7784 allocated for the image by looking at the pixels of an XImage for
7786 class = FRAME_X_VISUAL (f
)->class;
7787 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
7793 /* Try to get an XImage for img->pixmep. */
7794 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7795 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7800 /* Initialize the color table. */
7801 init_color_table ();
7803 /* For each pixel of the image, look its color up in the
7804 color table. After having done so, the color table will
7805 contain an entry for each color used by the image. */
7806 for (y
= 0; y
< img
->height
; ++y
)
7807 for (x
= 0; x
< img
->width
; ++x
)
7809 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
7810 lookup_pixel_color (f
, pixel
);
7813 /* Record colors in the image. Free color table and XImage. */
7814 #ifdef COLOR_TABLE_SUPPORT
7815 img
->colors
= colors_in_color_table (&img
->ncolors
);
7816 free_color_table ();
7818 XDestroyImage (ximg
);
7820 #if 0 /* This doesn't seem to be the case. If we free the colors
7821 here, we get a BadAccess later in x_clear_image when
7822 freeing the colors. */
7823 /* We have allocated colors once, but Ghostscript has also
7824 allocated colors on behalf of us. So, to get the
7825 reference counts right, free them once. */
7827 x_free_colors (f
, img
->colors
, img
->ncolors
);
7831 image_error ("Cannot get X image of `%s'; colors will not be freed",
7836 #endif /* HAVE_X_WINDOWS */
7838 /* Now that we have the pixmap, compute mask and transform the
7839 image if requested. */
7841 postprocess_image (f
, img
);
7845 #endif /* HAVE_GHOSTSCRIPT */
7848 /***********************************************************************
7850 ***********************************************************************/
7854 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
7855 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
7859 return valid_image_p (spec
) ? Qt
: Qnil
;
7863 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
7869 if (valid_image_p (spec
))
7870 id
= lookup_image (SELECTED_FRAME (), spec
);
7873 return make_number (id
);
7876 #endif /* GLYPH_DEBUG != 0 */
7879 /***********************************************************************
7881 ***********************************************************************/
7886 QCascent
= intern (":ascent");
7887 staticpro (&QCascent
);
7888 QCmargin
= intern (":margin");
7889 staticpro (&QCmargin
);
7890 QCrelief
= intern (":relief");
7891 staticpro (&QCrelief
);
7892 QCconversion
= intern (":conversion");
7893 staticpro (&QCconversion
);
7894 QCcolor_symbols
= intern (":color-symbols");
7895 staticpro (&QCcolor_symbols
);
7896 QCheuristic_mask
= intern (":heuristic-mask");
7897 staticpro (&QCheuristic_mask
);
7898 QCindex
= intern (":index");
7899 staticpro (&QCindex
);
7900 QCmatrix
= intern (":matrix");
7901 staticpro (&QCmatrix
);
7902 QCcolor_adjustment
= intern (":color-adjustment");
7903 staticpro (&QCcolor_adjustment
);
7904 QCmask
= intern (":mask");
7905 staticpro (&QCmask
);
7907 Qlaplace
= intern ("laplace");
7908 staticpro (&Qlaplace
);
7909 Qemboss
= intern ("emboss");
7910 staticpro (&Qemboss
);
7911 Qedge_detection
= intern ("edge-detection");
7912 staticpro (&Qedge_detection
);
7913 Qheuristic
= intern ("heuristic");
7914 staticpro (&Qheuristic
);
7916 Qpostscript
= intern ("postscript");
7917 staticpro (&Qpostscript
);
7918 #ifdef HAVE_GHOSTSCRIPT
7919 QCloader
= intern (":loader");
7920 staticpro (&QCloader
);
7921 QCbounding_box
= intern (":bounding-box");
7922 staticpro (&QCbounding_box
);
7923 QCpt_width
= intern (":pt-width");
7924 staticpro (&QCpt_width
);
7925 QCpt_height
= intern (":pt-height");
7926 staticpro (&QCpt_height
);
7927 #endif /* HAVE_GHOSTSCRIPT */
7929 Qpbm
= intern ("pbm");
7932 Qxbm
= intern ("xbm");
7935 #if defined (HAVE_XPM) || defined (MAC_OS)
7936 Qxpm
= intern ("xpm");
7940 #if defined (HAVE_JPEG) || defined (MAC_OS)
7941 Qjpeg
= intern ("jpeg");
7945 #if defined (HAVE_TIFF) || defined (MAC_OS)
7946 Qtiff
= intern ("tiff");
7950 #if defined (HAVE_GIF) || defined (MAC_OS)
7951 Qgif
= intern ("gif");
7955 #if defined (HAVE_PNG) || defined (MAC_OS)
7956 Qpng
= intern ("png");
7960 defsubr (&Sclear_image_cache
);
7961 defsubr (&Simage_size
);
7962 defsubr (&Simage_mask_p
);
7966 defsubr (&Slookup_image
);
7969 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
7970 doc
: /* Non-nil means always draw a cross over disabled images.
7971 Disabled images are those having an `:conversion disabled' property.
7972 A cross is always drawn on black & white displays. */);
7973 cross_disabled_images
= 0;
7975 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
7976 doc
: /* List of directories to search for window system bitmap files. */);
7977 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
7979 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
7980 doc
: /* Time after which cached images are removed from the cache.
7981 When an image has not been displayed this many seconds, remove it
7982 from the image cache. Value must be an integer or nil with nil
7983 meaning don't clear the cache. */);
7984 Vimage_cache_eviction_delay
= make_number (30 * 60);
7989 /* Image types that rely on external libraries are loaded dynamically
7990 if the library is available. */
7991 #define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn())
7993 #define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */
7994 #endif /* HAVE_NTGUI */
8000 Vimage_types
= Qnil
;
8002 define_image_type (&xbm_type
);
8003 define_image_type (&pbm_type
);
8005 #if defined (HAVE_XPM) || defined (MAC_OS)
8006 IF_LIB_AVAILABLE(init_xpm_functions
)
8007 define_image_type (&xpm_type
);
8010 #if defined (HAVE_JPEG) || defined (MAC_OS)
8011 IF_LIB_AVAILABLE(init_jpeg_functions
)
8012 define_image_type (&jpeg_type
);
8015 #if defined (HAVE_TIFF) || defined (MAC_OS)
8016 IF_LIB_AVAILABLE(init_tiff_functions
)
8017 define_image_type (&tiff_type
);
8020 #if defined (HAVE_GIF) || defined (MAC_OS)
8021 IF_LIB_AVAILABLE(init_gif_functions
)
8022 define_image_type (&gif_type
);
8025 #if defined (HAVE_PNG) || defined (MAC_OS)
8026 IF_LIB_AVAILABLE(init_png_functions
)
8027 define_image_type (&png_type
);
8030 #ifdef HAVE_GHOSTSCRIPT
8031 define_image_type (&gs_type
);
8035 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8038 init_image_func_pointer ();
8043 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8044 (do not change this comment) */