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. */
32 /* This makes the fields of a Display accessible, in Xlib header files. */
34 #define XLIB_ILLEGAL_ACCESS
39 #include "dispextern.h"
40 #include "blockinput.h"
47 #include <sys/types.h>
50 #define COLOR_TABLE_SUPPORT 1
52 typedef struct x_bitmap_record Bitmap_Record
;
53 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
54 #define NO_PIXMAP None
56 #define RGB_PIXEL_COLOR unsigned long
58 #define PIX_MASK_RETAIN(f) 0
59 #define PIX_MASK_DRAW(f) 1
60 #endif /* HAVE_X_WINDOWS */
66 /* W32_TODO : Color tables on W32. */
67 #undef COLOR_TABLE_SUPPORT
69 typedef struct w32_bitmap_record Bitmap_Record
;
70 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
73 #define RGB_PIXEL_COLOR COLORREF
75 #define PIX_MASK_RETAIN(f) 0
76 #define PIX_MASK_DRAW(f) 1
78 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
79 #define x_defined_color w32_defined_color
80 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
81 #endif /* HAVE_NTGUI */
91 #include <QuickTime/QuickTime.h>
92 #else /* not MAC_OSX */
95 #include <TextUtils.h>
96 #endif /* not MAC_OSX */
98 /* MAC_TODO : Color tables on Mac. */
99 #undef COLOR_TABLE_SUPPORT
101 #define ZPixmap 0 /* arbitrary */
102 typedef struct mac_bitmap_record Bitmap_Record
;
104 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
107 #define RGB_PIXEL_COLOR unsigned long
109 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
110 #define x_defined_color mac_defined_color
111 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
112 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
113 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
118 /* Search path for bitmap files. */
120 Lisp_Object Vx_bitmap_file_path
;
123 static void x_disable_image
P_ ((struct frame
*, struct image
*));
124 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
127 static void init_color_table
P_ ((void));
128 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
129 #ifdef COLOR_TABLE_SUPPORT
130 static void free_color_table
P_ ((void));
131 static unsigned long *colors_in_color_table
P_ ((int *n
));
132 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
135 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
136 id, which is just an int that this section returns. Bitmaps are
137 reference counted so they can be shared among frames.
139 Bitmap indices are guaranteed to be > 0, so a negative number can
140 be used to indicate no bitmap.
142 If you use x_create_bitmap_from_data, then you must keep track of
143 the bitmaps yourself. That is, creating a bitmap from the same
144 data more than once will not be caught. */
149 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
150 Display
*display
; /* not used */
152 int x
, y
; /* not used */
153 unsigned int width
, height
; /* not used */
154 unsigned long plane_mask
; /* not used */
155 int format
; /* not used */
158 xassert (x
== 0 && y
== 0);
161 SetRect (&ri
, 0, 0, width
, height
);
162 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
164 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
167 LockPixels (GetGWorldPixMap (pixmap
));
173 XPutPixel (ximage
, x
, y
, pixel
)
182 GetGWorld (&old_port
, &old_gdh
);
183 SetGWorld (ximage
, NULL
);
185 color
.red
= RED16_FROM_ULONG (pixel
);
186 color
.green
= GREEN16_FROM_ULONG (pixel
);
187 color
.blue
= BLUE16_FROM_ULONG (pixel
);
188 SetCPixel (x
, y
, &color
);
190 SetGWorld (old_port
, old_gdh
);
194 XGetPixel (ximage
, x
, y
)
202 GetGWorld (&old_port
, &old_gdh
);
203 SetGWorld (ximage
, NULL
);
205 GetCPixel (x
, y
, &color
);
207 SetGWorld (old_port
, old_gdh
);
208 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
215 UnlockPixels (GetGWorldPixMap (ximg
));
220 /* Functions to access the contents of a bitmap, given an id. */
223 x_bitmap_height (f
, id
)
227 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
231 x_bitmap_width (f
, id
)
235 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
238 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
240 x_bitmap_pixmap (f
, id
)
244 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
248 #ifdef HAVE_X_WINDOWS
250 x_bitmap_mask (f
, id
)
254 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
258 /* Allocate a new bitmap record. Returns index of new record. */
261 x_allocate_bitmap_record (f
)
264 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
267 if (dpyinfo
->bitmaps
== NULL
)
269 dpyinfo
->bitmaps_size
= 10;
271 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
272 dpyinfo
->bitmaps_last
= 1;
276 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
277 return ++dpyinfo
->bitmaps_last
;
279 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
280 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
283 dpyinfo
->bitmaps_size
*= 2;
285 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
286 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
287 return ++dpyinfo
->bitmaps_last
;
290 /* Add one reference to the reference count of the bitmap with id ID. */
293 x_reference_bitmap (f
, id
)
297 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
300 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
303 x_create_bitmap_from_data (f
, bits
, width
, height
)
306 unsigned int width
, height
;
308 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
311 #ifdef HAVE_X_WINDOWS
313 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
314 bits
, width
, height
);
317 #endif /* HAVE_X_WINDOWS */
321 bitmap
= CreateBitmap (width
, height
,
322 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
323 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
327 #endif /* HAVE_NTGUI */
330 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
335 id
= x_allocate_bitmap_record (f
);
337 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
338 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
340 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
343 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
344 dpyinfo
->bitmaps
[id
- 1].height
= height
;
345 dpyinfo
->bitmaps
[id
- 1].width
= width
;
346 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
348 #ifdef HAVE_X_WINDOWS
349 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
350 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
351 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
352 #endif /* HAVE_X_WINDOWS */
355 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
356 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
357 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
358 #endif /* HAVE_NTGUI */
363 /* Create bitmap from file FILE for frame F. */
366 x_create_bitmap_from_file (f
, file
)
371 return -1; /* MAC_TODO : bitmap support */
375 return -1; /* W32_TODO : bitmap support */
376 #endif /* HAVE_NTGUI */
378 #ifdef HAVE_X_WINDOWS
379 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
380 unsigned int width
, height
;
382 int xhot
, yhot
, result
, id
;
387 /* Look for an existing bitmap with the same name. */
388 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
390 if (dpyinfo
->bitmaps
[id
].refcount
391 && dpyinfo
->bitmaps
[id
].file
392 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
394 ++dpyinfo
->bitmaps
[id
].refcount
;
399 /* Search bitmap-file-path for the file, if appropriate. */
400 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
405 filename
= (char *) SDATA (found
);
407 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
408 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
409 if (result
!= BitmapSuccess
)
412 id
= x_allocate_bitmap_record (f
);
413 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
414 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
415 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
416 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
417 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
418 dpyinfo
->bitmaps
[id
- 1].height
= height
;
419 dpyinfo
->bitmaps
[id
- 1].width
= width
;
420 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
423 #endif /* HAVE_X_WINDOWS */
429 Free_Bitmap_Record (dpyinfo
, bm
)
430 Display_Info
*dpyinfo
;
433 #ifdef HAVE_X_WINDOWS
434 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
436 XFreePixmap (dpyinfo
->display
, bm
->mask
);
437 #endif /* HAVE_X_WINDOWS */
440 DeleteObject (bm
->pixmap
);
441 #endif /* HAVE_NTGUI */
444 xfree (bm
->bitmap_data
); /* Added ++kfs */
445 bm
->bitmap_data
= NULL
;
455 /* Remove reference to bitmap with id number ID. */
458 x_destroy_bitmap (f
, id
)
462 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
466 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
468 if (--bm
->refcount
== 0)
471 Free_Bitmap_Record (dpyinfo
, bm
);
477 /* Free all the bitmaps for the display specified by DPYINFO. */
480 x_destroy_all_bitmaps (dpyinfo
)
481 Display_Info
*dpyinfo
;
484 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
486 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
487 if (bm
->refcount
> 0)
488 Free_Bitmap_Record (dpyinfo
, bm
);
490 dpyinfo
->bitmaps_last
= 0;
494 #ifdef HAVE_X_WINDOWS
496 /* Useful functions defined in the section
497 `Image type independent image structures' below. */
499 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
500 unsigned long height
));
502 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
503 int depth
, XImagePtr
*ximg
,
506 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
509 /* Create a mask of a bitmap. Note is this not a perfect mask.
510 It's nicer with some borders in this context */
513 x_create_bitmap_mask (f
, id
)
518 XImagePtr ximg
, mask_img
;
519 unsigned long width
, height
;
522 unsigned long x
, y
, xp
, xm
, yp
, ym
;
525 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
530 pixmap
= x_bitmap_pixmap (f
, id
);
531 width
= x_bitmap_width (f
, id
);
532 height
= x_bitmap_height (f
, id
);
535 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
544 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
549 XDestroyImage (ximg
);
553 bg
= four_corners_best (ximg
, width
, height
);
555 for (y
= 0; y
< ximg
->height
; ++y
)
557 for (x
= 0; x
< ximg
->width
; ++x
)
559 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
560 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
561 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
562 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
563 if (XGetPixel (ximg
, x
, y
) == bg
564 && XGetPixel (ximg
, x
, yp
) == bg
565 && XGetPixel (ximg
, x
, ym
) == bg
566 && XGetPixel (ximg
, xp
, y
) == bg
567 && XGetPixel (ximg
, xp
, yp
) == bg
568 && XGetPixel (ximg
, xp
, ym
) == bg
569 && XGetPixel (ximg
, xm
, y
) == bg
570 && XGetPixel (ximg
, xm
, yp
) == bg
571 && XGetPixel (ximg
, xm
, ym
) == bg
)
572 XPutPixel (mask_img
, x
, y
, 0);
574 XPutPixel (mask_img
, x
, y
, 1);
578 xassert (interrupt_input_blocked
);
579 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
580 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
582 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
584 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
585 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
587 XDestroyImage (ximg
);
588 x_destroy_x_image (mask_img
);
593 #endif /* HAVE_X_WINDOWS */
596 /***********************************************************************
598 ***********************************************************************/
600 /* Value is the number of elements of vector VECTOR. */
602 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
604 /* List of supported image types. Use define_image_type to add new
605 types. Use lookup_image_type to find a type for a given symbol. */
607 static struct image_type
*image_types
;
609 /* A list of symbols, one for each supported image type. */
611 Lisp_Object Vimage_types
;
613 /* Cache for delayed-loading image types. */
615 static Lisp_Object Vimage_type_cache
;
617 /* The symbol `xbm' which is used as the type symbol for XBM images. */
623 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
624 extern Lisp_Object QCdata
, QCtype
;
625 extern Lisp_Object Qcenter
;
626 Lisp_Object QCascent
, QCmargin
, QCrelief
;
627 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
628 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
632 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
634 /* Time in seconds after which images should be removed from the cache
637 Lisp_Object Vimage_cache_eviction_delay
;
639 /* Function prototypes. */
641 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
642 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
643 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
644 static void x_laplace
P_ ((struct frame
*, struct image
*));
645 static void x_emboss
P_ ((struct frame
*, struct image
*));
646 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
649 #define CACHE_IMAGE_TYPE(type, status) \
650 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
652 #define ADD_IMAGE_TYPE(type) \
653 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
655 /* Define a new image type from TYPE. This adds a copy of TYPE to
656 image_types and caches the loading status of TYPE. */
659 define_image_type (type
, loaded
)
660 struct image_type
*type
;
669 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
670 The initialized data segment is read-only. */
671 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
672 bcopy (type
, p
, sizeof *p
);
673 p
->next
= image_types
;
678 CACHE_IMAGE_TYPE(*type
->type
, success
);
683 /* Look up image type SYMBOL, and return a pointer to its image_type
684 structure. Value is null if SYMBOL is not a known image type. */
686 static INLINE
struct image_type
*
687 lookup_image_type (symbol
)
690 struct image_type
*type
;
692 for (type
= image_types
; type
; type
= type
->next
)
693 if (EQ (symbol
, *type
->type
))
700 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
701 valid image specification is a list whose car is the symbol
702 `image', and whose rest is a property list. The property list must
703 contain a value for key `:type'. That value must be the name of a
704 supported image type. The rest of the property list depends on the
708 valid_image_p (object
)
717 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
718 if (EQ (XCAR (tem
), QCtype
))
721 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
723 struct image_type
*type
;
724 type
= lookup_image_type (XCAR (tem
));
726 valid_p
= type
->valid_p (object
);
737 /* Log error message with format string FORMAT and argument ARG.
738 Signaling an error, e.g. when an image cannot be loaded, is not a
739 good idea because this would interrupt redisplay, and the error
740 message display would lead to another redisplay. This function
741 therefore simply displays a message. */
744 image_error (format
, arg1
, arg2
)
746 Lisp_Object arg1
, arg2
;
748 add_to_log (format
, arg1
, arg2
);
753 /***********************************************************************
755 ***********************************************************************/
757 enum image_value_type
759 IMAGE_DONT_CHECK_VALUE_TYPE
,
761 IMAGE_STRING_OR_NIL_VALUE
,
763 IMAGE_POSITIVE_INTEGER_VALUE
,
764 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
765 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
768 IMAGE_FUNCTION_VALUE
,
773 /* Structure used when parsing image specifications. */
777 /* Name of keyword. */
780 /* The type of value allowed. */
781 enum image_value_type type
;
783 /* Non-zero means key must be present. */
786 /* Used to recognize duplicate keywords in a property list. */
789 /* The value that was found. */
794 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
796 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
799 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
800 has the format (image KEYWORD VALUE ...). One of the keyword/
801 value pairs must be `:type TYPE'. KEYWORDS is a vector of
802 image_keywords structures of size NKEYWORDS describing other
803 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
806 parse_image_spec (spec
, keywords
, nkeywords
, type
)
808 struct image_keyword
*keywords
;
819 while (CONSP (plist
))
821 Lisp_Object key
, value
;
823 /* First element of a pair must be a symbol. */
825 plist
= XCDR (plist
);
829 /* There must follow a value. */
832 value
= XCAR (plist
);
833 plist
= XCDR (plist
);
835 /* Find key in KEYWORDS. Error if not found. */
836 for (i
= 0; i
< nkeywords
; ++i
)
837 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
843 /* Record that we recognized the keyword. If a keywords
844 was found more than once, it's an error. */
845 keywords
[i
].value
= value
;
848 if (keywords
[i
].count
> 1)
851 /* Check type of value against allowed type. */
852 switch (keywords
[i
].type
)
854 case IMAGE_STRING_VALUE
:
855 if (!STRINGP (value
))
859 case IMAGE_STRING_OR_NIL_VALUE
:
860 if (!STRINGP (value
) && !NILP (value
))
864 case IMAGE_SYMBOL_VALUE
:
865 if (!SYMBOLP (value
))
869 case IMAGE_POSITIVE_INTEGER_VALUE
:
870 if (!INTEGERP (value
) || XINT (value
) <= 0)
874 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
875 if (INTEGERP (value
) && XINT (value
) >= 0)
878 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
879 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
883 case IMAGE_ASCENT_VALUE
:
884 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
886 else if (INTEGERP (value
)
888 && XINT (value
) <= 100)
892 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
893 if (!INTEGERP (value
) || XINT (value
) < 0)
897 case IMAGE_DONT_CHECK_VALUE_TYPE
:
900 case IMAGE_FUNCTION_VALUE
:
901 value
= indirect_function (value
);
904 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
908 case IMAGE_NUMBER_VALUE
:
909 if (!INTEGERP (value
) && !FLOATP (value
))
913 case IMAGE_INTEGER_VALUE
:
914 if (!INTEGERP (value
))
918 case IMAGE_BOOL_VALUE
:
919 if (!NILP (value
) && !EQ (value
, Qt
))
928 if (EQ (key
, QCtype
) && !EQ (type
, value
))
932 /* Check that all mandatory fields are present. */
933 for (i
= 0; i
< nkeywords
; ++i
)
934 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
941 /* Return the value of KEY in image specification SPEC. Value is nil
942 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
943 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
946 image_spec_value (spec
, key
, found
)
947 Lisp_Object spec
, key
;
952 xassert (valid_image_p (spec
));
954 for (tail
= XCDR (spec
);
955 CONSP (tail
) && CONSP (XCDR (tail
));
956 tail
= XCDR (XCDR (tail
)))
958 if (EQ (XCAR (tail
), key
))
962 return XCAR (XCDR (tail
));
972 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
973 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
974 PIXELS non-nil means return the size in pixels, otherwise return the
975 size in canonical character units.
976 FRAME is the frame on which the image will be displayed. FRAME nil
977 or omitted means use the selected frame. */)
978 (spec
, pixels
, frame
)
979 Lisp_Object spec
, pixels
, frame
;
984 if (valid_image_p (spec
))
986 struct frame
*f
= check_x_frame (frame
);
987 int id
= lookup_image (f
, spec
);
988 struct image
*img
= IMAGE_FROM_ID (f
, id
);
989 int width
= img
->width
+ 2 * img
->hmargin
;
990 int height
= img
->height
+ 2 * img
->vmargin
;
993 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
994 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
996 size
= Fcons (make_number (width
), make_number (height
));
999 error ("Invalid image specification");
1005 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1006 doc
: /* Return t if image SPEC has a mask bitmap.
1007 FRAME is the frame on which the image will be displayed. FRAME nil
1008 or omitted means use the selected frame. */)
1010 Lisp_Object spec
, frame
;
1015 if (valid_image_p (spec
))
1017 struct frame
*f
= check_x_frame (frame
);
1018 int id
= lookup_image (f
, spec
);
1019 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1024 error ("Invalid image specification");
1030 /***********************************************************************
1031 Image type independent image structures
1032 ***********************************************************************/
1034 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1035 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1038 /* Allocate and return a new image structure for image specification
1039 SPEC. SPEC has a hash value of HASH. */
1041 static struct image
*
1042 make_image (spec
, hash
)
1046 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1048 xassert (valid_image_p (spec
));
1049 bzero (img
, sizeof *img
);
1050 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1051 xassert (img
->type
!= NULL
);
1053 img
->data
.lisp_val
= Qnil
;
1054 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1060 /* Free image IMG which was used on frame F, including its resources. */
1069 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1071 /* Remove IMG from the hash table of its cache. */
1073 img
->prev
->next
= img
->next
;
1075 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1078 img
->next
->prev
= img
->prev
;
1080 c
->images
[img
->id
] = NULL
;
1082 /* Free resources, then free IMG. */
1083 img
->type
->free (f
, img
);
1089 /* Prepare image IMG for display on frame F. Must be called before
1090 drawing an image. */
1093 prepare_image_for_display (f
, img
)
1099 /* We're about to display IMG, so set its timestamp to `now'. */
1101 img
->timestamp
= EMACS_SECS (t
);
1103 /* If IMG doesn't have a pixmap yet, load it now, using the image
1104 type dependent loader function. */
1105 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1106 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1110 /* Value is the number of pixels for the ascent of image IMG when
1111 drawn in face FACE. */
1114 image_ascent (img
, face
, slice
)
1117 struct glyph_slice
*slice
;
1122 if (slice
->height
== img
->height
)
1123 height
= img
->height
+ img
->vmargin
;
1124 else if (slice
->y
== 0)
1125 height
= slice
->height
+ img
->vmargin
;
1127 height
= slice
->height
;
1129 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1134 /* W32 specific version. Why?. ++kfs */
1135 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1136 - FONT_BASE(face
->font
)) / 2;
1138 /* This expression is arranged so that if the image can't be
1139 exactly centered, it will be moved slightly up. This is
1140 because a typical font is `top-heavy' (due to the presence
1141 uppercase letters), so the image placement should err towards
1142 being top-heavy too. It also just generally looks better. */
1143 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1144 #endif /* HAVE_NTGUI */
1147 ascent
= height
/ 2;
1150 ascent
= (int) (height
* img
->ascent
/ 100.0);
1156 /* Image background colors. */
1158 /* Find the "best" corner color of a bitmap.
1159 On W32, XIMG is assumed to a device context with the bitmap selected. */
1161 static RGB_PIXEL_COLOR
1162 four_corners_best (ximg
, width
, height
)
1163 XImagePtr_or_DC ximg
;
1164 unsigned long width
, height
;
1166 RGB_PIXEL_COLOR corners
[4], best
;
1169 /* Get the colors at the corners of ximg. */
1170 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1171 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1172 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1173 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1175 /* Choose the most frequently found color as background. */
1176 for (i
= best_count
= 0; i
< 4; ++i
)
1180 for (j
= n
= 0; j
< 4; ++j
)
1181 if (corners
[i
] == corners
[j
])
1185 best
= corners
[i
], best_count
= n
;
1191 /* Portability macros */
1195 #define Destroy_Image(img_dc, prev) \
1196 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1198 #define Free_Pixmap(display, pixmap) \
1199 DeleteObject (pixmap)
1203 #define Destroy_Image(ximg, dummy) \
1204 XDestroyImage (ximg)
1206 #define Free_Pixmap(display, pixmap) \
1207 XFreePixmap (display, pixmap)
1209 #endif /* HAVE_NTGUI */
1212 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1213 it is guessed heuristically. If non-zero, XIMG is an existing
1214 XImage object (or device context with the image selected on W32) to
1215 use for the heuristic. */
1218 image_background (img
, f
, ximg
)
1221 XImagePtr_or_DC ximg
;
1223 if (! img
->background_valid
)
1224 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1226 int free_ximg
= !ximg
;
1229 #endif /* HAVE_NTGUI */
1234 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1235 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1237 HDC frame_dc
= get_frame_dc (f
);
1238 ximg
= CreateCompatibleDC (frame_dc
);
1239 release_frame_dc (f
, frame_dc
);
1240 prev
= SelectObject (ximg
, img
->pixmap
);
1241 #endif /* !HAVE_NTGUI */
1244 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1247 Destroy_Image (ximg
, prev
);
1249 img
->background_valid
= 1;
1252 return img
->background
;
1255 /* Return the `background_transparent' field of IMG. If IMG doesn't
1256 have one yet, it is guessed heuristically. If non-zero, MASK is an
1257 existing XImage object to use for the heuristic. */
1260 image_background_transparent (img
, f
, mask
)
1263 XImagePtr_or_DC mask
;
1265 if (! img
->background_transparent_valid
)
1266 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1270 int free_mask
= !mask
;
1273 #endif /* HAVE_NTGUI */
1278 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1279 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1281 HDC frame_dc
= get_frame_dc (f
);
1282 mask
= CreateCompatibleDC (frame_dc
);
1283 release_frame_dc (f
, frame_dc
);
1284 prev
= SelectObject (mask
, img
->mask
);
1285 #endif /* HAVE_NTGUI */
1288 img
->background_transparent
1289 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN (f
));
1292 Destroy_Image (mask
, prev
);
1295 img
->background_transparent
= 0;
1297 img
->background_transparent_valid
= 1;
1300 return img
->background_transparent
;
1304 /***********************************************************************
1305 Helper functions for X image types
1306 ***********************************************************************/
1308 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1310 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1311 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1313 Lisp_Object color_name
,
1314 unsigned long dflt
));
1317 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1318 free the pixmap if any. MASK_P non-zero means clear the mask
1319 pixmap if any. COLORS_P non-zero means free colors allocated for
1320 the image, if any. */
1323 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1326 int pixmap_p
, mask_p
, colors_p
;
1328 if (pixmap_p
&& img
->pixmap
)
1330 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1331 img
->pixmap
= NO_PIXMAP
;
1332 img
->background_valid
= 0;
1335 if (mask_p
&& img
->mask
)
1337 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1338 img
->mask
= NO_PIXMAP
;
1339 img
->background_transparent_valid
= 0;
1342 if (colors_p
&& img
->ncolors
)
1344 /* MAC_TODO: color table support. */
1345 /* W32_TODO: color table support. */
1346 #ifdef HAVE_X_WINDOWS
1347 x_free_colors (f
, img
->colors
, img
->ncolors
);
1348 #endif /* HAVE_X_WINDOWS */
1349 xfree (img
->colors
);
1355 /* Free X resources of image IMG which is used on frame F. */
1358 x_clear_image (f
, img
)
1363 x_clear_image_1 (f
, img
, 1, 1, 1);
1368 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1369 cannot be allocated, use DFLT. Add a newly allocated color to
1370 IMG->colors, so that it can be freed again. Value is the pixel
1373 static unsigned long
1374 x_alloc_image_color (f
, img
, color_name
, dflt
)
1377 Lisp_Object color_name
;
1381 unsigned long result
;
1383 xassert (STRINGP (color_name
));
1385 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1387 /* This isn't called frequently so we get away with simply
1388 reallocating the color vector to the needed size, here. */
1391 (unsigned long *) xrealloc (img
->colors
,
1392 img
->ncolors
* sizeof *img
->colors
);
1393 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1394 result
= color
.pixel
;
1404 /***********************************************************************
1406 ***********************************************************************/
1408 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1409 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1411 /* Return a new, initialized image cache that is allocated from the
1412 heap. Call free_image_cache to free an image cache. */
1414 struct image_cache
*
1417 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1420 bzero (c
, sizeof *c
);
1422 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1423 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1424 c
->buckets
= (struct image
**) xmalloc (size
);
1425 bzero (c
->buckets
, size
);
1430 /* Free image cache of frame F. Be aware that X frames share images
1434 free_image_cache (f
)
1437 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1442 /* Cache should not be referenced by any frame when freed. */
1443 xassert (c
->refcount
== 0);
1445 for (i
= 0; i
< c
->used
; ++i
)
1446 free_image (f
, c
->images
[i
]);
1450 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1455 /* Clear image cache of frame F. FORCE_P non-zero means free all
1456 images. FORCE_P zero means clear only images that haven't been
1457 displayed for some time. Should be called from time to time to
1458 reduce the number of loaded images. If image-eviction-seconds is
1459 non-nil, this frees images in the cache which weren't displayed for
1460 at least that many seconds. */
1463 clear_image_cache (f
, force_p
)
1467 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1469 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1476 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1478 /* Block input so that we won't be interrupted by a SIGIO
1479 while being in an inconsistent state. */
1482 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1484 struct image
*img
= c
->images
[i
];
1486 && (force_p
|| img
->timestamp
< old
))
1488 free_image (f
, img
);
1493 /* We may be clearing the image cache because, for example,
1494 Emacs was iconified for a longer period of time. In that
1495 case, current matrices may still contain references to
1496 images freed above. So, clear these matrices. */
1499 Lisp_Object tail
, frame
;
1501 FOR_EACH_FRAME (tail
, frame
)
1503 struct frame
*f
= XFRAME (frame
);
1504 if (FRAME_WINDOW_P (f
)
1505 && FRAME_X_IMAGE_CACHE (f
) == c
)
1506 clear_current_matrices (f
);
1509 ++windows_or_buffers_changed
;
1517 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1519 doc
: /* Clear the image cache of FRAME.
1520 FRAME nil or omitted means use the selected frame.
1521 FRAME t means clear the image caches of all frames. */)
1529 FOR_EACH_FRAME (tail
, frame
)
1530 if (FRAME_WINDOW_P (XFRAME (frame
)))
1531 clear_image_cache (XFRAME (frame
), 1);
1534 clear_image_cache (check_x_frame (frame
), 1);
1540 /* Compute masks and transform image IMG on frame F, as specified
1541 by the image's specification, */
1544 postprocess_image (f
, img
)
1548 /* Manipulation of the image's mask. */
1551 Lisp_Object conversion
, spec
;
1556 /* `:heuristic-mask t'
1558 means build a mask heuristically.
1559 `:heuristic-mask (R G B)'
1560 `:mask (heuristic (R G B))'
1561 means build a mask from color (R G B) in the
1564 means remove a mask, if any. */
1566 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1568 x_build_heuristic_mask (f
, img
, mask
);
1573 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1575 if (EQ (mask
, Qheuristic
))
1576 x_build_heuristic_mask (f
, img
, Qt
);
1577 else if (CONSP (mask
)
1578 && EQ (XCAR (mask
), Qheuristic
))
1580 if (CONSP (XCDR (mask
)))
1581 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1583 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1585 else if (NILP (mask
) && found_p
&& img
->mask
)
1587 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1588 img
->mask
= NO_PIXMAP
;
1593 /* Should we apply an image transformation algorithm? */
1594 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1595 if (EQ (conversion
, Qdisabled
))
1596 x_disable_image (f
, img
);
1597 else if (EQ (conversion
, Qlaplace
))
1599 else if (EQ (conversion
, Qemboss
))
1601 else if (CONSP (conversion
)
1602 && EQ (XCAR (conversion
), Qedge_detection
))
1605 tem
= XCDR (conversion
);
1607 x_edge_detection (f
, img
,
1608 Fplist_get (tem
, QCmatrix
),
1609 Fplist_get (tem
, QCcolor_adjustment
));
1615 /* Return the id of image with Lisp specification SPEC on frame F.
1616 SPEC must be a valid Lisp image specification (see valid_image_p). */
1619 lookup_image (f
, spec
)
1623 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1625 /* Work around a problem with MinGW builds of graphics libraries
1626 not honoring calling conventions. */
1632 struct gcpro gcpro1
;
1635 /* F must be a window-system frame, and SPEC must be a valid image
1637 xassert (FRAME_WINDOW_P (f
));
1638 xassert (valid_image_p (spec
));
1642 /* Look up SPEC in the hash table of the image cache. */
1643 hash
= sxhash (spec
, 0);
1644 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1646 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1647 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1650 /* If not found, create a new image and cache it. */
1653 extern Lisp_Object Qpostscript
;
1656 img
= make_image (spec
, hash
);
1657 cache_image (f
, img
);
1658 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1660 /* If we can't load the image, and we don't have a width and
1661 height, use some arbitrary width and height so that we can
1662 draw a rectangle for it. */
1663 if (img
->load_failed_p
)
1667 value
= image_spec_value (spec
, QCwidth
, NULL
);
1668 img
->width
= (INTEGERP (value
)
1669 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1670 value
= image_spec_value (spec
, QCheight
, NULL
);
1671 img
->height
= (INTEGERP (value
)
1672 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1676 /* Handle image type independent image attributes
1677 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1678 `:background COLOR'. */
1679 Lisp_Object ascent
, margin
, relief
, bg
;
1681 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1682 if (INTEGERP (ascent
))
1683 img
->ascent
= XFASTINT (ascent
);
1684 else if (EQ (ascent
, Qcenter
))
1685 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1687 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1688 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1689 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1690 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1691 && INTEGERP (XCDR (margin
)))
1693 if (XINT (XCAR (margin
)) > 0)
1694 img
->hmargin
= XFASTINT (XCAR (margin
));
1695 if (XINT (XCDR (margin
)) > 0)
1696 img
->vmargin
= XFASTINT (XCDR (margin
));
1699 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1700 if (INTEGERP (relief
))
1702 img
->relief
= XINT (relief
);
1703 img
->hmargin
+= abs (img
->relief
);
1704 img
->vmargin
+= abs (img
->relief
);
1707 if (! img
->background_valid
)
1709 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1713 = x_alloc_image_color (f
, img
, bg
,
1714 FRAME_BACKGROUND_PIXEL (f
));
1715 img
->background_valid
= 1;
1719 /* Do image transformations and compute masks, unless we
1720 don't have the image yet. */
1721 if (!EQ (*img
->type
->type
, Qpostscript
))
1722 postprocess_image (f
, img
);
1728 /* We're using IMG, so set its timestamp to `now'. */
1729 EMACS_GET_TIME (now
);
1730 img
->timestamp
= EMACS_SECS (now
);
1734 /* Value is the image id. */
1739 /* Cache image IMG in the image cache of frame F. */
1742 cache_image (f
, img
)
1746 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1749 /* Find a free slot in c->images. */
1750 for (i
= 0; i
< c
->used
; ++i
)
1751 if (c
->images
[i
] == NULL
)
1754 /* If no free slot found, maybe enlarge c->images. */
1755 if (i
== c
->used
&& c
->used
== c
->size
)
1758 c
->images
= (struct image
**) xrealloc (c
->images
,
1759 c
->size
* sizeof *c
->images
);
1762 /* Add IMG to c->images, and assign IMG an id. */
1768 /* Add IMG to the cache's hash table. */
1769 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1770 img
->next
= c
->buckets
[i
];
1772 img
->next
->prev
= img
;
1774 c
->buckets
[i
] = img
;
1778 /* Call FN on every image in the image cache of frame F. Used to mark
1779 Lisp Objects in the image cache. */
1782 forall_images_in_image_cache (f
, fn
)
1784 void (*fn
) P_ ((struct image
*img
));
1786 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1788 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1792 for (i
= 0; i
< c
->used
; ++i
)
1801 /***********************************************************************
1802 X / MAC / W32 support code
1803 ***********************************************************************/
1807 /* Macro for defining functions that will be loaded from image DLLs. */
1808 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1810 /* Macro for loading those image functions from the library. */
1811 #define LOAD_IMGLIB_FN(lib,func) { \
1812 fn_##func = (void *) GetProcAddress (lib, #func); \
1813 if (!fn_##func) return 0; \
1816 /* Load a DLL implementing an image type.
1817 The `image-library-alist' variable associates a symbol,
1818 identifying an image type, to a list of possible filenames.
1819 The function returns NULL if no library could be loaded for
1820 the given image type, or if the library was previously loaded;
1821 else the handle of the DLL. */
1823 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
1825 HMODULE library
= NULL
;
1827 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
1829 Lisp_Object dlls
= Fassq (type
, libraries
);
1832 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
1834 CHECK_STRING_CAR (dlls
);
1835 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
1843 #endif /* HAVE_NTGUI */
1845 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
1846 XImagePtr
*, Pixmap
*));
1847 static void x_destroy_x_image
P_ ((XImagePtr
));
1848 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
1851 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1852 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1853 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1854 via xmalloc. Print error messages via image_error if an error
1855 occurs. Value is non-zero if successful.
1857 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1858 should indicate the bit depth of the image. */
1861 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
1863 int width
, height
, depth
;
1867 #ifdef HAVE_X_WINDOWS
1868 Display
*display
= FRAME_X_DISPLAY (f
);
1869 Window window
= FRAME_X_WINDOW (f
);
1870 Screen
*screen
= FRAME_X_SCREEN (f
);
1872 xassert (interrupt_input_blocked
);
1875 depth
= DefaultDepthOfScreen (screen
);
1876 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
1877 depth
, ZPixmap
, 0, NULL
, width
, height
,
1878 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
1881 image_error ("Unable to allocate X image", Qnil
, Qnil
);
1885 /* Allocate image raster. */
1886 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
1888 /* Allocate a pixmap of the same size. */
1889 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1890 if (*pixmap
== NO_PIXMAP
)
1892 x_destroy_x_image (*ximg
);
1894 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1899 #endif /* HAVE_X_WINDOWS */
1903 BITMAPINFOHEADER
*header
;
1905 int scanline_width_bits
;
1907 int palette_colors
= 0;
1912 if (depth
!= 1 && depth
!= 4 && depth
!= 8
1913 && depth
!= 16 && depth
!= 24 && depth
!= 32)
1915 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
1919 scanline_width_bits
= width
* depth
;
1920 remainder
= scanline_width_bits
% 32;
1923 scanline_width_bits
+= 32 - remainder
;
1925 /* Bitmaps with a depth less than 16 need a palette. */
1926 /* BITMAPINFO structure already contains the first RGBQUAD. */
1928 palette_colors
= 1 << depth
- 1;
1930 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
1933 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
1937 header
= &((*ximg
)->info
.bmiHeader
);
1938 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
1939 header
->biSize
= sizeof (*header
);
1940 header
->biWidth
= width
;
1941 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
1942 header
->biPlanes
= 1;
1943 header
->biBitCount
= depth
;
1944 header
->biCompression
= BI_RGB
;
1945 header
->biClrUsed
= palette_colors
;
1947 /* TODO: fill in palette. */
1950 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
1951 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
1952 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
1953 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
1954 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
1955 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
1956 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
1957 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
1960 hdc
= get_frame_dc (f
);
1962 /* Create a DIBSection and raster array for the bitmap,
1963 and store its handle in *pixmap. */
1964 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
1965 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
1966 &((*ximg
)->data
), NULL
, 0);
1968 /* Realize display palette and garbage all frames. */
1969 release_frame_dc (f
, hdc
);
1971 if (*pixmap
== NULL
)
1973 DWORD err
= GetLastError();
1974 Lisp_Object errcode
;
1975 /* All system errors are < 10000, so the following is safe. */
1976 XSETINT (errcode
, (int) err
);
1977 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
1978 x_destroy_x_image (*ximg
);
1984 #endif /* HAVE_NTGUI */
1987 Display
*display
= FRAME_X_DISPLAY (f
);
1988 Window window
= FRAME_X_WINDOW (f
);
1990 xassert (interrupt_input_blocked
);
1992 /* Allocate a pixmap of the same size. */
1993 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1994 if (*pixmap
== NO_PIXMAP
)
1996 x_destroy_x_image (*ximg
);
1998 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2002 LockPixels (GetGWorldPixMap (*pixmap
));
2010 /* Destroy XImage XIMG. Free XIMG->data. */
2013 x_destroy_x_image (ximg
)
2016 xassert (interrupt_input_blocked
);
2019 #ifdef HAVE_X_WINDOWS
2022 XDestroyImage (ximg
);
2023 #endif /* HAVE_X_WINDOWS */
2025 /* Data will be freed by DestroyObject. */
2028 #endif /* HAVE_NTGUI */
2030 XDestroyImage (ximg
);
2036 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2037 are width and height of both the image and pixmap. */
2040 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2046 #ifdef HAVE_X_WINDOWS
2049 xassert (interrupt_input_blocked
);
2050 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2051 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2052 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2053 #endif /* HAVE_X_WINDOWS */
2056 #if 0 /* I don't think this is necessary looking at where it is used. */
2057 HDC hdc
= get_frame_dc (f
);
2058 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2059 release_frame_dc (f
, hdc
);
2061 #endif /* HAVE_NTGUI */
2064 xassert (ximg
== pixmap
);
2069 /***********************************************************************
2071 ***********************************************************************/
2073 static unsigned char *slurp_file
P_ ((char *, int *));
2076 /* Find image file FILE. Look in data-directory, then
2077 x-bitmap-file-path. Value is the full name of the file found, or
2078 nil if not found. */
2081 x_find_image_file (file
)
2084 Lisp_Object file_found
, search_path
;
2085 struct gcpro gcpro1
, gcpro2
;
2089 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2090 GCPRO2 (file_found
, search_path
);
2092 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2093 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2105 /* Read FILE into memory. Value is a pointer to a buffer allocated
2106 with xmalloc holding FILE's contents. Value is null if an error
2107 occurred. *SIZE is set to the size of the file. */
2109 static unsigned char *
2110 slurp_file (file
, size
)
2115 unsigned char *buf
= NULL
;
2118 if (stat (file
, &st
) == 0
2119 && (fp
= fopen (file
, "rb")) != NULL
2120 && (buf
= (char *) xmalloc (st
.st_size
),
2121 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2144 /***********************************************************************
2145 MAC Image Load Functions
2146 ***********************************************************************/
2148 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2151 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2155 find_image_fsspec (specified_file
, file
, fss
)
2156 Lisp_Object specified_file
, *file
;
2159 #if TARGET_API_MAC_CARBON
2162 Str255 mac_pathname
;
2166 *file
= x_find_image_file (specified_file
);
2167 if (!STRINGP (*file
))
2168 return fnfErr
; /* file or directory not found;
2169 incomplete pathname */
2170 /* Try to open the image file. */
2171 #if TARGET_API_MAC_CARBON
2172 err
= FSPathMakeRef (SDATA (*file
), &fsr
, NULL
);
2174 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
2176 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
2178 c2pstr (mac_pathname
);
2179 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
2185 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2193 GraphicsImportComponent gi
;
2196 short draw_all_pixels
;
2197 Lisp_Object specified_bg
;
2202 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2206 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2211 /* read from file system spec */
2212 err
= GraphicsImportSetDataFile (gi
, fss
);
2215 image_error ("Cannot set fsspec to graphics importer for '%s'",
2222 /* read from data handle */
2223 err
= GraphicsImportSetDataHandle (gi
, dh
);
2226 image_error ("Cannot set data handle to graphics importer for `%s'",
2231 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
2234 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2237 width
= img
->width
= rect
.right
- rect
.left
;
2238 height
= img
->height
= rect
.bottom
- rect
.top
;
2239 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2241 /* Don't check the error code here. It may have an undocumented
2245 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2249 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2251 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2252 if (!STRINGP (specified_bg
) ||
2253 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2255 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2256 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2257 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2258 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2262 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2264 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2269 GetGWorld (&old_port
, &old_gdh
);
2270 SetGWorld (ximg
, NULL
);
2271 bg_color
.red
= color
.red
;
2272 bg_color
.green
= color
.green
;
2273 bg_color
.blue
= color
.blue
;
2274 RGBBackColor (&bg_color
);
2275 #if TARGET_API_MAC_CARBON
2276 GetPortBounds (ximg
, &rect
);
2279 EraseRect (&(ximg
->portRect
));
2281 SetGWorld (old_port
, old_gdh
);
2283 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2284 GraphicsImportDraw (gi
);
2285 CloseComponent (gi
);
2287 /* Maybe fill in the background field while we have ximg handy. */
2288 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2289 IMAGE_BACKGROUND (img
, f
, ximg
);
2291 /* Put the image into the pixmap. */
2292 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2293 x_destroy_x_image (ximg
);
2297 CloseComponent (gi
);
2302 /* Load an image using the QuickTime Graphics Importer.
2303 Note: The alpha channel does not work for PNG images. */
2305 image_load_quicktime (f
, img
, type
)
2310 Lisp_Object specified_file
;
2311 Lisp_Object specified_data
;
2314 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2315 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2317 if (NILP (specified_data
))
2319 /* Read from a file */
2323 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2327 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2329 image_error ("Cannot open `%s'", file
, Qnil
);
2332 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2336 /* Memory source! */
2340 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2343 image_error ("Cannot allocate data handle for `%s'",
2347 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2355 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2356 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2357 So don't use this function directly but determine at runtime
2358 whether it exists. */
2359 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2360 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2361 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2365 init_image_func_pointer ()
2367 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2369 MyCGImageCreateWithPNGDataProvider
2370 = (CGImageCreateWithPNGDataProviderProcType
)
2371 NSAddressOfSymbol (NSLookupAndBindSymbol
2372 ("_CGImageCreateWithPNGDataProvider"));
2375 MyCGImageCreateWithPNGDataProvider
= NULL
;
2380 image_load_quartz2d (f
, img
, png_p
)
2385 Lisp_Object file
, specified_file
;
2386 Lisp_Object specified_data
, specified_bg
;
2387 struct gcpro gcpro1
;
2388 CGDataProviderRef source
;
2392 XImagePtr ximg
= NULL
;
2393 CGContextRef context
;
2396 /* Open the file. */
2397 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2398 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2403 if (NILP (specified_data
))
2408 file
= x_find_image_file (specified_file
);
2409 if (!STRINGP (file
))
2411 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2415 path
= CFStringCreateWithCString (NULL
, SDATA (file
),
2416 kCFStringEncodingUTF8
);
2417 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2418 kCFURLPOSIXPathStyle
, 0);
2420 source
= CGDataProviderCreateWithURL (url
);
2424 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2425 SBYTES (specified_data
), NULL
);
2428 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2429 kCGRenderingIntentDefault
);
2431 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2432 kCGRenderingIntentDefault
);
2434 CGDataProviderRelease (source
);
2438 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2444 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2445 if (!STRINGP (specified_bg
) ||
2446 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2448 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2449 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2450 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2451 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2454 width
= img
->width
= CGImageGetWidth (image
);
2455 height
= img
->height
= CGImageGetHeight (image
);
2456 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2458 CGImageRelease (image
);
2462 rectangle
= CGRectMake (0, 0, width
, height
);
2463 QDBeginCGContext (ximg
, &context
);
2466 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2467 color
.green
/ 65535.0,
2468 color
.blue
/ 65535.0, 1.0);
2469 CGContextFillRect (context
, rectangle
);
2471 CGContextDrawImage (context
, rectangle
, image
);
2472 QDEndCGContext (ximg
, &context
);
2473 CGImageRelease (image
);
2475 /* Maybe fill in the background field while we have ximg handy. */
2476 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2477 IMAGE_BACKGROUND (img
, f
, ximg
);
2479 /* Put the image into the pixmap. */
2480 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2481 x_destroy_x_image (ximg
);
2490 /***********************************************************************
2492 ***********************************************************************/
2494 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2495 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2496 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2497 unsigned char *, unsigned char *));
2498 static int xbm_image_p
P_ ((Lisp_Object object
));
2499 static int xbm_read_bitmap_data
P_ ((unsigned char *, unsigned char *,
2500 int *, int *, unsigned char **));
2501 static int xbm_file_p
P_ ((Lisp_Object
));
2504 /* Indices of image specification fields in xbm_format, below. */
2506 enum xbm_keyword_index
2524 /* Vector of image_keyword structures describing the format
2525 of valid XBM image specifications. */
2527 static struct image_keyword xbm_format
[XBM_LAST
] =
2529 {":type", IMAGE_SYMBOL_VALUE
, 1},
2530 {":file", IMAGE_STRING_VALUE
, 0},
2531 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2532 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2533 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2534 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2535 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2536 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2537 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2538 {":relief", IMAGE_INTEGER_VALUE
, 0},
2539 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2540 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2541 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2544 /* Structure describing the image type XBM. */
2546 static struct image_type xbm_type
=
2555 /* Tokens returned from xbm_scan. */
2564 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2565 A valid specification is a list starting with the symbol `image'
2566 The rest of the list is a property list which must contain an
2569 If the specification specifies a file to load, it must contain
2570 an entry `:file FILENAME' where FILENAME is a string.
2572 If the specification is for a bitmap loaded from memory it must
2573 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2574 WIDTH and HEIGHT are integers > 0. DATA may be:
2576 1. a string large enough to hold the bitmap data, i.e. it must
2577 have a size >= (WIDTH + 7) / 8 * HEIGHT
2579 2. a bool-vector of size >= WIDTH * HEIGHT
2581 3. a vector of strings or bool-vectors, one for each line of the
2584 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2585 may not be specified in this case because they are defined in the
2588 Both the file and data forms may contain the additional entries
2589 `:background COLOR' and `:foreground COLOR'. If not present,
2590 foreground and background of the frame on which the image is
2591 displayed is used. */
2594 xbm_image_p (object
)
2597 struct image_keyword kw
[XBM_LAST
];
2599 bcopy (xbm_format
, kw
, sizeof kw
);
2600 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2603 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2605 if (kw
[XBM_FILE
].count
)
2607 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2610 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2612 /* In-memory XBM file. */
2613 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2621 /* Entries for `:width', `:height' and `:data' must be present. */
2622 if (!kw
[XBM_WIDTH
].count
2623 || !kw
[XBM_HEIGHT
].count
2624 || !kw
[XBM_DATA
].count
)
2627 data
= kw
[XBM_DATA
].value
;
2628 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2629 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2631 /* Check type of data, and width and height against contents of
2637 /* Number of elements of the vector must be >= height. */
2638 if (XVECTOR (data
)->size
< height
)
2641 /* Each string or bool-vector in data must be large enough
2642 for one line of the image. */
2643 for (i
= 0; i
< height
; ++i
)
2645 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2650 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2653 else if (BOOL_VECTOR_P (elt
))
2655 if (XBOOL_VECTOR (elt
)->size
< width
)
2662 else if (STRINGP (data
))
2665 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2668 else if (BOOL_VECTOR_P (data
))
2670 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2681 /* Scan a bitmap file. FP is the stream to read from. Value is
2682 either an enumerator from enum xbm_token, or a character for a
2683 single-character token, or 0 at end of file. If scanning an
2684 identifier, store the lexeme of the identifier in SVAL. If
2685 scanning a number, store its value in *IVAL. */
2688 xbm_scan (s
, end
, sval
, ival
)
2689 unsigned char **s
, *end
;
2697 /* Skip white space. */
2698 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2703 else if (isdigit (c
))
2705 int value
= 0, digit
;
2707 if (c
== '0' && *s
< end
)
2710 if (c
== 'x' || c
== 'X')
2717 else if (c
>= 'a' && c
<= 'f')
2718 digit
= c
- 'a' + 10;
2719 else if (c
>= 'A' && c
<= 'F')
2720 digit
= c
- 'A' + 10;
2723 value
= 16 * value
+ digit
;
2726 else if (isdigit (c
))
2730 && (c
= *(*s
)++, isdigit (c
)))
2731 value
= 8 * value
+ c
- '0';
2738 && (c
= *(*s
)++, isdigit (c
)))
2739 value
= 10 * value
+ c
- '0';
2747 else if (isalpha (c
) || c
== '_')
2751 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2758 else if (c
== '/' && **s
== '*')
2760 /* C-style comment. */
2762 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2776 /* Create a Windows bitmap from X bitmap data. */
2778 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2780 static unsigned char swap_nibble
[16]
2781 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2782 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2783 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2784 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2786 unsigned char *bits
, *p
;
2789 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2790 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2791 bits
= (unsigned char *) alloca (height
* w2
);
2792 bzero (bits
, height
* w2
);
2793 for (i
= 0; i
< height
; i
++)
2796 for (j
= 0; j
< w1
; j
++)
2798 /* Bitswap XBM bytes to match how Windows does things. */
2799 unsigned char c
= *data
++;
2800 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2801 | (swap_nibble
[(c
>>4) & 0xf]));
2804 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2809 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
2812 COLORREF foreground
, background
;
2814 HDC hdc
, old_img_dc
, new_img_dc
;
2815 HGDIOBJ old_prev
, new_prev
;
2818 hdc
= get_frame_dc (f
);
2819 old_img_dc
= CreateCompatibleDC (hdc
);
2820 new_img_dc
= CreateCompatibleDC (hdc
);
2821 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2822 release_frame_dc (f
, hdc
);
2823 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2824 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2825 SetTextColor (new_img_dc
, foreground
);
2826 SetBkColor (new_img_dc
, background
);
2828 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2831 SelectObject (old_img_dc
, old_prev
);
2832 SelectObject (new_img_dc
, new_prev
);
2833 DeleteDC (old_img_dc
);
2834 DeleteDC (new_img_dc
);
2835 DeleteObject (img
->pixmap
);
2836 if (new_pixmap
== 0)
2837 fprintf (stderr
, "Failed to convert image to color.\n");
2839 img
->pixmap
= new_pixmap
;
2842 #define XBM_BIT_SHUFFLE(b) (~(b))
2846 #define XBM_BIT_SHUFFLE(b) (b)
2848 #endif /* HAVE_NTGUI */
2852 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
2856 RGB_PIXEL_COLOR fg
, bg
;
2857 int non_default_colors
;
2861 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2863 /* If colors were specified, transfer the bitmap to a color one. */
2864 if (non_default_colors
)
2865 convert_mono_to_color_image (f
, img
, fg
, bg
);
2868 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2871 img
->width
, img
->height
,
2873 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2874 #endif /* HAVE_NTGUI */
2879 /* Replacement for XReadBitmapFileData which isn't available under old
2880 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2881 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2882 the image. Return in *DATA the bitmap data allocated with xmalloc.
2883 Value is non-zero if successful. DATA null means just test if
2884 CONTENTS looks like an in-memory XBM file. */
2887 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
2888 unsigned char *contents
, *end
;
2889 int *width
, *height
;
2890 unsigned char **data
;
2892 unsigned char *s
= contents
;
2893 char buffer
[BUFSIZ
];
2896 int bytes_per_line
, i
, nbytes
;
2902 LA1 = xbm_scan (&s, end, buffer, &value)
2904 #define expect(TOKEN) \
2905 if (LA1 != (TOKEN)) \
2910 #define expect_ident(IDENT) \
2911 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2916 *width
= *height
= -1;
2919 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2921 /* Parse defines for width, height and hot-spots. */
2925 expect_ident ("define");
2926 expect (XBM_TK_IDENT
);
2928 if (LA1
== XBM_TK_NUMBER
);
2930 char *p
= strrchr (buffer
, '_');
2931 p
= p
? p
+ 1 : buffer
;
2932 if (strcmp (p
, "width") == 0)
2934 else if (strcmp (p
, "height") == 0)
2937 expect (XBM_TK_NUMBER
);
2940 if (*width
< 0 || *height
< 0)
2942 else if (data
== NULL
)
2945 /* Parse bits. Must start with `static'. */
2946 expect_ident ("static");
2947 if (LA1
== XBM_TK_IDENT
)
2949 if (strcmp (buffer
, "unsigned") == 0)
2952 expect_ident ("char");
2954 else if (strcmp (buffer
, "short") == 0)
2958 if (*width
% 16 && *width
% 16 < 9)
2961 else if (strcmp (buffer
, "char") == 0)
2969 expect (XBM_TK_IDENT
);
2975 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
2976 nbytes
= bytes_per_line
* *height
;
2977 p
= *data
= (char *) xmalloc (nbytes
);
2981 for (i
= 0; i
< nbytes
; i
+= 2)
2984 expect (XBM_TK_NUMBER
);
2986 *p
++ = XBM_BIT_SHUFFLE (val
);
2987 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
2988 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
2990 if (LA1
== ',' || LA1
== '}')
2998 for (i
= 0; i
< nbytes
; ++i
)
3001 expect (XBM_TK_NUMBER
);
3003 *p
++ = XBM_BIT_SHUFFLE (val
);
3005 if (LA1
== ',' || LA1
== '}')
3030 /* Load XBM image IMG which will be displayed on frame F from buffer
3031 CONTENTS. END is the end of the buffer. Value is non-zero if
3035 xbm_load_image (f
, img
, contents
, end
)
3038 unsigned char *contents
, *end
;
3041 unsigned char *data
;
3044 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
3047 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3048 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3049 int non_default_colors
= 0;
3052 xassert (img
->width
> 0 && img
->height
> 0);
3054 /* Get foreground and background colors, maybe allocate colors. */
3055 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3058 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3059 non_default_colors
= 1;
3061 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3064 background
= x_alloc_image_color (f
, img
, value
, background
);
3065 img
->background
= background
;
3066 img
->background_valid
= 1;
3067 non_default_colors
= 1;
3070 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3071 foreground
, background
,
3072 non_default_colors
);
3075 if (img
->pixmap
== NO_PIXMAP
)
3077 x_clear_image (f
, img
);
3078 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3084 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3090 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3097 return (STRINGP (data
)
3098 && xbm_read_bitmap_data (SDATA (data
),
3105 /* Fill image IMG which is used on frame F with pixmap data. Value is
3106 non-zero if successful. */
3114 Lisp_Object file_name
;
3116 xassert (xbm_image_p (img
->spec
));
3118 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3119 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3120 if (STRINGP (file_name
))
3123 unsigned char *contents
;
3125 struct gcpro gcpro1
;
3127 file
= x_find_image_file (file_name
);
3129 if (!STRINGP (file
))
3131 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3136 contents
= slurp_file (SDATA (file
), &size
);
3137 if (contents
== NULL
)
3139 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3144 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3149 struct image_keyword fmt
[XBM_LAST
];
3151 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3152 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3153 int non_default_colors
= 0;
3156 int in_memory_file_p
= 0;
3158 /* See if data looks like an in-memory XBM file. */
3159 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3160 in_memory_file_p
= xbm_file_p (data
);
3162 /* Parse the image specification. */
3163 bcopy (xbm_format
, fmt
, sizeof fmt
);
3164 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3167 /* Get specified width, and height. */
3168 if (!in_memory_file_p
)
3170 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3171 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3172 xassert (img
->width
> 0 && img
->height
> 0);
3175 /* Get foreground and background colors, maybe allocate colors. */
3176 if (fmt
[XBM_FOREGROUND
].count
3177 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3179 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3181 non_default_colors
= 1;
3184 if (fmt
[XBM_BACKGROUND
].count
3185 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3187 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3189 non_default_colors
= 1;
3192 if (in_memory_file_p
)
3193 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3202 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3204 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3205 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3207 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3209 bcopy (SDATA (line
), p
, nbytes
);
3211 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3214 else if (STRINGP (data
))
3215 bits
= SDATA (data
);
3217 bits
= XBOOL_VECTOR (data
)->data
;
3219 /* Create the pixmap. */
3221 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3222 foreground
, background
,
3223 non_default_colors
);
3228 image_error ("Unable to create pixmap for XBM image `%s'",
3230 x_clear_image (f
, img
);
3240 /***********************************************************************
3242 ***********************************************************************/
3244 #if defined (HAVE_XPM) || defined (MAC_OS)
3246 static int xpm_image_p
P_ ((Lisp_Object object
));
3247 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3248 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3250 #endif /* HAVE_XPM || MAC_OS */
3254 /* Indicate to xpm.h that we don't have Xlib. */
3256 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3257 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3258 #define XColor xpm_XColor
3259 #define XImage xpm_XImage
3260 #define Display xpm_Display
3261 #define PIXEL_ALREADY_TYPEDEFED
3262 #include "X11/xpm.h"
3267 #undef PIXEL_ALREADY_TYPEDEFED
3269 #include "X11/xpm.h"
3270 #endif /* HAVE_NTGUI */
3271 #endif /* HAVE_XPM */
3273 #if defined (HAVE_XPM) || defined (MAC_OS)
3274 /* The symbol `xpm' identifying XPM-format images. */
3278 /* Indices of image specification fields in xpm_format, below. */
3280 enum xpm_keyword_index
3296 /* Vector of image_keyword structures describing the format
3297 of valid XPM image specifications. */
3299 static struct image_keyword xpm_format
[XPM_LAST
] =
3301 {":type", IMAGE_SYMBOL_VALUE
, 1},
3302 {":file", IMAGE_STRING_VALUE
, 0},
3303 {":data", IMAGE_STRING_VALUE
, 0},
3304 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3305 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3306 {":relief", IMAGE_INTEGER_VALUE
, 0},
3307 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3308 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3309 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3310 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3311 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3314 /* Structure describing the image type XPM. */
3316 static struct image_type xpm_type
=
3325 #ifdef HAVE_X_WINDOWS
3327 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3328 functions for allocating image colors. Our own functions handle
3329 color allocation failures more gracefully than the ones on the XPM
3332 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3333 #define ALLOC_XPM_COLORS
3335 #endif /* HAVE_X_WINDOWS */
3337 #ifdef ALLOC_XPM_COLORS
3339 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3340 static void xpm_free_color_cache
P_ ((void));
3341 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3342 static int xpm_color_bucket
P_ ((char *));
3343 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3346 /* An entry in a hash table used to cache color definitions of named
3347 colors. This cache is necessary to speed up XPM image loading in
3348 case we do color allocations ourselves. Without it, we would need
3349 a call to XParseColor per pixel in the image. */
3351 struct xpm_cached_color
3353 /* Next in collision chain. */
3354 struct xpm_cached_color
*next
;
3356 /* Color definition (RGB and pixel color). */
3363 /* The hash table used for the color cache, and its bucket vector
3366 #define XPM_COLOR_CACHE_BUCKETS 1001
3367 struct xpm_cached_color
**xpm_color_cache
;
3369 /* Initialize the color cache. */
3372 xpm_init_color_cache (f
, attrs
)
3374 XpmAttributes
*attrs
;
3376 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3377 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3378 memset (xpm_color_cache
, 0, nbytes
);
3379 init_color_table ();
3381 if (attrs
->valuemask
& XpmColorSymbols
)
3386 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3387 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3388 attrs
->colorsymbols
[i
].value
, &color
))
3390 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3392 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3397 /* Free the color cache. */
3400 xpm_free_color_cache ()
3402 struct xpm_cached_color
*p
, *next
;
3405 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3406 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3412 xfree (xpm_color_cache
);
3413 xpm_color_cache
= NULL
;
3414 free_color_table ();
3417 /* Return the bucket index for color named COLOR_NAME in the color
3421 xpm_color_bucket (color_name
)
3427 for (s
= color_name
; *s
; ++s
)
3429 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3433 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3434 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3437 static struct xpm_cached_color
*
3438 xpm_cache_color (f
, color_name
, color
, bucket
)
3445 struct xpm_cached_color
*p
;
3448 bucket
= xpm_color_bucket (color_name
);
3450 nbytes
= sizeof *p
+ strlen (color_name
);
3451 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3452 strcpy (p
->name
, color_name
);
3454 p
->next
= xpm_color_cache
[bucket
];
3455 xpm_color_cache
[bucket
] = p
;
3459 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3460 return the cached definition in *COLOR. Otherwise, make a new
3461 entry in the cache and allocate the color. Value is zero if color
3462 allocation failed. */
3465 xpm_lookup_color (f
, color_name
, color
)
3470 struct xpm_cached_color
*p
;
3471 int h
= xpm_color_bucket (color_name
);
3473 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3474 if (strcmp (p
->name
, color_name
) == 0)
3479 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3482 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3484 p
= xpm_cache_color (f
, color_name
, color
, h
);
3486 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3487 with transparency, and it's useful. */
3488 else if (strcmp ("opaque", color_name
) == 0)
3490 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3491 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3492 p
= xpm_cache_color (f
, color_name
, color
, h
);
3499 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3500 CLOSURE is a pointer to the frame on which we allocate the
3501 color. Return in *COLOR the allocated color. Value is non-zero
3505 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3512 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3516 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3517 is a pointer to the frame on which we allocate the color. Value is
3518 non-zero if successful. */
3521 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3531 #endif /* ALLOC_XPM_COLORS */
3536 /* XPM library details. */
3538 DEF_IMGLIB_FN (XpmFreeAttributes
);
3539 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3540 DEF_IMGLIB_FN (XpmReadFileToImage
);
3541 DEF_IMGLIB_FN (XImageFree
);
3544 init_xpm_functions (Lisp_Object libraries
)
3548 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3551 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3552 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3553 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3554 LOAD_IMGLIB_FN (library
, XImageFree
);
3558 #endif /* HAVE_NTGUI */
3561 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3562 for XPM images. Such a list must consist of conses whose car and
3566 xpm_valid_color_symbols_p (color_symbols
)
3567 Lisp_Object color_symbols
;
3569 while (CONSP (color_symbols
))
3571 Lisp_Object sym
= XCAR (color_symbols
);
3573 || !STRINGP (XCAR (sym
))
3574 || !STRINGP (XCDR (sym
)))
3576 color_symbols
= XCDR (color_symbols
);
3579 return NILP (color_symbols
);
3583 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3586 xpm_image_p (object
)
3589 struct image_keyword fmt
[XPM_LAST
];
3590 bcopy (xpm_format
, fmt
, sizeof fmt
);
3591 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3592 /* Either `:file' or `:data' must be present. */
3593 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3594 /* Either no `:color-symbols' or it's a list of conses
3595 whose car and cdr are strings. */
3596 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3597 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3600 #endif /* HAVE_XPM || MAC_OS */
3602 /* Load image IMG which will be displayed on frame F. Value is
3603 non-zero if successful. */
3613 XpmAttributes attrs
;
3614 Lisp_Object specified_file
, color_symbols
;
3617 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3618 #endif /* HAVE_NTGUI */
3620 /* Configure the XPM lib. Use the visual of frame F. Allocate
3621 close colors. Return colors allocated. */
3622 bzero (&attrs
, sizeof attrs
);
3625 attrs
.visual
= FRAME_X_VISUAL (f
);
3626 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3627 attrs
.valuemask
|= XpmVisual
;
3628 attrs
.valuemask
|= XpmColormap
;
3629 #endif /* HAVE_NTGUI */
3631 #ifdef ALLOC_XPM_COLORS
3632 /* Allocate colors with our own functions which handle
3633 failing color allocation more gracefully. */
3634 attrs
.color_closure
= f
;
3635 attrs
.alloc_color
= xpm_alloc_color
;
3636 attrs
.free_colors
= xpm_free_colors
;
3637 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3638 #else /* not ALLOC_XPM_COLORS */
3639 /* Let the XPM lib allocate colors. */
3640 attrs
.valuemask
|= XpmReturnAllocPixels
;
3641 #ifdef XpmAllocCloseColors
3642 attrs
.alloc_close_colors
= 1;
3643 attrs
.valuemask
|= XpmAllocCloseColors
;
3644 #else /* not XpmAllocCloseColors */
3645 attrs
.closeness
= 600;
3646 attrs
.valuemask
|= XpmCloseness
;
3647 #endif /* not XpmAllocCloseColors */
3648 #endif /* ALLOC_XPM_COLORS */
3650 /* If image specification contains symbolic color definitions, add
3651 these to `attrs'. */
3652 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3653 if (CONSP (color_symbols
))
3656 XpmColorSymbol
*xpm_syms
;
3659 attrs
.valuemask
|= XpmColorSymbols
;
3661 /* Count number of symbols. */
3662 attrs
.numsymbols
= 0;
3663 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3666 /* Allocate an XpmColorSymbol array. */
3667 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3668 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3669 bzero (xpm_syms
, size
);
3670 attrs
.colorsymbols
= xpm_syms
;
3672 /* Fill the color symbol array. */
3673 for (tail
= color_symbols
, i
= 0;
3675 ++i
, tail
= XCDR (tail
))
3677 Lisp_Object name
= XCAR (XCAR (tail
));
3678 Lisp_Object color
= XCDR (XCAR (tail
));
3679 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3680 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3681 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3682 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3686 /* Create a pixmap for the image, either from a file, or from a
3687 string buffer containing data in the same format as an XPM file. */
3688 #ifdef ALLOC_XPM_COLORS
3689 xpm_init_color_cache (f
, &attrs
);
3692 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3696 HDC frame_dc
= get_frame_dc (f
);
3697 hdc
= CreateCompatibleDC (frame_dc
);
3698 release_frame_dc (f
, frame_dc
);
3700 #endif /* HAVE_NTGUI */
3702 if (STRINGP (specified_file
))
3704 Lisp_Object file
= x_find_image_file (specified_file
);
3705 if (!STRINGP (file
))
3707 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3712 /* XpmReadFileToPixmap is not available in the Windows port of
3713 libxpm. But XpmReadFileToImage almost does what we want. */
3714 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3715 &xpm_image
, &xpm_mask
,
3718 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3719 SDATA (file
), &img
->pixmap
, &img
->mask
,
3721 #endif /* HAVE_NTGUI */
3725 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3727 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3728 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3729 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3730 &xpm_image
, &xpm_mask
,
3733 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3735 &img
->pixmap
, &img
->mask
,
3737 #endif /* HAVE_NTGUI */
3740 if (rc
== XpmSuccess
)
3742 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3743 img
->colors
= colors_in_color_table (&img
->ncolors
);
3744 #else /* not ALLOC_XPM_COLORS */
3748 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3749 plus some duplicate attributes. */
3750 if (xpm_image
&& xpm_image
->bitmap
)
3752 img
->pixmap
= xpm_image
->bitmap
;
3753 /* XImageFree in libXpm frees XImage struct without destroying
3754 the bitmap, which is what we want. */
3755 fn_XImageFree (xpm_image
);
3757 if (xpm_mask
&& xpm_mask
->bitmap
)
3759 /* The mask appears to be inverted compared with what we expect.
3760 TODO: invert our expectations. See other places where we
3761 have to invert bits because our idea of masks is backwards. */
3763 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3765 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3766 SelectObject (hdc
, old_obj
);
3768 img
->mask
= xpm_mask
->bitmap
;
3769 fn_XImageFree (xpm_mask
);
3774 #endif /* HAVE_NTGUI */
3776 /* Remember allocated colors. */
3777 img
->ncolors
= attrs
.nalloc_pixels
;
3778 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3779 * sizeof *img
->colors
);
3780 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3782 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3783 #ifdef DEBUG_X_COLORS
3784 register_color (img
->colors
[i
]);
3787 #endif /* not ALLOC_XPM_COLORS */
3789 img
->width
= attrs
.width
;
3790 img
->height
= attrs
.height
;
3791 xassert (img
->width
> 0 && img
->height
> 0);
3793 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3795 fn_XpmFreeAttributes (&attrs
);
3797 XpmFreeAttributes (&attrs
);
3798 #endif /* HAVE_NTGUI */
3804 #endif /* HAVE_NTGUI */
3809 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3812 case XpmFileInvalid
:
3813 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3817 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3820 case XpmColorFailed
:
3821 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3825 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3830 #ifdef ALLOC_XPM_COLORS
3831 xpm_free_color_cache ();
3833 return rc
== XpmSuccess
;
3836 #endif /* HAVE_XPM */
3840 /* XPM support functions for Mac OS where libxpm is not available.
3841 Only XPM version 3 (without any extensions) is supported. */
3843 static int xpm_scan
P_ ((unsigned char **, unsigned char *,
3844 unsigned char **, int *));
3845 static Lisp_Object xpm_make_color_table_v
3846 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3847 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3848 static void xpm_put_color_table_v
P_ ((Lisp_Object
, unsigned char *,
3850 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3851 unsigned char *, int));
3852 static Lisp_Object xpm_make_color_table_h
3853 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3854 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3855 static void xpm_put_color_table_h
P_ ((Lisp_Object
, unsigned char *,
3857 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3858 unsigned char *, int));
3859 static int xpm_str_to_color_key
P_ ((char *));
3860 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3861 unsigned char *, unsigned char *));
3863 /* Tokens returned from xpm_scan. */
3872 /* Scan an XPM data and return a character (< 256) or a token defined
3873 by enum xpm_token above. *S and END are the start (inclusive) and
3874 the end (exclusive) addresses of the data, respectively. Advance
3875 *S while scanning. If token is either XPM_TK_IDENT or
3876 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3877 length of the corresponding token, respectively. */
3880 xpm_scan (s
, end
, beg
, len
)
3881 unsigned char **s
, *end
, **beg
;
3888 /* Skip white-space. */
3889 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3892 /* gnus-pointer.xpm uses '-' in its identifier.
3893 sb-dir-plus.xpm uses '+' in its identifier. */
3894 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
3898 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
3901 return XPM_TK_IDENT
;
3906 while (*s
< end
&& **s
!= '"')
3911 return XPM_TK_STRING
;
3915 if (*s
< end
&& **s
== '*')
3917 /* C-style comment. */
3921 while (*s
< end
&& *(*s
)++ != '*')
3924 while (*s
< end
&& **s
!= '/');
3938 /* Functions for color table lookup in XPM data. A Key is a string
3939 specifying the color of each pixel in XPM data. A value is either
3940 an integer that specifies a pixel color, Qt that specifies
3941 transparency, or Qnil for the unspecified color. If the length of
3942 the key string is one, a vector is used as a table. Otherwise, a
3943 hash table is used. */
3946 xpm_make_color_table_v (put_func
, get_func
)
3947 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3948 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3950 *put_func
= xpm_put_color_table_v
;
3951 *get_func
= xpm_get_color_table_v
;
3952 return Fmake_vector (make_number (256), Qnil
);
3956 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
3957 Lisp_Object color_table
;
3958 unsigned char *chars_start
;
3962 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
3966 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
3967 Lisp_Object color_table
;
3968 unsigned char *chars_start
;
3971 return XVECTOR (color_table
)->contents
[*chars_start
];
3975 xpm_make_color_table_h (put_func
, get_func
)
3976 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3977 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3979 *put_func
= xpm_put_color_table_h
;
3980 *get_func
= xpm_get_color_table_h
;
3981 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
3982 make_float (DEFAULT_REHASH_SIZE
),
3983 make_float (DEFAULT_REHASH_THRESHOLD
),
3988 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
3989 Lisp_Object color_table
;
3990 unsigned char *chars_start
;
3994 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
3996 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
3998 hash_lookup (table
, chars
, &hash_code
);
3999 hash_put (table
, chars
, color
, hash_code
);
4003 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4004 Lisp_Object color_table
;
4005 unsigned char *chars_start
;
4008 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4009 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4012 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4015 enum xpm_color_key
{
4023 static char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4026 xpm_str_to_color_key (s
)
4032 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4034 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4040 xpm_load_image (f
, img
, contents
, end
)
4043 unsigned char *contents
, *end
;
4045 unsigned char *s
= contents
, *beg
, *str
;
4046 unsigned char buffer
[BUFSIZ
];
4047 int width
, height
, x
, y
;
4048 int num_colors
, chars_per_pixel
;
4050 void (*put_color_table
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4051 Lisp_Object (*get_color_table
) (Lisp_Object
, unsigned char *, int);
4052 Lisp_Object frame
, color_symbols
, color_table
;
4053 int best_key
, have_mask
= 0;
4054 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4057 LA1 = xpm_scan (&s, end, &beg, &len)
4059 #define expect(TOKEN) \
4060 if (LA1 != (TOKEN)) \
4065 #define expect_ident(IDENT) \
4066 if (LA1 == XPM_TK_IDENT \
4067 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4072 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4076 expect_ident ("static");
4077 expect_ident ("char");
4079 expect (XPM_TK_IDENT
);
4084 expect (XPM_TK_STRING
);
4087 memcpy (buffer
, beg
, len
);
4089 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4090 &num_colors
, &chars_per_pixel
) != 4
4091 || width
<= 0 || height
<= 0
4092 || num_colors
<= 0 || chars_per_pixel
<= 0)
4096 XSETFRAME (frame
, f
);
4097 if (!NILP (Fxw_display_color_p (frame
)))
4098 best_key
= XPM_COLOR_KEY_C
;
4099 else if (!NILP (Fx_display_grayscale_p (frame
)))
4100 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4101 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4103 best_key
= XPM_COLOR_KEY_M
;
4105 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4106 if (chars_per_pixel
== 1)
4107 color_table
= xpm_make_color_table_v (&put_color_table
,
4110 color_table
= xpm_make_color_table_h (&put_color_table
,
4113 while (num_colors
-- > 0)
4115 unsigned char *color
, *max_color
;
4116 int key
, next_key
, max_key
= 0;
4117 Lisp_Object symbol_color
= Qnil
, color_val
;
4120 expect (XPM_TK_STRING
);
4121 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4123 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4124 buffer
[len
- chars_per_pixel
] = '\0';
4126 str
= strtok (buffer
, " \t");
4129 key
= xpm_str_to_color_key (str
);
4134 color
= strtok (NULL
, " \t");
4138 while (str
= strtok (NULL
, " \t"))
4140 next_key
= xpm_str_to_color_key (str
);
4143 color
[strlen (color
)] = ' ';
4146 if (key
== XPM_COLOR_KEY_S
)
4148 if (NILP (symbol_color
))
4149 symbol_color
= build_string (color
);
4151 else if (max_key
< key
&& key
<= best_key
)
4161 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4163 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4165 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4166 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4168 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4170 color_val
= make_number (cdef
.pixel
);
4172 if (NILP (color_val
) && max_key
> 0)
4173 if (xstricmp (max_color
, "None") == 0)
4175 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4176 color_val
= make_number (cdef
.pixel
);
4177 if (!NILP (color_val
))
4178 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4183 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4184 &ximg
, &img
->pixmap
)
4185 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4186 &mask_img
, &img
->mask
))
4188 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4192 for (y
= 0; y
< height
; y
++)
4194 expect (XPM_TK_STRING
);
4196 if (len
< width
* chars_per_pixel
)
4198 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4200 Lisp_Object color_val
=
4201 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4203 XPutPixel (ximg
, x
, y
,
4204 (INTEGERP (color_val
) ? XINT (color_val
)
4205 : FRAME_FOREGROUND_PIXEL (f
)));
4206 XPutPixel (mask_img
, x
, y
,
4207 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW (f
)
4208 : (have_mask
= 1, PIX_MASK_RETAIN (f
))));
4215 img
->height
= height
;
4217 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4218 x_destroy_x_image (ximg
);
4221 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4222 x_destroy_x_image (mask_img
);
4226 x_destroy_x_image (mask_img
);
4227 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4228 img
->mask
= NO_PIXMAP
;
4234 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4236 x_destroy_x_image (ximg
);
4237 x_destroy_x_image (mask_img
);
4238 x_clear_image (f
, img
);
4252 Lisp_Object file_name
;
4254 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4255 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4256 if (STRINGP (file_name
))
4259 unsigned char *contents
;
4261 struct gcpro gcpro1
;
4263 file
= x_find_image_file (file_name
);
4265 if (!STRINGP (file
))
4267 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4272 contents
= slurp_file (SDATA (file
), &size
);
4273 if (contents
== NULL
)
4275 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4280 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4288 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4289 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4290 SDATA (data
) + SBYTES (data
));
4300 /***********************************************************************
4302 ***********************************************************************/
4304 #ifdef COLOR_TABLE_SUPPORT
4306 /* An entry in the color table mapping an RGB color to a pixel color. */
4311 unsigned long pixel
;
4313 /* Next in color table collision list. */
4314 struct ct_color
*next
;
4317 /* The bucket vector size to use. Must be prime. */
4321 /* Value is a hash of the RGB color given by R, G, and B. */
4323 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4325 /* The color hash table. */
4327 struct ct_color
**ct_table
;
4329 /* Number of entries in the color table. */
4331 int ct_colors_allocated
;
4333 /* Initialize the color table. */
4338 int size
= CT_SIZE
* sizeof (*ct_table
);
4339 ct_table
= (struct ct_color
**) xmalloc (size
);
4340 bzero (ct_table
, size
);
4341 ct_colors_allocated
= 0;
4345 /* Free memory associated with the color table. */
4351 struct ct_color
*p
, *next
;
4353 for (i
= 0; i
< CT_SIZE
; ++i
)
4354 for (p
= ct_table
[i
]; p
; p
= next
)
4365 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4366 entry for that color already is in the color table, return the
4367 pixel color of that entry. Otherwise, allocate a new color for R,
4368 G, B, and make an entry in the color table. */
4370 static unsigned long
4371 lookup_rgb_color (f
, r
, g
, b
)
4375 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4376 int i
= hash
% CT_SIZE
;
4378 Display_Info
*dpyinfo
;
4380 /* Handle TrueColor visuals specially, which improves performance by
4381 two orders of magnitude. Freeing colors on TrueColor visuals is
4382 a nop, and pixel colors specify RGB values directly. See also
4383 the Xlib spec, chapter 3.1. */
4384 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4385 if (dpyinfo
->red_bits
> 0)
4387 unsigned long pr
, pg
, pb
;
4389 /* Apply gamma-correction like normal color allocation does. */
4393 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4394 gamma_correct (f
, &color
);
4395 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4398 /* Scale down RGB values to the visual's bits per RGB, and shift
4399 them to the right position in the pixel color. Note that the
4400 original RGB values are 16-bit values, as usual in X. */
4401 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4402 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4403 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4405 /* Assemble the pixel color. */
4406 return pr
| pg
| pb
;
4409 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4410 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4416 #ifdef HAVE_X_WINDOWS
4425 cmap
= FRAME_X_COLORMAP (f
);
4426 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4429 ++ct_colors_allocated
;
4430 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4434 p
->pixel
= color
.pixel
;
4435 p
->next
= ct_table
[i
];
4439 return FRAME_FOREGROUND_PIXEL (f
);
4444 color
= PALETTERGB (r
, g
, b
);
4446 color
= RGB_TO_ULONG (r
, g
, b
);
4447 #endif /* HAVE_NTGUI */
4448 ++ct_colors_allocated
;
4449 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4454 p
->next
= ct_table
[i
];
4456 #endif /* HAVE_X_WINDOWS */
4464 /* Look up pixel color PIXEL which is used on frame F in the color
4465 table. If not already present, allocate it. Value is PIXEL. */
4467 static unsigned long
4468 lookup_pixel_color (f
, pixel
)
4470 unsigned long pixel
;
4472 int i
= pixel
% CT_SIZE
;
4475 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4476 if (p
->pixel
== pixel
)
4485 #ifdef HAVE_X_WINDOWS
4486 cmap
= FRAME_X_COLORMAP (f
);
4487 color
.pixel
= pixel
;
4488 x_query_color (f
, &color
);
4489 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4492 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4493 color
.pixel
= pixel
;
4494 XQueryColor (NULL
, cmap
, &color
);
4495 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4497 #endif /* HAVE_X_WINDOWS */
4501 ++ct_colors_allocated
;
4503 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4508 p
->next
= ct_table
[i
];
4512 return FRAME_FOREGROUND_PIXEL (f
);
4518 /* Value is a vector of all pixel colors contained in the color table,
4519 allocated via xmalloc. Set *N to the number of colors. */
4521 static unsigned long *
4522 colors_in_color_table (n
)
4527 unsigned long *colors
;
4529 if (ct_colors_allocated
== 0)
4536 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4538 *n
= ct_colors_allocated
;
4540 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4541 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4542 colors
[j
++] = p
->pixel
;
4548 #else /* COLOR_TABLE_SUPPORT */
4550 static unsigned long
4551 lookup_rgb_color (f
, r
, g
, b
)
4555 unsigned long pixel
;
4558 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4559 gamma_correct (f
, &pixel
);
4563 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4564 #endif /* HAVE_NTGUI */
4573 #endif /* COLOR_TABLE_SUPPORT */
4576 /***********************************************************************
4578 ***********************************************************************/
4580 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4581 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4582 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4585 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4586 #endif /* HAVE_NTGUI */
4588 /* Non-zero means draw a cross on images having `:conversion
4591 int cross_disabled_images
;
4593 /* Edge detection matrices for different edge-detection
4596 static int emboss_matrix
[9] = {
4598 2, -1, 0, /* y - 1 */
4600 0, 1, -2 /* y + 1 */
4603 static int laplace_matrix
[9] = {
4605 1, 0, 0, /* y - 1 */
4607 0, 0, -1 /* y + 1 */
4610 /* Value is the intensity of the color whose red/green/blue values
4613 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4616 /* On frame F, return an array of XColor structures describing image
4617 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4618 non-zero means also fill the red/green/blue members of the XColor
4619 structures. Value is a pointer to the array of XColors structures,
4620 allocated with xmalloc; it must be freed by the caller. */
4623 x_to_xcolors (f
, img
, rgb_p
)
4630 XImagePtr_or_DC ximg
;
4634 #endif /* HAVE_NTGUI */
4636 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4639 /* Get the X image IMG->pixmap. */
4640 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4641 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4643 /* Load the image into a memory device context. */
4644 hdc
= get_frame_dc (f
);
4645 ximg
= CreateCompatibleDC (hdc
);
4646 release_frame_dc (f
, hdc
);
4647 prev
= SelectObject (ximg
, img
->pixmap
);
4648 #endif /* HAVE_NTGUI */
4650 /* Fill the `pixel' members of the XColor array. I wished there
4651 were an easy and portable way to circumvent XGetPixel. */
4653 for (y
= 0; y
< img
->height
; ++y
)
4657 #ifdef HAVE_X_WINDOWS
4658 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4659 p
->pixel
= XGetPixel (ximg
, x
, y
);
4661 x_query_colors (f
, row
, img
->width
);
4665 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4667 /* W32_TODO: palette support needed here? */
4668 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4672 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4673 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4674 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4677 p
->red
= 256 * GetRValue (p
->pixel
);
4678 p
->green
= 256 * GetGValue (p
->pixel
);
4679 p
->blue
= 256 * GetBValue (p
->pixel
);
4680 #endif /* HAVE_NTGUI */
4683 #endif /* HAVE_X_WINDOWS */
4686 Destroy_Image (ximg
, prev
);
4693 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4694 created with CreateDIBSection, with the pointer to the bit values
4695 stored in ximg->data. */
4697 static void XPutPixel (ximg
, x
, y
, color
)
4702 int width
= ximg
->info
.bmiHeader
.biWidth
;
4703 int height
= ximg
->info
.bmiHeader
.biHeight
;
4704 unsigned char * pixel
;
4706 /* True color images. */
4707 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4709 int rowbytes
= width
* 3;
4710 /* Ensure scanlines are aligned on 4 byte boundaries. */
4712 rowbytes
+= 4 - (rowbytes
% 4);
4714 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4715 /* Windows bitmaps are in BGR order. */
4716 *pixel
= GetBValue (color
);
4717 *(pixel
+ 1) = GetGValue (color
);
4718 *(pixel
+ 2) = GetRValue (color
);
4720 /* Monochrome images. */
4721 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4723 int rowbytes
= width
/ 8;
4724 /* Ensure scanlines are aligned on 4 byte boundaries. */
4726 rowbytes
+= 4 - (rowbytes
% 4);
4727 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4728 /* Filter out palette info. */
4729 if (color
& 0x00ffffff)
4730 *pixel
= *pixel
| (1 << x
% 8);
4732 *pixel
= *pixel
& ~(1 << x
% 8);
4735 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4738 #endif /* HAVE_NTGUI */
4740 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4741 RGB members are set. F is the frame on which this all happens.
4742 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4745 x_from_xcolors (f
, img
, colors
)
4755 init_color_table ();
4757 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4760 for (y
= 0; y
< img
->height
; ++y
)
4761 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4763 unsigned long pixel
;
4764 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4765 XPutPixel (oimg
, x
, y
, pixel
);
4769 x_clear_image_1 (f
, img
, 1, 0, 1);
4771 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4772 x_destroy_x_image (oimg
);
4773 img
->pixmap
= pixmap
;
4774 #ifdef COLOR_TABLE_SUPPORT
4775 img
->colors
= colors_in_color_table (&img
->ncolors
);
4776 free_color_table ();
4777 #endif /* COLOR_TABLE_SUPPORT */
4781 /* On frame F, perform edge-detection on image IMG.
4783 MATRIX is a nine-element array specifying the transformation
4784 matrix. See emboss_matrix for an example.
4786 COLOR_ADJUST is a color adjustment added to each pixel of the
4790 x_detect_edges (f
, img
, matrix
, color_adjust
)
4793 int matrix
[9], color_adjust
;
4795 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4799 for (i
= sum
= 0; i
< 9; ++i
)
4800 sum
+= abs (matrix
[i
]);
4802 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4804 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4806 for (y
= 0; y
< img
->height
; ++y
)
4808 p
= COLOR (new, 0, y
);
4809 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4810 p
= COLOR (new, img
->width
- 1, y
);
4811 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4814 for (x
= 1; x
< img
->width
- 1; ++x
)
4816 p
= COLOR (new, x
, 0);
4817 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4818 p
= COLOR (new, x
, img
->height
- 1);
4819 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4822 for (y
= 1; y
< img
->height
- 1; ++y
)
4824 p
= COLOR (new, 1, y
);
4826 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4828 int r
, g
, b
, y1
, x1
;
4831 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4832 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4835 XColor
*t
= COLOR (colors
, x1
, y1
);
4836 r
+= matrix
[i
] * t
->red
;
4837 g
+= matrix
[i
] * t
->green
;
4838 b
+= matrix
[i
] * t
->blue
;
4841 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4842 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4843 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4844 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4849 x_from_xcolors (f
, img
, new);
4855 /* Perform the pre-defined `emboss' edge-detection on image IMG
4863 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4867 /* Transform image IMG which is used on frame F with a Laplace
4868 edge-detection algorithm. The result is an image that can be used
4869 to draw disabled buttons, for example. */
4876 x_detect_edges (f
, img
, laplace_matrix
, 45000);
4880 /* Perform edge-detection on image IMG on frame F, with specified
4881 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4883 MATRIX must be either
4885 - a list of at least 9 numbers in row-major form
4886 - a vector of at least 9 numbers
4888 COLOR_ADJUST nil means use a default; otherwise it must be a
4892 x_edge_detection (f
, img
, matrix
, color_adjust
)
4895 Lisp_Object matrix
, color_adjust
;
4903 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
4904 ++i
, matrix
= XCDR (matrix
))
4905 trans
[i
] = XFLOATINT (XCAR (matrix
));
4907 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
4909 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
4910 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
4913 if (NILP (color_adjust
))
4914 color_adjust
= make_number (0xffff / 2);
4916 if (i
== 9 && NUMBERP (color_adjust
))
4917 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
4921 /* Transform image IMG on frame F so that it looks disabled. */
4924 x_disable_image (f
, img
)
4928 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4930 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
4932 int n_planes
= dpyinfo
->n_planes
;
4933 #endif /* HAVE_NTGUI */
4937 /* Color (or grayscale). Convert to gray, and equalize. Just
4938 drawing such images with a stipple can look very odd, so
4939 we're using this method instead. */
4940 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4942 const int h
= 15000;
4943 const int l
= 30000;
4945 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
4949 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
4950 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
4951 p
->red
= p
->green
= p
->blue
= i2
;
4954 x_from_xcolors (f
, img
, colors
);
4957 /* Draw a cross over the disabled image, if we must or if we
4959 if (n_planes
< 2 || cross_disabled_images
)
4962 Display
*dpy
= FRAME_X_DISPLAY (f
);
4966 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4967 #define MaskForeground(f) PIX_MASK_DRAW (f)
4969 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4970 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4973 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
4974 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
4975 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
4976 img
->width
- 1, img
->height
- 1);
4977 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
4983 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
4984 XSetForeground (dpy
, gc
, MaskForeground (f
));
4985 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
4986 img
->width
- 1, img
->height
- 1);
4987 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
4995 hdc
= get_frame_dc (f
);
4996 bmpdc
= CreateCompatibleDC (hdc
);
4997 release_frame_dc (f
, hdc
);
4999 prev
= SelectObject (bmpdc
, img
->pixmap
);
5001 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5002 MoveToEx (bmpdc
, 0, 0, NULL
);
5003 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5004 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5005 LineTo (bmpdc
, img
->width
- 1, 0);
5009 SelectObject (bmpdc
, img
->mask
);
5010 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5011 MoveToEx (bmpdc
, 0, 0, NULL
);
5012 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5013 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5014 LineTo (bmpdc
, img
->width
- 1, 0);
5016 SelectObject (bmpdc
, prev
);
5018 #endif /* HAVE_NTGUI */
5023 /* Build a mask for image IMG which is used on frame F. FILE is the
5024 name of an image file, for error messages. HOW determines how to
5025 determine the background color of IMG. If it is a list '(R G B)',
5026 with R, G, and B being integers >= 0, take that as the color of the
5027 background. Otherwise, determine the background color of IMG
5028 heuristically. Value is non-zero if successful. */
5031 x_build_heuristic_mask (f
, img
, how
)
5036 XImagePtr_or_DC ximg
;
5044 #endif /* HAVE_NTGUI */
5045 int x
, y
, rc
, use_img_background
;
5046 unsigned long bg
= 0;
5050 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5051 img
->mask
= NO_PIXMAP
;
5052 img
->background_transparent_valid
= 0;
5056 /* Create an image and pixmap serving as mask. */
5057 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5058 &mask_img
, &img
->mask
);
5062 /* Get the X image of IMG->pixmap. */
5063 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5064 img
->width
, img
->height
,
5067 /* Create the bit array serving as mask. */
5068 row_width
= (img
->width
+ 7) / 8;
5069 mask_img
= xmalloc (row_width
* img
->height
);
5070 bzero (mask_img
, row_width
* img
->height
);
5072 /* Create a memory device context for IMG->pixmap. */
5073 frame_dc
= get_frame_dc (f
);
5074 ximg
= CreateCompatibleDC (frame_dc
);
5075 release_frame_dc (f
, frame_dc
);
5076 prev
= SelectObject (ximg
, img
->pixmap
);
5077 #endif /* HAVE_NTGUI */
5079 /* Determine the background color of ximg. If HOW is `(R G B)'
5080 take that as color. Otherwise, use the image's background color. */
5081 use_img_background
= 1;
5087 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5089 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5093 if (i
== 3 && NILP (how
))
5095 char color_name
[30];
5096 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5099 0x00ffffff & /* Filter out palette info. */
5100 #endif /* HAVE_NTGUI */
5101 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5102 use_img_background
= 0;
5106 if (use_img_background
)
5107 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
5109 /* Set all bits in mask_img to 1 whose color in ximg is different
5110 from the background color bg. */
5112 for (y
= 0; y
< img
->height
; ++y
)
5113 for (x
= 0; x
< img
->width
; ++x
)
5114 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5115 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
)));
5117 /* Fill in the background_transparent field while we have the mask handy. */
5118 image_background_transparent (img
, f
, mask_img
);
5120 /* Put mask_img into img->mask. */
5121 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5122 x_destroy_x_image (mask_img
);
5125 for (y
= 0; y
< img
->height
; ++y
)
5126 for (x
= 0; x
< img
->width
; ++x
)
5128 COLORREF p
= GetPixel (ximg
, x
, y
);
5130 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5133 /* Create the mask image. */
5134 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5136 /* Fill in the background_transparent field while we have the mask handy. */
5137 SelectObject (ximg
, img
->mask
);
5138 image_background_transparent (img
, f
, ximg
);
5140 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5142 #endif /* HAVE_NTGUI */
5144 Destroy_Image (ximg
, prev
);
5150 /***********************************************************************
5151 PBM (mono, gray, color)
5152 ***********************************************************************/
5154 static int pbm_image_p
P_ ((Lisp_Object object
));
5155 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5156 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5158 /* The symbol `pbm' identifying images of this type. */
5162 /* Indices of image specification fields in gs_format, below. */
5164 enum pbm_keyword_index
5180 /* Vector of image_keyword structures describing the format
5181 of valid user-defined image specifications. */
5183 static struct image_keyword pbm_format
[PBM_LAST
] =
5185 {":type", IMAGE_SYMBOL_VALUE
, 1},
5186 {":file", IMAGE_STRING_VALUE
, 0},
5187 {":data", IMAGE_STRING_VALUE
, 0},
5188 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5189 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5190 {":relief", IMAGE_INTEGER_VALUE
, 0},
5191 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5192 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5193 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5194 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5195 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5198 /* Structure describing the image type `pbm'. */
5200 static struct image_type pbm_type
=
5210 /* Return non-zero if OBJECT is a valid PBM image specification. */
5213 pbm_image_p (object
)
5216 struct image_keyword fmt
[PBM_LAST
];
5218 bcopy (pbm_format
, fmt
, sizeof fmt
);
5220 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5223 /* Must specify either :data or :file. */
5224 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5228 /* Scan a decimal number from *S and return it. Advance *S while
5229 reading the number. END is the end of the string. Value is -1 at
5233 pbm_scan_number (s
, end
)
5234 unsigned char **s
, *end
;
5236 int c
= 0, val
= -1;
5240 /* Skip white-space. */
5241 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5246 /* Skip comment to end of line. */
5247 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5250 else if (isdigit (c
))
5252 /* Read decimal number. */
5254 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5255 val
= 10 * val
+ c
- '0';
5267 #if 0 /* Unused. ++kfs */
5269 /* Read FILE into memory. Value is a pointer to a buffer allocated
5270 with xmalloc holding FILE's contents. Value is null if an error
5271 occurred. *SIZE is set to the size of the file. */
5274 pbm_read_file (file
, size
)
5282 if (stat (SDATA (file
), &st
) == 0
5283 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5284 && (buf
= (char *) xmalloc (st
.st_size
),
5285 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5304 #endif /* HAVE_NTGUI */
5306 /* Load PBM image IMG for use on frame F. */
5314 int width
, height
, max_color_idx
= 0;
5316 Lisp_Object file
, specified_file
;
5317 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5318 struct gcpro gcpro1
;
5319 unsigned char *contents
= NULL
;
5320 unsigned char *end
, *p
;
5323 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5327 if (STRINGP (specified_file
))
5329 file
= x_find_image_file (specified_file
);
5330 if (!STRINGP (file
))
5332 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5337 contents
= slurp_file (SDATA (file
), &size
);
5338 if (contents
== NULL
)
5340 image_error ("Error reading `%s'", file
, Qnil
);
5346 end
= contents
+ size
;
5351 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5353 end
= p
+ SBYTES (data
);
5356 /* Check magic number. */
5357 if (end
- p
< 2 || *p
++ != 'P')
5359 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5369 raw_p
= 0, type
= PBM_MONO
;
5373 raw_p
= 0, type
= PBM_GRAY
;
5377 raw_p
= 0, type
= PBM_COLOR
;
5381 raw_p
= 1, type
= PBM_MONO
;
5385 raw_p
= 1, type
= PBM_GRAY
;
5389 raw_p
= 1, type
= PBM_COLOR
;
5393 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5397 /* Read width, height, maximum color-component. Characters
5398 starting with `#' up to the end of a line are ignored. */
5399 width
= pbm_scan_number (&p
, end
);
5400 height
= pbm_scan_number (&p
, end
);
5402 if (type
!= PBM_MONO
)
5404 max_color_idx
= pbm_scan_number (&p
, end
);
5405 if (raw_p
&& max_color_idx
> 255)
5406 max_color_idx
= 255;
5411 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5414 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5415 &ximg
, &img
->pixmap
))
5418 /* Initialize the color hash table. */
5419 init_color_table ();
5421 if (type
== PBM_MONO
)
5424 struct image_keyword fmt
[PBM_LAST
];
5425 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5426 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5428 /* Parse the image specification. */
5429 bcopy (pbm_format
, fmt
, sizeof fmt
);
5430 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5432 /* Get foreground and background colors, maybe allocate colors. */
5433 if (fmt
[PBM_FOREGROUND
].count
5434 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5435 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5436 if (fmt
[PBM_BACKGROUND
].count
5437 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5439 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5440 img
->background
= bg
;
5441 img
->background_valid
= 1;
5444 for (y
= 0; y
< height
; ++y
)
5445 for (x
= 0; x
< width
; ++x
)
5455 g
= pbm_scan_number (&p
, end
);
5457 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5462 for (y
= 0; y
< height
; ++y
)
5463 for (x
= 0; x
< width
; ++x
)
5467 if (type
== PBM_GRAY
)
5468 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5477 r
= pbm_scan_number (&p
, end
);
5478 g
= pbm_scan_number (&p
, end
);
5479 b
= pbm_scan_number (&p
, end
);
5482 if (r
< 0 || g
< 0 || b
< 0)
5484 x_destroy_x_image (ximg
);
5485 image_error ("Invalid pixel value in image `%s'",
5490 /* RGB values are now in the range 0..max_color_idx.
5491 Scale this to the range 0..0xffff supported by X. */
5492 r
= (double) r
* 65535 / max_color_idx
;
5493 g
= (double) g
* 65535 / max_color_idx
;
5494 b
= (double) b
* 65535 / max_color_idx
;
5495 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5499 #ifdef COLOR_TABLE_SUPPORT
5500 /* Store in IMG->colors the colors allocated for the image, and
5501 free the color table. */
5502 img
->colors
= colors_in_color_table (&img
->ncolors
);
5503 free_color_table ();
5504 #endif /* COLOR_TABLE_SUPPORT */
5507 img
->height
= height
;
5509 /* Maybe fill in the background field while we have ximg handy. */
5511 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5512 IMAGE_BACKGROUND (img
, f
, ximg
);
5514 /* Put the image into a pixmap. */
5515 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5516 x_destroy_x_image (ximg
);
5518 /* X and W32 versions did it here, MAC version above. ++kfs
5520 img->height = height; */
5528 /***********************************************************************
5530 ***********************************************************************/
5532 #if defined (HAVE_PNG) || defined (MAC_OS)
5534 /* Function prototypes. */
5536 static int png_image_p
P_ ((Lisp_Object object
));
5537 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5539 /* The symbol `png' identifying images of this type. */
5543 /* Indices of image specification fields in png_format, below. */
5545 enum png_keyword_index
5560 /* Vector of image_keyword structures describing the format
5561 of valid user-defined image specifications. */
5563 static struct image_keyword png_format
[PNG_LAST
] =
5565 {":type", IMAGE_SYMBOL_VALUE
, 1},
5566 {":data", IMAGE_STRING_VALUE
, 0},
5567 {":file", IMAGE_STRING_VALUE
, 0},
5568 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5569 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5570 {":relief", IMAGE_INTEGER_VALUE
, 0},
5571 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5572 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5573 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5574 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5577 /* Structure describing the image type `png'. */
5579 static struct image_type png_type
=
5588 /* Return non-zero if OBJECT is a valid PNG image specification. */
5591 png_image_p (object
)
5594 struct image_keyword fmt
[PNG_LAST
];
5595 bcopy (png_format
, fmt
, sizeof fmt
);
5597 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5600 /* Must specify either the :data or :file keyword. */
5601 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5604 #endif /* HAVE_PNG || MAC_OS */
5609 #if defined HAVE_LIBPNG_PNG_H
5610 # include <libpng/png.h>
5616 /* PNG library details. */
5618 DEF_IMGLIB_FN (png_get_io_ptr
);
5619 DEF_IMGLIB_FN (png_check_sig
);
5620 DEF_IMGLIB_FN (png_create_read_struct
);
5621 DEF_IMGLIB_FN (png_create_info_struct
);
5622 DEF_IMGLIB_FN (png_destroy_read_struct
);
5623 DEF_IMGLIB_FN (png_set_read_fn
);
5624 DEF_IMGLIB_FN (png_init_io
);
5625 DEF_IMGLIB_FN (png_set_sig_bytes
);
5626 DEF_IMGLIB_FN (png_read_info
);
5627 DEF_IMGLIB_FN (png_get_IHDR
);
5628 DEF_IMGLIB_FN (png_get_valid
);
5629 DEF_IMGLIB_FN (png_set_strip_16
);
5630 DEF_IMGLIB_FN (png_set_expand
);
5631 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5632 DEF_IMGLIB_FN (png_set_background
);
5633 DEF_IMGLIB_FN (png_get_bKGD
);
5634 DEF_IMGLIB_FN (png_read_update_info
);
5635 DEF_IMGLIB_FN (png_get_channels
);
5636 DEF_IMGLIB_FN (png_get_rowbytes
);
5637 DEF_IMGLIB_FN (png_read_image
);
5638 DEF_IMGLIB_FN (png_read_end
);
5639 DEF_IMGLIB_FN (png_error
);
5642 init_png_functions (Lisp_Object libraries
)
5646 /* Try loading libpng under probable names. */
5647 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5650 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5651 LOAD_IMGLIB_FN (library
, png_check_sig
);
5652 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5653 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5654 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5655 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5656 LOAD_IMGLIB_FN (library
, png_init_io
);
5657 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5658 LOAD_IMGLIB_FN (library
, png_read_info
);
5659 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5660 LOAD_IMGLIB_FN (library
, png_get_valid
);
5661 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5662 LOAD_IMGLIB_FN (library
, png_set_expand
);
5663 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5664 LOAD_IMGLIB_FN (library
, png_set_background
);
5665 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5666 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5667 LOAD_IMGLIB_FN (library
, png_get_channels
);
5668 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5669 LOAD_IMGLIB_FN (library
, png_read_image
);
5670 LOAD_IMGLIB_FN (library
, png_read_end
);
5671 LOAD_IMGLIB_FN (library
, png_error
);
5676 #define fn_png_get_io_ptr png_get_io_ptr
5677 #define fn_png_check_sig png_check_sig
5678 #define fn_png_create_read_struct png_create_read_struct
5679 #define fn_png_create_info_struct png_create_info_struct
5680 #define fn_png_destroy_read_struct png_destroy_read_struct
5681 #define fn_png_set_read_fn png_set_read_fn
5682 #define fn_png_init_io png_init_io
5683 #define fn_png_set_sig_bytes png_set_sig_bytes
5684 #define fn_png_read_info png_read_info
5685 #define fn_png_get_IHDR png_get_IHDR
5686 #define fn_png_get_valid png_get_valid
5687 #define fn_png_set_strip_16 png_set_strip_16
5688 #define fn_png_set_expand png_set_expand
5689 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5690 #define fn_png_set_background png_set_background
5691 #define fn_png_get_bKGD png_get_bKGD
5692 #define fn_png_read_update_info png_read_update_info
5693 #define fn_png_get_channels png_get_channels
5694 #define fn_png_get_rowbytes png_get_rowbytes
5695 #define fn_png_read_image png_read_image
5696 #define fn_png_read_end png_read_end
5697 #define fn_png_error png_error
5699 #endif /* HAVE_NTGUI */
5701 /* Error and warning handlers installed when the PNG library
5705 my_png_error (png_ptr
, msg
)
5706 png_struct
*png_ptr
;
5709 xassert (png_ptr
!= NULL
);
5710 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5711 longjmp (png_ptr
->jmpbuf
, 1);
5716 my_png_warning (png_ptr
, msg
)
5717 png_struct
*png_ptr
;
5720 xassert (png_ptr
!= NULL
);
5721 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5724 /* Memory source for PNG decoding. */
5726 struct png_memory_storage
5728 unsigned char *bytes
; /* The data */
5729 size_t len
; /* How big is it? */
5730 int index
; /* Where are we? */
5734 /* Function set as reader function when reading PNG image from memory.
5735 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5736 bytes from the input to DATA. */
5739 /* Work around a problem with MinGW builds of graphics libraries
5740 not honoring calling conventions. */
5741 #pragma optimize("g", off)
5745 png_read_from_memory (png_ptr
, data
, length
)
5746 png_structp png_ptr
;
5750 struct png_memory_storage
*tbr
5751 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5753 if (length
> tbr
->len
- tbr
->index
)
5754 fn_png_error (png_ptr
, "Read error");
5756 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5757 tbr
->index
= tbr
->index
+ length
;
5761 /* Restore normal optimization, as specified on the command line. */
5762 #pragma optimize("", on)
5765 /* Load PNG image IMG for use on frame F. Value is non-zero if
5773 Lisp_Object file
, specified_file
;
5774 Lisp_Object specified_data
;
5776 XImagePtr ximg
, mask_img
= NULL
;
5777 struct gcpro gcpro1
;
5778 png_struct
*png_ptr
= NULL
;
5779 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5780 FILE *volatile fp
= NULL
;
5782 png_byte
* volatile pixels
= NULL
;
5783 png_byte
** volatile rows
= NULL
;
5784 png_uint_32 width
, height
;
5785 int bit_depth
, color_type
, interlace_type
;
5787 png_uint_32 row_bytes
;
5789 double screen_gamma
;
5790 struct png_memory_storage tbr
; /* Data to be read */
5792 /* Find out what file to load. */
5793 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5794 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5798 if (NILP (specified_data
))
5800 file
= x_find_image_file (specified_file
);
5801 if (!STRINGP (file
))
5803 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5808 /* Open the image file. */
5809 fp
= fopen (SDATA (file
), "rb");
5812 image_error ("Cannot open image file `%s'", file
, Qnil
);
5818 /* Check PNG signature. */
5819 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5820 || !fn_png_check_sig (sig
, sizeof sig
))
5822 image_error ("Not a PNG file: `%s'", file
, Qnil
);
5830 /* Read from memory. */
5831 tbr
.bytes
= SDATA (specified_data
);
5832 tbr
.len
= SBYTES (specified_data
);
5835 /* Check PNG signature. */
5836 if (tbr
.len
< sizeof sig
5837 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
5839 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
5844 /* Need to skip past the signature. */
5845 tbr
.bytes
+= sizeof (sig
);
5848 /* Initialize read and info structs for PNG lib. */
5849 png_ptr
= fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
5850 my_png_error
, my_png_warning
);
5853 if (fp
) fclose (fp
);
5858 info_ptr
= fn_png_create_info_struct (png_ptr
);
5861 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
5862 if (fp
) fclose (fp
);
5867 end_info
= fn_png_create_info_struct (png_ptr
);
5870 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
5871 if (fp
) fclose (fp
);
5876 /* Set error jump-back. We come back here when the PNG library
5877 detects an error. */
5878 if (setjmp (png_ptr
->jmpbuf
))
5882 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5885 if (fp
) fclose (fp
);
5890 /* Read image info. */
5891 if (!NILP (specified_data
))
5892 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
5894 fn_png_init_io (png_ptr
, fp
);
5896 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
5897 fn_png_read_info (png_ptr
, info_ptr
);
5898 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
5899 &interlace_type
, NULL
, NULL
);
5901 /* If image contains simply transparency data, we prefer to
5902 construct a clipping mask. */
5903 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
5908 /* This function is easier to write if we only have to handle
5909 one data format: RGB or RGBA with 8 bits per channel. Let's
5910 transform other formats into that format. */
5912 /* Strip more than 8 bits per channel. */
5913 if (bit_depth
== 16)
5914 fn_png_set_strip_16 (png_ptr
);
5916 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5918 fn_png_set_expand (png_ptr
);
5920 /* Convert grayscale images to RGB. */
5921 if (color_type
== PNG_COLOR_TYPE_GRAY
5922 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5923 fn_png_set_gray_to_rgb (png_ptr
);
5925 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
5927 #if 0 /* Avoid double gamma correction for PNG images. */
5928 { /* Tell the PNG lib to handle gamma correction for us. */
5931 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5932 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
5933 /* The libpng documentation says this is right in this case. */
5934 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5937 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
5938 /* Image contains gamma information. */
5939 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
5941 /* Use the standard default for the image gamma. */
5942 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5946 /* Handle alpha channel by combining the image with a background
5947 color. Do this only if a real alpha channel is supplied. For
5948 simple transparency, we prefer a clipping mask. */
5951 png_color_16
*image_bg
;
5952 Lisp_Object specified_bg
5953 = image_spec_value (img
->spec
, QCbackground
, NULL
);
5955 if (STRINGP (specified_bg
))
5956 /* The user specified `:background', use that. */
5958 /* W32 version incorrectly used COLORREF here!! ++kfs */
5960 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
5962 png_color_16 user_bg
;
5964 bzero (&user_bg
, sizeof user_bg
);
5965 user_bg
.red
= color
.red
>> 8;
5966 user_bg
.green
= color
.green
>> 8;
5967 user_bg
.blue
= color
.blue
>> 8;
5969 fn_png_set_background (png_ptr
, &user_bg
,
5970 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5973 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
5974 /* Image contains a background color with which to
5975 combine the image. */
5976 fn_png_set_background (png_ptr
, image_bg
,
5977 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
5980 /* Image does not contain a background color with which
5981 to combine the image data via an alpha channel. Use
5982 the frame's background instead. */
5983 #ifdef HAVE_X_WINDOWS
5985 png_color_16 frame_background
;
5987 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
5988 x_query_color (f
, &color
);
5990 bzero (&frame_background
, sizeof frame_background
);
5991 frame_background
.red
= color
.red
>> 8;
5992 frame_background
.green
= color
.green
>> 8;
5993 frame_background
.blue
= color
.blue
>> 8;
5994 #endif /* HAVE_X_WINDOWS */
5998 png_color_16 frame_background
;
5999 color
= FRAME_BACKGROUND_PIXEL (f
);
6000 #if 0 /* W32 TODO : Colormap support. */
6001 x_query_color (f
, &color
);
6003 bzero (&frame_background
, sizeof frame_background
);
6004 frame_background
.red
= GetRValue (color
);
6005 frame_background
.green
= GetGValue (color
);
6006 frame_background
.blue
= GetBValue (color
);
6007 #endif /* HAVE_NTGUI */
6010 unsigned long color
;
6011 png_color_16 frame_background
;
6012 color
= FRAME_BACKGROUND_PIXEL (f
);
6013 #if 0 /* MAC/W32 TODO : Colormap support. */
6014 x_query_color (f
, &color
);
6016 bzero (&frame_background
, sizeof frame_background
);
6017 frame_background
.red
= RED_FROM_ULONG (color
);
6018 frame_background
.green
= GREEN_FROM_ULONG (color
);
6019 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6022 fn_png_set_background (png_ptr
, &frame_background
,
6023 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6027 /* Update info structure. */
6028 fn_png_read_update_info (png_ptr
, info_ptr
);
6030 /* Get number of channels. Valid values are 1 for grayscale images
6031 and images with a palette, 2 for grayscale images with transparency
6032 information (alpha channel), 3 for RGB images, and 4 for RGB
6033 images with alpha channel, i.e. RGBA. If conversions above were
6034 sufficient we should only have 3 or 4 channels here. */
6035 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6036 xassert (channels
== 3 || channels
== 4);
6038 /* Number of bytes needed for one row of the image. */
6039 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6041 /* Allocate memory for the image. */
6042 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6043 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6044 for (i
= 0; i
< height
; ++i
)
6045 rows
[i
] = pixels
+ i
* row_bytes
;
6047 /* Read the entire image. */
6048 fn_png_read_image (png_ptr
, rows
);
6049 fn_png_read_end (png_ptr
, info_ptr
);
6056 /* Create the X image and pixmap. */
6057 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6061 /* Create an image and pixmap serving as mask if the PNG image
6062 contains an alpha channel. */
6065 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6066 &mask_img
, &img
->mask
))
6068 x_destroy_x_image (ximg
);
6069 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6070 img
->pixmap
= NO_PIXMAP
;
6074 /* Fill the X image and mask from PNG data. */
6075 init_color_table ();
6077 for (y
= 0; y
< height
; ++y
)
6079 png_byte
*p
= rows
[y
];
6081 for (x
= 0; x
< width
; ++x
)
6088 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6089 /* An alpha channel, aka mask channel, associates variable
6090 transparency with an image. Where other image formats
6091 support binary transparency---fully transparent or fully
6092 opaque---PNG allows up to 254 levels of partial transparency.
6093 The PNG library implements partial transparency by combining
6094 the image with a specified background color.
6096 I'm not sure how to handle this here nicely: because the
6097 background on which the image is displayed may change, for
6098 real alpha channel support, it would be necessary to create
6099 a new image for each possible background.
6101 What I'm doing now is that a mask is created if we have
6102 boolean transparency information. Otherwise I'm using
6103 the frame's background color to combine the image with. */
6108 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
6114 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6115 /* Set IMG's background color from the PNG image, unless the user
6119 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6121 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6122 img
->background_valid
= 1;
6126 #ifdef COLOR_TABLE_SUPPORT
6127 /* Remember colors allocated for this image. */
6128 img
->colors
= colors_in_color_table (&img
->ncolors
);
6129 free_color_table ();
6130 #endif /* COLOR_TABLE_SUPPORT */
6133 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6138 img
->height
= height
;
6140 /* Maybe fill in the background field while we have ximg handy. */
6141 IMAGE_BACKGROUND (img
, f
, ximg
);
6143 /* Put the image into the pixmap, then free the X image and its buffer. */
6144 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6145 x_destroy_x_image (ximg
);
6147 /* Same for the mask. */
6150 /* Fill in the background_transparent field while we have the mask
6152 image_background_transparent (img
, f
, mask_img
);
6154 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6155 x_destroy_x_image (mask_img
);
6162 #else /* HAVE_PNG */
6171 if (MyCGImageCreateWithPNGDataProvider
)
6172 return image_load_quartz2d (f
, img
, 1);
6175 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6179 #endif /* !HAVE_PNG */
6183 /***********************************************************************
6185 ***********************************************************************/
6187 #if defined (HAVE_JPEG) || defined (MAC_OS)
6189 static int jpeg_image_p
P_ ((Lisp_Object object
));
6190 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6192 /* The symbol `jpeg' identifying images of this type. */
6196 /* Indices of image specification fields in gs_format, below. */
6198 enum jpeg_keyword_index
6207 JPEG_HEURISTIC_MASK
,
6213 /* Vector of image_keyword structures describing the format
6214 of valid user-defined image specifications. */
6216 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6218 {":type", IMAGE_SYMBOL_VALUE
, 1},
6219 {":data", IMAGE_STRING_VALUE
, 0},
6220 {":file", IMAGE_STRING_VALUE
, 0},
6221 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6222 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6223 {":relief", IMAGE_INTEGER_VALUE
, 0},
6224 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6225 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6226 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6227 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6230 /* Structure describing the image type `jpeg'. */
6232 static struct image_type jpeg_type
=
6241 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6244 jpeg_image_p (object
)
6247 struct image_keyword fmt
[JPEG_LAST
];
6249 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6251 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6254 /* Must specify either the :data or :file keyword. */
6255 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6258 #endif /* HAVE_JPEG || MAC_OS */
6262 /* Work around a warning about HAVE_STDLIB_H being redefined in
6264 #ifdef HAVE_STDLIB_H
6265 #define HAVE_STDLIB_H_1
6266 #undef HAVE_STDLIB_H
6267 #endif /* HAVE_STLIB_H */
6269 #include <jpeglib.h>
6273 #ifdef HAVE_STLIB_H_1
6274 #define HAVE_STDLIB_H 1
6279 /* JPEG library details. */
6280 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6281 DEF_IMGLIB_FN (jpeg_start_decompress
);
6282 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6283 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6284 DEF_IMGLIB_FN (jpeg_read_header
);
6285 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6286 DEF_IMGLIB_FN (jpeg_stdio_src
);
6287 DEF_IMGLIB_FN (jpeg_std_error
);
6288 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6291 init_jpeg_functions (Lisp_Object libraries
)
6295 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6298 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6299 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6300 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6301 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6302 LOAD_IMGLIB_FN (library
, jpeg_stdio_src
);
6303 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6304 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6305 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6306 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6310 /* Wrapper since we can't directly assign the function pointer
6311 to another function pointer that was declared more completely easily. */
6313 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
6314 j_decompress_ptr cinfo
;
6317 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6322 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6323 #define fn_jpeg_start_decompress jpeg_start_decompress
6324 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6325 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6326 #define fn_jpeg_read_header jpeg_read_header
6327 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6328 #define fn_jpeg_stdio_src jpeg_stdio_src
6329 #define fn_jpeg_std_error jpeg_std_error
6330 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6332 #endif /* HAVE_NTGUI */
6334 struct my_jpeg_error_mgr
6336 struct jpeg_error_mgr pub
;
6337 jmp_buf setjmp_buffer
;
6342 my_error_exit (cinfo
)
6345 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6346 longjmp (mgr
->setjmp_buffer
, 1);
6350 /* Init source method for JPEG data source manager. Called by
6351 jpeg_read_header() before any data is actually read. See
6352 libjpeg.doc from the JPEG lib distribution. */
6355 our_init_source (cinfo
)
6356 j_decompress_ptr cinfo
;
6361 /* Fill input buffer method for JPEG data source manager. Called
6362 whenever more data is needed. We read the whole image in one step,
6363 so this only adds a fake end of input marker at the end. */
6366 our_fill_input_buffer (cinfo
)
6367 j_decompress_ptr cinfo
;
6369 /* Insert a fake EOI marker. */
6370 struct jpeg_source_mgr
*src
= cinfo
->src
;
6371 static JOCTET buffer
[2];
6373 buffer
[0] = (JOCTET
) 0xFF;
6374 buffer
[1] = (JOCTET
) JPEG_EOI
;
6376 src
->next_input_byte
= buffer
;
6377 src
->bytes_in_buffer
= 2;
6382 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6383 is the JPEG data source manager. */
6386 our_skip_input_data (cinfo
, num_bytes
)
6387 j_decompress_ptr cinfo
;
6390 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6394 if (num_bytes
> src
->bytes_in_buffer
)
6395 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6397 src
->bytes_in_buffer
-= num_bytes
;
6398 src
->next_input_byte
+= num_bytes
;
6403 /* Method to terminate data source. Called by
6404 jpeg_finish_decompress() after all data has been processed. */
6407 our_term_source (cinfo
)
6408 j_decompress_ptr cinfo
;
6413 /* Set up the JPEG lib for reading an image from DATA which contains
6414 LEN bytes. CINFO is the decompression info structure created for
6415 reading the image. */
6418 jpeg_memory_src (cinfo
, data
, len
)
6419 j_decompress_ptr cinfo
;
6423 struct jpeg_source_mgr
*src
;
6425 if (cinfo
->src
== NULL
)
6427 /* First time for this JPEG object? */
6428 cinfo
->src
= (struct jpeg_source_mgr
*)
6429 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6430 sizeof (struct jpeg_source_mgr
));
6431 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6432 src
->next_input_byte
= data
;
6435 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6436 src
->init_source
= our_init_source
;
6437 src
->fill_input_buffer
= our_fill_input_buffer
;
6438 src
->skip_input_data
= our_skip_input_data
;
6439 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6440 src
->term_source
= our_term_source
;
6441 src
->bytes_in_buffer
= len
;
6442 src
->next_input_byte
= data
;
6446 /* Load image IMG for use on frame F. Patterned after example.c
6447 from the JPEG lib. */
6454 struct jpeg_decompress_struct cinfo
;
6455 struct my_jpeg_error_mgr mgr
;
6456 Lisp_Object file
, specified_file
;
6457 Lisp_Object specified_data
;
6458 FILE * volatile fp
= NULL
;
6460 int row_stride
, x
, y
;
6461 XImagePtr ximg
= NULL
;
6463 unsigned long *colors
;
6465 struct gcpro gcpro1
;
6467 /* Open the JPEG file. */
6468 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6469 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6473 if (NILP (specified_data
))
6475 file
= x_find_image_file (specified_file
);
6476 if (!STRINGP (file
))
6478 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6483 fp
= fopen (SDATA (file
), "rb");
6486 image_error ("Cannot open `%s'", file
, Qnil
);
6492 /* Customize libjpeg's error handling to call my_error_exit when an
6493 error is detected. This function will perform a longjmp. */
6494 cinfo
.err
= fn_jpeg_std_error (&mgr
.pub
);
6495 mgr
.pub
.error_exit
= my_error_exit
;
6497 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6501 /* Called from my_error_exit. Display a JPEG error. */
6502 char buffer
[JMSG_LENGTH_MAX
];
6503 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6504 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6505 build_string (buffer
));
6508 /* Close the input file and destroy the JPEG object. */
6510 fclose ((FILE *) fp
);
6511 fn_jpeg_destroy_decompress (&cinfo
);
6513 /* If we already have an XImage, free that. */
6514 x_destroy_x_image (ximg
);
6516 /* Free pixmap and colors. */
6517 x_clear_image (f
, img
);
6523 /* Create the JPEG decompression object. Let it read from fp.
6524 Read the JPEG image header. */
6525 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6527 if (NILP (specified_data
))
6528 fn_jpeg_stdio_src (&cinfo
, (FILE *) fp
);
6530 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6531 SBYTES (specified_data
));
6533 fn_jpeg_read_header (&cinfo
, TRUE
);
6535 /* Customize decompression so that color quantization will be used.
6536 Start decompression. */
6537 cinfo
.quantize_colors
= TRUE
;
6538 fn_jpeg_start_decompress (&cinfo
);
6539 width
= img
->width
= cinfo
.output_width
;
6540 height
= img
->height
= cinfo
.output_height
;
6542 /* Create X image and pixmap. */
6543 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6544 longjmp (mgr
.setjmp_buffer
, 2);
6546 /* Allocate colors. When color quantization is used,
6547 cinfo.actual_number_of_colors has been set with the number of
6548 colors generated, and cinfo.colormap is a two-dimensional array
6549 of color indices in the range 0..cinfo.actual_number_of_colors.
6550 No more than 255 colors will be generated. */
6554 if (cinfo
.out_color_components
> 2)
6555 ir
= 0, ig
= 1, ib
= 2;
6556 else if (cinfo
.out_color_components
> 1)
6557 ir
= 0, ig
= 1, ib
= 0;
6559 ir
= 0, ig
= 0, ib
= 0;
6561 /* Use the color table mechanism because it handles colors that
6562 cannot be allocated nicely. Such colors will be replaced with
6563 a default color, and we don't have to care about which colors
6564 can be freed safely, and which can't. */
6565 init_color_table ();
6566 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6569 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6571 /* Multiply RGB values with 255 because X expects RGB values
6572 in the range 0..0xffff. */
6573 int r
= cinfo
.colormap
[ir
][i
] << 8;
6574 int g
= cinfo
.colormap
[ig
][i
] << 8;
6575 int b
= cinfo
.colormap
[ib
][i
] << 8;
6576 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6579 #ifdef COLOR_TABLE_SUPPORT
6580 /* Remember those colors actually allocated. */
6581 img
->colors
= colors_in_color_table (&img
->ncolors
);
6582 free_color_table ();
6583 #endif /* COLOR_TABLE_SUPPORT */
6587 row_stride
= width
* cinfo
.output_components
;
6588 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6590 for (y
= 0; y
< height
; ++y
)
6592 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6593 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6594 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6598 fn_jpeg_finish_decompress (&cinfo
);
6599 fn_jpeg_destroy_decompress (&cinfo
);
6601 fclose ((FILE *) fp
);
6603 /* Maybe fill in the background field while we have ximg handy. */
6604 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6605 IMAGE_BACKGROUND (img
, f
, ximg
);
6607 /* Put the image into the pixmap. */
6608 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6609 x_destroy_x_image (ximg
);
6614 #else /* HAVE_JPEG */
6623 return image_load_quartz2d (f
, img
, 0);
6625 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
6630 #endif /* !HAVE_JPEG */
6634 /***********************************************************************
6636 ***********************************************************************/
6638 #if defined (HAVE_TIFF) || defined (MAC_OS)
6640 static int tiff_image_p
P_ ((Lisp_Object object
));
6641 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6643 /* The symbol `tiff' identifying images of this type. */
6647 /* Indices of image specification fields in tiff_format, below. */
6649 enum tiff_keyword_index
6658 TIFF_HEURISTIC_MASK
,
6664 /* Vector of image_keyword structures describing the format
6665 of valid user-defined image specifications. */
6667 static struct image_keyword tiff_format
[TIFF_LAST
] =
6669 {":type", IMAGE_SYMBOL_VALUE
, 1},
6670 {":data", IMAGE_STRING_VALUE
, 0},
6671 {":file", IMAGE_STRING_VALUE
, 0},
6672 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6673 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6674 {":relief", IMAGE_INTEGER_VALUE
, 0},
6675 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6676 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6677 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6678 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6681 /* Structure describing the image type `tiff'. */
6683 static struct image_type tiff_type
=
6692 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6695 tiff_image_p (object
)
6698 struct image_keyword fmt
[TIFF_LAST
];
6699 bcopy (tiff_format
, fmt
, sizeof fmt
);
6701 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6704 /* Must specify either the :data or :file keyword. */
6705 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6708 #endif /* HAVE_TIFF || MAC_OS */
6716 /* TIFF library details. */
6717 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6718 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6719 DEF_IMGLIB_FN (TIFFOpen
);
6720 DEF_IMGLIB_FN (TIFFClientOpen
);
6721 DEF_IMGLIB_FN (TIFFGetField
);
6722 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6723 DEF_IMGLIB_FN (TIFFClose
);
6726 init_tiff_functions (Lisp_Object libraries
)
6730 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
6733 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6734 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6735 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6736 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6737 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6738 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6739 LOAD_IMGLIB_FN (library
, TIFFClose
);
6745 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6746 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6747 #define fn_TIFFOpen TIFFOpen
6748 #define fn_TIFFClientOpen TIFFClientOpen
6749 #define fn_TIFFGetField TIFFGetField
6750 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6751 #define fn_TIFFClose TIFFClose
6753 #endif /* HAVE_NTGUI */
6756 /* Reading from a memory buffer for TIFF images Based on the PNG
6757 memory source, but we have to provide a lot of extra functions.
6760 We really only need to implement read and seek, but I am not
6761 convinced that the TIFF library is smart enough not to destroy
6762 itself if we only hand it the function pointers we need to
6767 unsigned char *bytes
;
6774 tiff_read_from_memory (data
, buf
, size
)
6779 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6781 if (size
> src
->len
- src
->index
)
6783 bcopy (src
->bytes
+ src
->index
, buf
, size
);
6789 tiff_write_from_memory (data
, buf
, size
)
6798 tiff_seek_in_memory (data
, off
, whence
)
6803 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6808 case SEEK_SET
: /* Go from beginning of source. */
6812 case SEEK_END
: /* Go from end of source. */
6813 idx
= src
->len
+ off
;
6816 case SEEK_CUR
: /* Go from current position. */
6817 idx
= src
->index
+ off
;
6820 default: /* Invalid `whence'. */
6824 if (idx
> src
->len
|| idx
< 0)
6832 tiff_close_memory (data
)
6840 tiff_mmap_memory (data
, pbase
, psize
)
6845 /* It is already _IN_ memory. */
6850 tiff_unmap_memory (data
, base
, size
)
6855 /* We don't need to do this. */
6859 tiff_size_of_memory (data
)
6862 return ((tiff_memory_source
*) data
)->len
;
6867 tiff_error_handler (title
, format
, ap
)
6868 const char *title
, *format
;
6874 len
= sprintf (buf
, "TIFF error: %s ", title
);
6875 vsprintf (buf
+ len
, format
, ap
);
6876 add_to_log (buf
, Qnil
, Qnil
);
6881 tiff_warning_handler (title
, format
, ap
)
6882 const char *title
, *format
;
6888 len
= sprintf (buf
, "TIFF warning: %s ", title
);
6889 vsprintf (buf
+ len
, format
, ap
);
6890 add_to_log (buf
, Qnil
, Qnil
);
6894 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6902 Lisp_Object file
, specified_file
;
6903 Lisp_Object specified_data
;
6905 int width
, height
, x
, y
;
6909 struct gcpro gcpro1
;
6910 tiff_memory_source memsrc
;
6912 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6913 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6917 fn_TIFFSetErrorHandler (tiff_error_handler
);
6918 fn_TIFFSetWarningHandler (tiff_warning_handler
);
6920 if (NILP (specified_data
))
6922 /* Read from a file */
6923 file
= x_find_image_file (specified_file
);
6924 if (!STRINGP (file
))
6926 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6931 /* Try to open the image file. */
6932 tiff
= fn_TIFFOpen (SDATA (file
), "r");
6935 image_error ("Cannot open `%s'", file
, Qnil
);
6942 /* Memory source! */
6943 memsrc
.bytes
= SDATA (specified_data
);
6944 memsrc
.len
= SBYTES (specified_data
);
6947 tiff
= fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
6948 (TIFFReadWriteProc
) tiff_read_from_memory
,
6949 (TIFFReadWriteProc
) tiff_write_from_memory
,
6950 tiff_seek_in_memory
,
6952 tiff_size_of_memory
,
6958 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
6964 /* Get width and height of the image, and allocate a raster buffer
6965 of width x height 32-bit values. */
6966 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
6967 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
6968 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
6970 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
6971 fn_TIFFClose (tiff
);
6974 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
6980 /* Create the X image and pixmap. */
6981 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6988 /* Initialize the color table. */
6989 init_color_table ();
6991 /* Process the pixel raster. Origin is in the lower-left corner. */
6992 for (y
= 0; y
< height
; ++y
)
6994 uint32
*row
= buf
+ y
* width
;
6996 for (x
= 0; x
< width
; ++x
)
6998 uint32 abgr
= row
[x
];
6999 int r
= TIFFGetR (abgr
) << 8;
7000 int g
= TIFFGetG (abgr
) << 8;
7001 int b
= TIFFGetB (abgr
) << 8;
7002 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7006 #ifdef COLOR_TABLE_SUPPORT
7007 /* Remember the colors allocated for the image. Free the color table. */
7008 img
->colors
= colors_in_color_table (&img
->ncolors
);
7009 free_color_table ();
7010 #endif /* COLOR_TABLE_SUPPORT */
7013 img
->height
= height
;
7015 /* Maybe fill in the background field while we have ximg handy. */
7016 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7017 IMAGE_BACKGROUND (img
, f
, ximg
);
7019 /* Put the image into the pixmap, then free the X image and its buffer. */
7020 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7021 x_destroy_x_image (ximg
);
7028 #else /* HAVE_TIFF */
7036 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7040 #endif /* !HAVE_TIFF */
7044 /***********************************************************************
7046 ***********************************************************************/
7048 #if defined (HAVE_GIF) || defined (MAC_OS)
7050 static int gif_image_p
P_ ((Lisp_Object object
));
7051 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7053 /* The symbol `gif' identifying images of this type. */
7057 /* Indices of image specification fields in gif_format, below. */
7059 enum gif_keyword_index
7075 /* Vector of image_keyword structures describing the format
7076 of valid user-defined image specifications. */
7078 static struct image_keyword gif_format
[GIF_LAST
] =
7080 {":type", IMAGE_SYMBOL_VALUE
, 1},
7081 {":data", IMAGE_STRING_VALUE
, 0},
7082 {":file", IMAGE_STRING_VALUE
, 0},
7083 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7084 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7085 {":relief", IMAGE_INTEGER_VALUE
, 0},
7086 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7087 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7088 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7089 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7090 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7093 /* Structure describing the image type `gif'. */
7095 static struct image_type gif_type
=
7104 /* Return non-zero if OBJECT is a valid GIF image specification. */
7107 gif_image_p (object
)
7110 struct image_keyword fmt
[GIF_LAST
];
7111 bcopy (gif_format
, fmt
, sizeof fmt
);
7113 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7116 /* Must specify either the :data or :file keyword. */
7117 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7120 #endif /* HAVE_GIF || MAC_OS */
7124 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7125 /* avoid conflict with QuickdrawText.h */
7126 #define DrawText gif_DrawText
7127 #include <gif_lib.h>
7130 #else /* HAVE_NTGUI || MAC_OS */
7132 #include <gif_lib.h>
7134 #endif /* HAVE_NTGUI || MAC_OS */
7139 /* GIF library details. */
7140 DEF_IMGLIB_FN (DGifCloseFile
);
7141 DEF_IMGLIB_FN (DGifSlurp
);
7142 DEF_IMGLIB_FN (DGifOpen
);
7143 DEF_IMGLIB_FN (DGifOpenFileName
);
7146 init_gif_functions (Lisp_Object libraries
)
7150 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7153 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7154 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7155 LOAD_IMGLIB_FN (library
, DGifOpen
);
7156 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7162 #define fn_DGifCloseFile DGifCloseFile
7163 #define fn_DGifSlurp DGifSlurp
7164 #define fn_DGifOpen DGifOpen
7165 #define fn_DGifOpenFileName DGifOpenFileName
7167 #endif /* HAVE_NTGUI */
7169 /* Reading a GIF image from memory
7170 Based on the PNG memory stuff to a certain extent. */
7174 unsigned char *bytes
;
7180 /* Make the current memory source available to gif_read_from_memory.
7181 It's done this way because not all versions of libungif support
7182 a UserData field in the GifFileType structure. */
7183 static gif_memory_source
*current_gif_memory_src
;
7186 gif_read_from_memory (file
, buf
, len
)
7191 gif_memory_source
*src
= current_gif_memory_src
;
7193 if (len
> src
->len
- src
->index
)
7196 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7202 /* Load GIF image IMG for use on frame F. Value is non-zero if
7210 Lisp_Object file
, specified_file
;
7211 Lisp_Object specified_data
;
7212 int rc
, width
, height
, x
, y
, i
;
7214 ColorMapObject
*gif_color_map
;
7215 unsigned long pixel_colors
[256];
7217 struct gcpro gcpro1
;
7219 int ino
, image_left
, image_top
, image_width
, image_height
;
7220 gif_memory_source memsrc
;
7221 unsigned char *raster
;
7223 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7224 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7228 if (NILP (specified_data
))
7230 file
= x_find_image_file (specified_file
);
7231 if (!STRINGP (file
))
7233 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7238 /* Open the GIF file. */
7239 gif
= fn_DGifOpenFileName (SDATA (file
));
7242 image_error ("Cannot open `%s'", file
, Qnil
);
7249 /* Read from memory! */
7250 current_gif_memory_src
= &memsrc
;
7251 memsrc
.bytes
= SDATA (specified_data
);
7252 memsrc
.len
= SBYTES (specified_data
);
7255 gif
= fn_DGifOpen(&memsrc
, gif_read_from_memory
);
7258 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7264 /* Read entire contents. */
7265 rc
= fn_DGifSlurp (gif
);
7266 if (rc
== GIF_ERROR
)
7268 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7269 fn_DGifCloseFile (gif
);
7274 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7275 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7276 if (ino
>= gif
->ImageCount
)
7278 image_error ("Invalid image number `%s' in image `%s'",
7280 fn_DGifCloseFile (gif
);
7285 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
7286 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
7288 /* Create the X image and pixmap. */
7289 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7291 fn_DGifCloseFile (gif
);
7296 /* Allocate colors. */
7297 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7299 gif_color_map
= gif
->SColorMap
;
7300 init_color_table ();
7301 bzero (pixel_colors
, sizeof pixel_colors
);
7303 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7305 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7306 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7307 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7308 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7311 #ifdef COLOR_TABLE_SUPPORT
7312 img
->colors
= colors_in_color_table (&img
->ncolors
);
7313 free_color_table ();
7314 #endif /* COLOR_TABLE_SUPPORT */
7316 /* Clear the part of the screen image that are not covered by
7317 the image from the GIF file. Full animated GIF support
7318 requires more than can be done here (see the gif89 spec,
7319 disposal methods). Let's simply assume that the part
7320 not covered by a sub-image is in the frame's background color. */
7321 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
7322 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
7323 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7324 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7326 for (y
= 0; y
< image_top
; ++y
)
7327 for (x
= 0; x
< width
; ++x
)
7328 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7330 for (y
= image_top
+ image_height
; y
< height
; ++y
)
7331 for (x
= 0; x
< width
; ++x
)
7332 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7334 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
7336 for (x
= 0; x
< image_left
; ++x
)
7337 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7338 for (x
= image_left
+ image_width
; x
< width
; ++x
)
7339 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7342 /* Read the GIF image into the X image. We use a local variable
7343 `raster' here because RasterBits below is a char *, and invites
7344 problems with bytes >= 0x80. */
7345 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7347 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7349 static int interlace_start
[] = {0, 4, 2, 1};
7350 static int interlace_increment
[] = {8, 8, 4, 2};
7352 int row
= interlace_start
[0];
7356 for (y
= 0; y
< image_height
; y
++)
7358 if (row
>= image_height
)
7360 row
= interlace_start
[++pass
];
7361 while (row
>= image_height
)
7362 row
= interlace_start
[++pass
];
7365 for (x
= 0; x
< image_width
; x
++)
7367 int i
= raster
[(y
* image_width
) + x
];
7368 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
7372 row
+= interlace_increment
[pass
];
7377 for (y
= 0; y
< image_height
; ++y
)
7378 for (x
= 0; x
< image_width
; ++x
)
7380 int i
= raster
[y
* image_width
+ x
];
7381 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
7385 fn_DGifCloseFile (gif
);
7387 /* Maybe fill in the background field while we have ximg handy. */
7388 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7389 IMAGE_BACKGROUND (img
, f
, ximg
);
7391 /* Put the image into the pixmap, then free the X image and its buffer. */
7392 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7393 x_destroy_x_image (ximg
);
7407 Lisp_Object specified_file
, file
;
7408 Lisp_Object specified_data
;
7410 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
7418 Lisp_Object specified_bg
;
7424 struct gcpro gcpro1
;
7429 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7430 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7432 if (NILP (specified_data
))
7434 /* Read from a file */
7438 err
= find_image_fsspec (specified_file
, &file
, &fss
);
7442 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7447 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
7448 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
7452 if (!graphic_p
&& !movie_p
)
7454 if (prefer_graphic_p
)
7455 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
7456 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
7459 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
7460 CloseMovieFile (refnum
);
7463 image_error ("Error reading `%s'", file
, Qnil
);
7469 /* Memory source! */
7471 long file_type_atom
[3];
7473 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
7476 image_error ("Cannot allocate data handle for `%s'",
7481 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
7482 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
7483 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
7484 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
7487 err
= PtrAndHand ("\p", dref
, 1);
7489 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
7492 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
7495 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
7496 &movie_p
, &prefer_graphic_p
, 0);
7500 if (!graphic_p
&& !movie_p
)
7502 if (prefer_graphic_p
)
7506 DisposeHandle (dref
);
7507 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
7511 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
7512 HandleDataHandlerSubType
);
7513 DisposeHandle (dref
);
7518 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7519 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7520 track
= GetMovieIndTrack (movie
, 1);
7521 media
= GetTrackMedia (track
);
7522 nsamples
= GetMediaSampleCount (media
);
7523 if (ino
>= nsamples
)
7525 image_error ("Invalid image number `%s' in image `%s'",
7530 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7531 if (!STRINGP (specified_bg
) ||
7532 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
7534 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
7535 color
.red
= RED16_FROM_ULONG (color
.pixel
);
7536 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
7537 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
7539 GetMovieBox (movie
, &rect
);
7540 width
= img
->width
= rect
.right
- rect
.left
;
7541 height
= img
->height
= rect
.bottom
- rect
.top
;
7542 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7545 GetGWorld (&old_port
, &old_gdh
);
7546 SetGWorld (ximg
, NULL
);
7547 bg_color
.red
= color
.red
;
7548 bg_color
.green
= color
.green
;
7549 bg_color
.blue
= color
.blue
;
7550 RGBBackColor (&bg_color
);
7551 SetGWorld (old_port
, old_gdh
);
7552 SetMovieActive (movie
, TRUE
);
7553 SetMovieGWorld (movie
, ximg
, NULL
);
7554 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7555 SetMovieTimeValue (movie
, time
);
7556 MoviesTask (movie
, 0L);
7557 DisposeTrackMedia (media
);
7558 DisposeMovieTrack (track
);
7559 DisposeMovie (movie
);
7562 /* Maybe fill in the background field while we have ximg handy. */
7563 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7564 IMAGE_BACKGROUND (img
, f
, ximg
);
7566 /* Put the image into the pixmap. */
7567 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7568 x_destroy_x_image (ximg
);
7572 image_error ("Cannot open `%s'", file
, Qnil
);
7575 DisposeTrackMedia (media
);
7577 DisposeMovieTrack (track
);
7579 DisposeMovie (movie
);
7586 #endif /* HAVE_GIF */
7590 /***********************************************************************
7592 ***********************************************************************/
7594 #ifdef HAVE_X_WINDOWS
7595 #define HAVE_GHOSTSCRIPT 1
7596 #endif /* HAVE_X_WINDOWS */
7598 /* The symbol `postscript' identifying images of this type. */
7600 Lisp_Object Qpostscript
;
7602 #ifdef HAVE_GHOSTSCRIPT
7604 static int gs_image_p
P_ ((Lisp_Object object
));
7605 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
7606 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7608 /* Keyword symbols. */
7610 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
7612 /* Indices of image specification fields in gs_format, below. */
7614 enum gs_keyword_index
7632 /* Vector of image_keyword structures describing the format
7633 of valid user-defined image specifications. */
7635 static struct image_keyword gs_format
[GS_LAST
] =
7637 {":type", IMAGE_SYMBOL_VALUE
, 1},
7638 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7639 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7640 {":file", IMAGE_STRING_VALUE
, 1},
7641 {":loader", IMAGE_FUNCTION_VALUE
, 0},
7642 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
7643 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7644 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7645 {":relief", IMAGE_INTEGER_VALUE
, 0},
7646 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7647 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7648 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7649 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7652 /* Structure describing the image type `ghostscript'. */
7654 static struct image_type gs_type
=
7664 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7667 gs_clear_image (f
, img
)
7671 /* IMG->data.ptr_val may contain a recorded colormap. */
7672 xfree (img
->data
.ptr_val
);
7673 x_clear_image (f
, img
);
7677 /* Return non-zero if OBJECT is a valid Ghostscript image
7684 struct image_keyword fmt
[GS_LAST
];
7688 bcopy (gs_format
, fmt
, sizeof fmt
);
7690 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
7693 /* Bounding box must be a list or vector containing 4 integers. */
7694 tem
= fmt
[GS_BOUNDING_BOX
].value
;
7697 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
7698 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
7703 else if (VECTORP (tem
))
7705 if (XVECTOR (tem
)->size
!= 4)
7707 for (i
= 0; i
< 4; ++i
)
7708 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
7718 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7727 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
7728 struct gcpro gcpro1
, gcpro2
;
7730 double in_width
, in_height
;
7731 Lisp_Object pixel_colors
= Qnil
;
7733 /* Compute pixel size of pixmap needed from the given size in the
7734 image specification. Sizes in the specification are in pt. 1 pt
7735 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7737 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
7738 in_width
= XFASTINT (pt_width
) / 72.0;
7739 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
7740 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
7741 in_height
= XFASTINT (pt_height
) / 72.0;
7742 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
7744 /* Create the pixmap. */
7745 xassert (img
->pixmap
== NO_PIXMAP
);
7747 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7749 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7750 img
->width
, img
->height
,
7751 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
7756 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
7760 /* Call the loader to fill the pixmap. It returns a process object
7761 if successful. We do not record_unwind_protect here because
7762 other places in redisplay like calling window scroll functions
7763 don't either. Let the Lisp loader use `unwind-protect' instead. */
7764 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
7766 sprintf (buffer
, "%lu %lu",
7767 (unsigned long) FRAME_X_WINDOW (f
),
7768 (unsigned long) img
->pixmap
);
7769 window_and_pixmap_id
= build_string (buffer
);
7771 sprintf (buffer
, "%lu %lu",
7772 FRAME_FOREGROUND_PIXEL (f
),
7773 FRAME_BACKGROUND_PIXEL (f
));
7774 pixel_colors
= build_string (buffer
);
7776 XSETFRAME (frame
, f
);
7777 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
7779 loader
= intern ("gs-load-image");
7781 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
7782 make_number (img
->width
),
7783 make_number (img
->height
),
7784 window_and_pixmap_id
,
7787 return PROCESSP (img
->data
.lisp_val
);
7791 /* Kill the Ghostscript process that was started to fill PIXMAP on
7792 frame F. Called from XTread_socket when receiving an event
7793 telling Emacs that Ghostscript has finished drawing. */
7796 x_kill_gs_process (pixmap
, f
)
7800 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7804 /* Find the image containing PIXMAP. */
7805 for (i
= 0; i
< c
->used
; ++i
)
7806 if (c
->images
[i
]->pixmap
== pixmap
)
7809 /* Should someone in between have cleared the image cache, for
7810 instance, give up. */
7814 /* Kill the GS process. We should have found PIXMAP in the image
7815 cache and its image should contain a process object. */
7817 xassert (PROCESSP (img
->data
.lisp_val
));
7818 Fkill_process (img
->data
.lisp_val
, Qnil
);
7819 img
->data
.lisp_val
= Qnil
;
7821 #if defined (HAVE_X_WINDOWS)
7823 /* On displays with a mutable colormap, figure out the colors
7824 allocated for the image by looking at the pixels of an XImage for
7826 class = FRAME_X_VISUAL (f
)->class;
7827 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
7833 /* Try to get an XImage for img->pixmep. */
7834 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7835 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7840 /* Initialize the color table. */
7841 init_color_table ();
7843 /* For each pixel of the image, look its color up in the
7844 color table. After having done so, the color table will
7845 contain an entry for each color used by the image. */
7846 for (y
= 0; y
< img
->height
; ++y
)
7847 for (x
= 0; x
< img
->width
; ++x
)
7849 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
7850 lookup_pixel_color (f
, pixel
);
7853 /* Record colors in the image. Free color table and XImage. */
7854 #ifdef COLOR_TABLE_SUPPORT
7855 img
->colors
= colors_in_color_table (&img
->ncolors
);
7856 free_color_table ();
7858 XDestroyImage (ximg
);
7860 #if 0 /* This doesn't seem to be the case. If we free the colors
7861 here, we get a BadAccess later in x_clear_image when
7862 freeing the colors. */
7863 /* We have allocated colors once, but Ghostscript has also
7864 allocated colors on behalf of us. So, to get the
7865 reference counts right, free them once. */
7867 x_free_colors (f
, img
->colors
, img
->ncolors
);
7871 image_error ("Cannot get X image of `%s'; colors will not be freed",
7876 #endif /* HAVE_X_WINDOWS */
7878 /* Now that we have the pixmap, compute mask and transform the
7879 image if requested. */
7881 postprocess_image (f
, img
);
7885 #endif /* HAVE_GHOSTSCRIPT */
7888 /***********************************************************************
7890 ***********************************************************************/
7894 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
7895 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
7899 return valid_image_p (spec
) ? Qt
: Qnil
;
7903 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
7909 if (valid_image_p (spec
))
7910 id
= lookup_image (SELECTED_FRAME (), spec
);
7913 return make_number (id
);
7916 #endif /* GLYPH_DEBUG != 0 */
7919 /***********************************************************************
7921 ***********************************************************************/
7924 /* Image types that rely on external libraries are loaded dynamically
7925 if the library is available. */
7926 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \
7927 define_image_type (image_type, init_lib_fn (libraries))
7929 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \
7930 define_image_type (image_type, TRUE)
7931 #endif /* HAVE_NTGUI */
7933 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
7934 doc
: /* Initialize image library implementing image type TYPE.
7935 Return non-nil if TYPE is a supported image type.
7937 Image types pbm and xbm are prebuilt; other types are loaded here.
7938 Libraries to load are specified in alist LIBRARIES (usually, the value
7939 of `image-library-alist', which see. */)
7944 /* Don't try to reload the library. */
7945 tested
= Fassq (type
, Vimage_type_cache
);
7947 return XCDR (tested
);
7949 #if defined (HAVE_XPM) || defined (MAC_OS)
7950 if (EQ (type
, Qxpm
))
7951 return CHECK_LIB_AVAILABLE(&xpm_type
, init_xpm_functions
);
7954 #if defined (HAVE_JPEG) || defined (MAC_OS)
7955 if (EQ (type
, Qjpeg
))
7956 return CHECK_LIB_AVAILABLE(&jpeg_type
, init_jpeg_functions
);
7959 #if defined (HAVE_TIFF) || defined (MAC_OS)
7960 if (EQ (type
, Qtiff
))
7961 return CHECK_LIB_AVAILABLE(&tiff_type
, init_tiff_functions
);
7964 #if defined (HAVE_GIF) || defined (MAC_OS)
7965 if (EQ (type
, Qgif
))
7966 return CHECK_LIB_AVAILABLE(&gif_type
, init_gif_functions
);
7969 #if defined (HAVE_PNG) || defined (MAC_OS)
7970 if (EQ (type
, Qpng
))
7971 return CHECK_LIB_AVAILABLE(&png_type
, init_png_functions
);
7974 #ifdef HAVE_GHOSTSCRIPT
7975 if (EQ (type
, Qpostscript
))
7976 return CHECK_LIB_AVAILABLE(&gs_type
, init_gs_functions
);
7979 /* If the type is not recognized, avoid testing it ever again. */
7980 CACHE_IMAGE_TYPE(type
, Qnil
);
7987 /* Must be defined now becase we're going to update it below, while
7988 defining the supported image types. */
7989 DEFVAR_LISP ("image-types", &Vimage_types
,
7990 doc
: /* List of potentially supported image types.
7991 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
7992 To check whether it is really supported, use `image-type-available-p'. */);
7993 Vimage_types
= Qnil
;
7995 Vimage_type_cache
= Qnil
;
7996 staticpro (&Vimage_type_cache
);
7998 QCascent
= intern (":ascent");
7999 staticpro (&QCascent
);
8000 QCmargin
= intern (":margin");
8001 staticpro (&QCmargin
);
8002 QCrelief
= intern (":relief");
8003 staticpro (&QCrelief
);
8004 QCconversion
= intern (":conversion");
8005 staticpro (&QCconversion
);
8006 QCcolor_symbols
= intern (":color-symbols");
8007 staticpro (&QCcolor_symbols
);
8008 QCheuristic_mask
= intern (":heuristic-mask");
8009 staticpro (&QCheuristic_mask
);
8010 QCindex
= intern (":index");
8011 staticpro (&QCindex
);
8012 QCmatrix
= intern (":matrix");
8013 staticpro (&QCmatrix
);
8014 QCcolor_adjustment
= intern (":color-adjustment");
8015 staticpro (&QCcolor_adjustment
);
8016 QCmask
= intern (":mask");
8017 staticpro (&QCmask
);
8019 Qlaplace
= intern ("laplace");
8020 staticpro (&Qlaplace
);
8021 Qemboss
= intern ("emboss");
8022 staticpro (&Qemboss
);
8023 Qedge_detection
= intern ("edge-detection");
8024 staticpro (&Qedge_detection
);
8025 Qheuristic
= intern ("heuristic");
8026 staticpro (&Qheuristic
);
8028 Qpostscript
= intern ("postscript");
8029 staticpro (&Qpostscript
);
8030 #ifdef HAVE_GHOSTSCRIPT
8031 ADD_IMAGE_TYPE(Qpostscript
);
8032 QCloader
= intern (":loader");
8033 staticpro (&QCloader
);
8034 QCbounding_box
= intern (":bounding-box");
8035 staticpro (&QCbounding_box
);
8036 QCpt_width
= intern (":pt-width");
8037 staticpro (&QCpt_width
);
8038 QCpt_height
= intern (":pt-height");
8039 staticpro (&QCpt_height
);
8040 #endif /* HAVE_GHOSTSCRIPT */
8042 Qpbm
= intern ("pbm");
8044 ADD_IMAGE_TYPE(Qpbm
);
8046 Qxbm
= intern ("xbm");
8048 ADD_IMAGE_TYPE(Qxbm
);
8050 #if defined (HAVE_XPM) || defined (MAC_OS)
8051 Qxpm
= intern ("xpm");
8053 ADD_IMAGE_TYPE(Qxpm
);
8056 #if defined (HAVE_JPEG) || defined (MAC_OS)
8057 Qjpeg
= intern ("jpeg");
8059 ADD_IMAGE_TYPE(Qjpeg
);
8062 #if defined (HAVE_TIFF) || defined (MAC_OS)
8063 Qtiff
= intern ("tiff");
8065 ADD_IMAGE_TYPE(Qtiff
);
8068 #if defined (HAVE_GIF) || defined (MAC_OS)
8069 Qgif
= intern ("gif");
8071 ADD_IMAGE_TYPE(Qgif
);
8074 #if defined (HAVE_PNG) || defined (MAC_OS)
8075 Qpng
= intern ("png");
8077 ADD_IMAGE_TYPE(Qpng
);
8080 defsubr (&Sinit_image_library
);
8081 defsubr (&Sclear_image_cache
);
8082 defsubr (&Simage_size
);
8083 defsubr (&Simage_mask_p
);
8087 defsubr (&Slookup_image
);
8090 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8091 doc
: /* Non-nil means always draw a cross over disabled images.
8092 Disabled images are those having an `:conversion disabled' property.
8093 A cross is always drawn on black & white displays. */);
8094 cross_disabled_images
= 0;
8096 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8097 doc
: /* List of directories to search for window system bitmap files. */);
8098 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8100 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8101 doc
: /* Time after which cached images are removed from the cache.
8102 When an image has not been displayed this many seconds, remove it
8103 from the image cache. Value must be an integer or nil with nil
8104 meaning don't clear the cache. */);
8105 Vimage_cache_eviction_delay
= make_number (30 * 60);
8113 define_image_type (&xbm_type
, TRUE
);
8114 define_image_type (&pbm_type
, TRUE
);
8117 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8120 init_image_func_pointer ();
8125 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8126 (do not change this comment) */