1 /* Functions for image support on window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000,01,02,03,04
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
38 #include "dispextern.h"
39 #include "blockinput.h"
46 #include <sys/types.h>
49 #define COLOR_TABLE_SUPPORT 1
51 typedef struct x_bitmap_record Bitmap_Record
;
52 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
53 #define NO_PIXMAP None
54 #define PNG_BG_COLOR_SHIFT 0
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)
72 #define PNG_BG_COLOR_SHIFT 0
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN(f) 0
77 #define PIX_MASK_DRAW(f) 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
82 #endif /* HAVE_NTGUI */
92 #include <QuickTime/QuickTime.h>
93 #else /* not MAC_OSX */
96 #include <TextUtils.h>
97 #endif /* not MAC_OSX */
99 /* MAC_TODO : Color tables on Mac. */
100 #undef COLOR_TABLE_SUPPORT
102 #define ZPixmap 0 /* arbitrary */
103 typedef struct mac_bitmap_record Bitmap_Record
;
105 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
107 #define PNG_BG_COLOR_SHIFT 8
109 #define RGB_PIXEL_COLOR unsigned long
111 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
112 #define x_defined_color mac_defined_color
113 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
114 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
115 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
120 /* Search path for bitmap files. */
122 Lisp_Object Vx_bitmap_file_path
;
125 static void x_disable_image
P_ ((struct frame
*, struct image
*));
126 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
129 static void init_color_table
P_ ((void));
130 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
131 #ifdef COLOR_TABLE_SUPPORT
132 static void free_color_table
P_ ((void));
133 static unsigned long *colors_in_color_table
P_ ((int *n
));
134 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
137 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
138 id, which is just an int that this section returns. Bitmaps are
139 reference counted so they can be shared among frames.
141 Bitmap indices are guaranteed to be > 0, so a negative number can
142 be used to indicate no bitmap.
144 If you use x_create_bitmap_from_data, then you must keep track of
145 the bitmaps yourself. That is, creating a bitmap from the same
146 data more than once will not be caught. */
151 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
152 Display
*display
; /* not used */
154 int x
, y
; /* not used */
155 unsigned int width
, height
; /* not used */
156 unsigned long plane_mask
; /* not used */
157 int format
; /* not used */
160 xassert (x
== 0 && y
== 0);
163 SetRect (&ri
, 0, 0, width
, height
);
164 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
166 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
169 LockPixels (GetGWorldPixMap (pixmap
));
175 XPutPixel (ximage
, x
, y
, pixel
)
182 SetGWorld (ximage
, NULL
);
184 color
.red
= RED16_FROM_ULONG (pixel
);
185 color
.green
= GREEN16_FROM_ULONG (pixel
);
186 color
.blue
= BLUE16_FROM_ULONG (pixel
);
187 SetCPixel (x
, y
, &color
);
191 XGetPixel (ximage
, x
, y
)
197 SetGWorld (ximage
, NULL
);
199 GetCPixel (x
, y
, &color
);
200 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
207 UnlockPixels (GetGWorldPixMap (ximg
));
212 /* Functions to access the contents of a bitmap, given an id. */
215 x_bitmap_height (f
, id
)
219 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
223 x_bitmap_width (f
, id
)
227 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
230 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
232 x_bitmap_pixmap (f
, id
)
236 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
240 #ifdef HAVE_X_WINDOWS
242 x_bitmap_mask (f
, id
)
246 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
250 /* Allocate a new bitmap record. Returns index of new record. */
253 x_allocate_bitmap_record (f
)
256 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
259 if (dpyinfo
->bitmaps
== NULL
)
261 dpyinfo
->bitmaps_size
= 10;
263 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
264 dpyinfo
->bitmaps_last
= 1;
268 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
269 return ++dpyinfo
->bitmaps_last
;
271 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
272 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
275 dpyinfo
->bitmaps_size
*= 2;
277 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
278 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
279 return ++dpyinfo
->bitmaps_last
;
282 /* Add one reference to the reference count of the bitmap with id ID. */
285 x_reference_bitmap (f
, id
)
289 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
292 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
295 x_create_bitmap_from_data (f
, bits
, width
, height
)
298 unsigned int width
, height
;
300 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
303 #ifdef HAVE_X_WINDOWS
305 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
306 bits
, width
, height
);
309 #endif /* HAVE_X_WINDOWS */
313 bitmap
= CreateBitmap (width
, height
,
314 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
315 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
319 #endif /* HAVE_NTGUI */
322 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
327 id
= x_allocate_bitmap_record (f
);
329 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
330 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
332 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
335 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
336 dpyinfo
->bitmaps
[id
- 1].height
= height
;
337 dpyinfo
->bitmaps
[id
- 1].width
= width
;
338 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
340 #ifdef HAVE_X_WINDOWS
341 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
342 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
343 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
344 #endif /* HAVE_X_WINDOWS */
347 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
348 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
349 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
350 #endif /* HAVE_NTGUI */
355 /* Create bitmap from file FILE for frame F. */
358 x_create_bitmap_from_file (f
, file
)
363 return -1; /* MAC_TODO : bitmap support */
367 return -1; /* W32_TODO : bitmap support */
368 #endif /* HAVE_NTGUI */
370 #ifdef HAVE_X_WINDOWS
371 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
372 unsigned int width
, height
;
374 int xhot
, yhot
, result
, id
;
379 /* Look for an existing bitmap with the same name. */
380 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
382 if (dpyinfo
->bitmaps
[id
].refcount
383 && dpyinfo
->bitmaps
[id
].file
384 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
386 ++dpyinfo
->bitmaps
[id
].refcount
;
391 /* Search bitmap-file-path for the file, if appropriate. */
392 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
397 filename
= (char *) SDATA (found
);
399 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
400 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
401 if (result
!= BitmapSuccess
)
404 id
= x_allocate_bitmap_record (f
);
405 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
406 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
407 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
408 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
409 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
410 dpyinfo
->bitmaps
[id
- 1].height
= height
;
411 dpyinfo
->bitmaps
[id
- 1].width
= width
;
412 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
415 #endif /* HAVE_X_WINDOWS */
421 Free_Bitmap_Record (dpyinfo
, bm
)
422 Display_Info
*dpyinfo
;
425 #ifdef HAVE_X_WINDOWS
426 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
428 XFreePixmap (dpyinfo
->display
, bm
->mask
);
429 #endif /* HAVE_X_WINDOWS */
432 DeleteObject (bm
->pixmap
);
433 #endif /* HAVE_NTGUI */
436 xfree (bm
->bitmap_data
); /* Added ++kfs */
437 bm
->bitmap_data
= NULL
;
447 /* Remove reference to bitmap with id number ID. */
450 x_destroy_bitmap (f
, id
)
454 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
458 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
460 if (--bm
->refcount
== 0)
463 Free_Bitmap_Record (dpyinfo
, bm
);
469 /* Free all the bitmaps for the display specified by DPYINFO. */
472 x_destroy_all_bitmaps (dpyinfo
)
473 Display_Info
*dpyinfo
;
476 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
478 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
479 if (bm
->refcount
> 0)
480 Free_Bitmap_Record (dpyinfo
, bm
);
482 dpyinfo
->bitmaps_last
= 0;
486 #ifdef HAVE_X_WINDOWS
488 /* Useful functions defined in the section
489 `Image type independent image structures' below. */
491 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
492 unsigned long height
));
494 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
495 int depth
, XImagePtr
*ximg
,
498 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
501 /* Create a mask of a bitmap. Note is this not a perfect mask.
502 It's nicer with some borders in this context */
505 x_create_bitmap_mask (f
, id
)
510 XImagePtr ximg
, mask_img
;
511 unsigned long width
, height
;
514 unsigned long x
, y
, xp
, xm
, yp
, ym
;
517 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
522 pixmap
= x_bitmap_pixmap (f
, id
);
523 width
= x_bitmap_width (f
, id
);
524 height
= x_bitmap_height (f
, id
);
527 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
536 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
541 XDestroyImage (ximg
);
545 bg
= four_corners_best (ximg
, width
, height
);
547 for (y
= 0; y
< ximg
->height
; ++y
)
549 for (x
= 0; x
< ximg
->width
; ++x
)
551 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
552 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
553 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
554 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
555 if (XGetPixel (ximg
, x
, y
) == bg
556 && XGetPixel (ximg
, x
, yp
) == bg
557 && XGetPixel (ximg
, x
, ym
) == bg
558 && XGetPixel (ximg
, xp
, y
) == bg
559 && XGetPixel (ximg
, xp
, yp
) == bg
560 && XGetPixel (ximg
, xp
, ym
) == bg
561 && XGetPixel (ximg
, xm
, y
) == bg
562 && XGetPixel (ximg
, xm
, yp
) == bg
563 && XGetPixel (ximg
, xm
, ym
) == bg
)
564 XPutPixel (mask_img
, x
, y
, 0);
566 XPutPixel (mask_img
, x
, y
, 1);
570 xassert (interrupt_input_blocked
);
571 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
572 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
574 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
576 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
577 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
579 XDestroyImage (ximg
);
580 x_destroy_x_image (mask_img
);
585 #endif /* HAVE_X_WINDOWS */
588 /***********************************************************************
590 ***********************************************************************/
592 /* Value is the number of elements of vector VECTOR. */
594 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
596 /* List of supported image types. Use define_image_type to add new
597 types. Use lookup_image_type to find a type for a given symbol. */
599 static struct image_type
*image_types
;
601 /* The symbol `xbm' which is used as the type symbol for XBM images. */
607 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
608 extern Lisp_Object QCdata
, QCtype
;
609 extern Lisp_Object Qcenter
;
610 Lisp_Object QCascent
, QCmargin
, QCrelief
;
611 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
612 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
616 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
618 /* Time in seconds after which images should be removed from the cache
621 Lisp_Object Vimage_cache_eviction_delay
;
623 /* Function prototypes. */
625 static void define_image_type
P_ ((struct image_type
*type
));
626 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
627 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
628 static void x_laplace
P_ ((struct frame
*, struct image
*));
629 static void x_emboss
P_ ((struct frame
*, struct image
*));
630 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
634 /* Define a new image type from TYPE. This adds a copy of TYPE to
635 image_types and adds the symbol *TYPE->type to Vimage_types. */
638 define_image_type (type
)
639 struct image_type
*type
;
641 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
642 The initialized data segment is read-only. */
643 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
644 bcopy (type
, p
, sizeof *p
);
645 p
->next
= image_types
;
647 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
651 /* Look up image type SYMBOL, and return a pointer to its image_type
652 structure. Value is null if SYMBOL is not a known image type. */
654 static INLINE
struct image_type
*
655 lookup_image_type (symbol
)
658 struct image_type
*type
;
660 for (type
= image_types
; type
; type
= type
->next
)
661 if (EQ (symbol
, *type
->type
))
668 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
669 valid image specification is a list whose car is the symbol
670 `image', and whose rest is a property list. The property list must
671 contain a value for key `:type'. That value must be the name of a
672 supported image type. The rest of the property list depends on the
676 valid_image_p (object
)
685 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
686 if (EQ (XCAR (tem
), QCtype
))
689 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
691 struct image_type
*type
;
692 type
= lookup_image_type (XCAR (tem
));
694 valid_p
= type
->valid_p (object
);
705 /* Log error message with format string FORMAT and argument ARG.
706 Signaling an error, e.g. when an image cannot be loaded, is not a
707 good idea because this would interrupt redisplay, and the error
708 message display would lead to another redisplay. This function
709 therefore simply displays a message. */
712 image_error (format
, arg1
, arg2
)
714 Lisp_Object arg1
, arg2
;
716 add_to_log (format
, arg1
, arg2
);
721 /***********************************************************************
723 ***********************************************************************/
725 enum image_value_type
727 IMAGE_DONT_CHECK_VALUE_TYPE
,
729 IMAGE_STRING_OR_NIL_VALUE
,
731 IMAGE_POSITIVE_INTEGER_VALUE
,
732 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
733 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
736 IMAGE_FUNCTION_VALUE
,
741 /* Structure used when parsing image specifications. */
745 /* Name of keyword. */
748 /* The type of value allowed. */
749 enum image_value_type type
;
751 /* Non-zero means key must be present. */
754 /* Used to recognize duplicate keywords in a property list. */
757 /* The value that was found. */
762 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
764 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
767 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
768 has the format (image KEYWORD VALUE ...). One of the keyword/
769 value pairs must be `:type TYPE'. KEYWORDS is a vector of
770 image_keywords structures of size NKEYWORDS describing other
771 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
774 parse_image_spec (spec
, keywords
, nkeywords
, type
)
776 struct image_keyword
*keywords
;
787 while (CONSP (plist
))
789 Lisp_Object key
, value
;
791 /* First element of a pair must be a symbol. */
793 plist
= XCDR (plist
);
797 /* There must follow a value. */
800 value
= XCAR (plist
);
801 plist
= XCDR (plist
);
803 /* Find key in KEYWORDS. Error if not found. */
804 for (i
= 0; i
< nkeywords
; ++i
)
805 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
811 /* Record that we recognized the keyword. If a keywords
812 was found more than once, it's an error. */
813 keywords
[i
].value
= value
;
816 if (keywords
[i
].count
> 1)
819 /* Check type of value against allowed type. */
820 switch (keywords
[i
].type
)
822 case IMAGE_STRING_VALUE
:
823 if (!STRINGP (value
))
827 case IMAGE_STRING_OR_NIL_VALUE
:
828 if (!STRINGP (value
) && !NILP (value
))
832 case IMAGE_SYMBOL_VALUE
:
833 if (!SYMBOLP (value
))
837 case IMAGE_POSITIVE_INTEGER_VALUE
:
838 if (!INTEGERP (value
) || XINT (value
) <= 0)
842 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
843 if (INTEGERP (value
) && XINT (value
) >= 0)
846 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
847 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
851 case IMAGE_ASCENT_VALUE
:
852 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
854 else if (INTEGERP (value
)
856 && XINT (value
) <= 100)
860 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
861 if (!INTEGERP (value
) || XINT (value
) < 0)
865 case IMAGE_DONT_CHECK_VALUE_TYPE
:
868 case IMAGE_FUNCTION_VALUE
:
869 value
= indirect_function (value
);
872 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
876 case IMAGE_NUMBER_VALUE
:
877 if (!INTEGERP (value
) && !FLOATP (value
))
881 case IMAGE_INTEGER_VALUE
:
882 if (!INTEGERP (value
))
886 case IMAGE_BOOL_VALUE
:
887 if (!NILP (value
) && !EQ (value
, Qt
))
896 if (EQ (key
, QCtype
) && !EQ (type
, value
))
900 /* Check that all mandatory fields are present. */
901 for (i
= 0; i
< nkeywords
; ++i
)
902 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
909 /* Return the value of KEY in image specification SPEC. Value is nil
910 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
911 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
914 image_spec_value (spec
, key
, found
)
915 Lisp_Object spec
, key
;
920 xassert (valid_image_p (spec
));
922 for (tail
= XCDR (spec
);
923 CONSP (tail
) && CONSP (XCDR (tail
));
924 tail
= XCDR (XCDR (tail
)))
926 if (EQ (XCAR (tail
), key
))
930 return XCAR (XCDR (tail
));
940 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
941 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
942 PIXELS non-nil means return the size in pixels, otherwise return the
943 size in canonical character units.
944 FRAME is the frame on which the image will be displayed. FRAME nil
945 or omitted means use the selected frame. */)
946 (spec
, pixels
, frame
)
947 Lisp_Object spec
, pixels
, frame
;
952 if (valid_image_p (spec
))
954 struct frame
*f
= check_x_frame (frame
);
955 int id
= lookup_image (f
, spec
);
956 struct image
*img
= IMAGE_FROM_ID (f
, id
);
957 int width
= img
->width
+ 2 * img
->hmargin
;
958 int height
= img
->height
+ 2 * img
->vmargin
;
961 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
962 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
964 size
= Fcons (make_number (width
), make_number (height
));
967 error ("Invalid image specification");
973 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
974 doc
: /* Return t if image SPEC has a mask bitmap.
975 FRAME is the frame on which the image will be displayed. FRAME nil
976 or omitted means use the selected frame. */)
978 Lisp_Object spec
, frame
;
983 if (valid_image_p (spec
))
985 struct frame
*f
= check_x_frame (frame
);
986 int id
= lookup_image (f
, spec
);
987 struct image
*img
= IMAGE_FROM_ID (f
, id
);
992 error ("Invalid image specification");
998 /***********************************************************************
999 Image type independent image structures
1000 ***********************************************************************/
1002 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1003 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1006 /* Allocate and return a new image structure for image specification
1007 SPEC. SPEC has a hash value of HASH. */
1009 static struct image
*
1010 make_image (spec
, hash
)
1014 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1016 xassert (valid_image_p (spec
));
1017 bzero (img
, sizeof *img
);
1018 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1019 xassert (img
->type
!= NULL
);
1021 img
->data
.lisp_val
= Qnil
;
1022 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1028 /* Free image IMG which was used on frame F, including its resources. */
1037 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1039 /* Remove IMG from the hash table of its cache. */
1041 img
->prev
->next
= img
->next
;
1043 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1046 img
->next
->prev
= img
->prev
;
1048 c
->images
[img
->id
] = NULL
;
1050 /* Free resources, then free IMG. */
1051 img
->type
->free (f
, img
);
1057 /* Prepare image IMG for display on frame F. Must be called before
1058 drawing an image. */
1061 prepare_image_for_display (f
, img
)
1067 /* We're about to display IMG, so set its timestamp to `now'. */
1069 img
->timestamp
= EMACS_SECS (t
);
1071 /* If IMG doesn't have a pixmap yet, load it now, using the image
1072 type dependent loader function. */
1073 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1074 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1078 /* Value is the number of pixels for the ascent of image IMG when
1079 drawn in face FACE. */
1082 image_ascent (img
, face
)
1086 int height
= img
->height
+ img
->vmargin
;
1089 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1094 /* W32 specific version. Why?. ++kfs */
1095 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1096 - FONT_BASE(face
->font
)) / 2;
1098 /* This expression is arranged so that if the image can't be
1099 exactly centered, it will be moved slightly up. This is
1100 because a typical font is `top-heavy' (due to the presence
1101 uppercase letters), so the image placement should err towards
1102 being top-heavy too. It also just generally looks better. */
1103 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1104 #endif /* HAVE_NTGUI */
1107 ascent
= height
/ 2;
1110 ascent
= (int) (height
* img
->ascent
/ 100.0);
1116 /* Image background colors. */
1118 /* Find the "best" corner color of a bitmap.
1119 On W32, XIMG is assumed to a device context with the bitmap selected. */
1121 static RGB_PIXEL_COLOR
1122 four_corners_best (ximg
, width
, height
)
1123 XImagePtr_or_DC ximg
;
1124 unsigned long width
, height
;
1126 RGB_PIXEL_COLOR corners
[4], best
;
1129 /* Get the colors at the corners of ximg. */
1130 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1131 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1132 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1133 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1135 /* Choose the most frequently found color as background. */
1136 for (i
= best_count
= 0; i
< 4; ++i
)
1140 for (j
= n
= 0; j
< 4; ++j
)
1141 if (corners
[i
] == corners
[j
])
1145 best
= corners
[i
], best_count
= n
;
1151 /* Portability macros */
1155 #define Destroy_Image(img_dc, prev) \
1156 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1158 #define Free_Pixmap(display, pixmap) \
1159 DeleteObject (pixmap)
1163 #define Destroy_Image(ximg, dummy) \
1164 XDestroyImage (ximg)
1166 #define Free_Pixmap(display, pixmap) \
1167 XFreePixmap (display, pixmap)
1169 #endif /* HAVE_NTGUI */
1172 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1173 it is guessed heuristically. If non-zero, XIMG is an existing
1174 XImage object (or device context with the image selected on W32) to
1175 use for the heuristic. */
1178 image_background (img
, f
, ximg
)
1181 XImagePtr_or_DC ximg
;
1183 if (! img
->background_valid
)
1184 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1186 int free_ximg
= !ximg
;
1189 #endif /* HAVE_NTGUI */
1194 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1195 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1197 HDC frame_dc
= get_frame_dc (f
);
1198 ximg
= CreateCompatibleDC (frame_dc
);
1199 release_frame_dc (f
, frame_dc
);
1200 prev
= SelectObject (ximg
, img
->pixmap
);
1201 #endif /* !HAVE_NTGUI */
1204 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1207 Destroy_Image (ximg
, prev
);
1209 img
->background_valid
= 1;
1212 return img
->background
;
1215 /* Return the `background_transparent' field of IMG. If IMG doesn't
1216 have one yet, it is guessed heuristically. If non-zero, MASK is an
1217 existing XImage object to use for the heuristic. */
1220 image_background_transparent (img
, f
, mask
)
1223 XImagePtr_or_DC mask
;
1225 if (! img
->background_transparent_valid
)
1226 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1230 int free_mask
= !mask
;
1233 #endif /* HAVE_NTGUI */
1238 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1239 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1241 HDC frame_dc
= get_frame_dc (f
);
1242 mask
= CreateCompatibleDC (frame_dc
);
1243 release_frame_dc (f
, frame_dc
);
1244 prev
= SelectObject (mask
, img
->mask
);
1245 #endif /* HAVE_NTGUI */
1248 img
->background_transparent
1249 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN (f
));
1252 Destroy_Image (mask
, prev
);
1255 img
->background_transparent
= 0;
1257 img
->background_transparent_valid
= 1;
1260 return img
->background_transparent
;
1264 /***********************************************************************
1265 Helper functions for X image types
1266 ***********************************************************************/
1268 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1270 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1271 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1273 Lisp_Object color_name
,
1274 unsigned long dflt
));
1277 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1278 free the pixmap if any. MASK_P non-zero means clear the mask
1279 pixmap if any. COLORS_P non-zero means free colors allocated for
1280 the image, if any. */
1283 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1286 int pixmap_p
, mask_p
, colors_p
;
1288 if (pixmap_p
&& img
->pixmap
)
1290 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1291 img
->pixmap
= NO_PIXMAP
;
1292 img
->background_valid
= 0;
1295 if (mask_p
&& img
->mask
)
1297 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1298 img
->mask
= NO_PIXMAP
;
1299 img
->background_transparent_valid
= 0;
1302 if (colors_p
&& img
->ncolors
)
1304 /* MAC_TODO: color table support. */
1305 /* W32_TODO: color table support. */
1306 #ifdef HAVE_X_WINDOWS
1307 x_free_colors (f
, img
->colors
, img
->ncolors
);
1308 #endif /* HAVE_X_WINDOWS */
1309 xfree (img
->colors
);
1315 /* Free X resources of image IMG which is used on frame F. */
1318 x_clear_image (f
, img
)
1323 x_clear_image_1 (f
, img
, 1, 1, 1);
1328 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1329 cannot be allocated, use DFLT. Add a newly allocated color to
1330 IMG->colors, so that it can be freed again. Value is the pixel
1333 static unsigned long
1334 x_alloc_image_color (f
, img
, color_name
, dflt
)
1337 Lisp_Object color_name
;
1341 unsigned long result
;
1343 xassert (STRINGP (color_name
));
1345 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1347 /* This isn't called frequently so we get away with simply
1348 reallocating the color vector to the needed size, here. */
1351 (unsigned long *) xrealloc (img
->colors
,
1352 img
->ncolors
* sizeof *img
->colors
);
1353 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1354 result
= color
.pixel
;
1364 /***********************************************************************
1366 ***********************************************************************/
1368 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1369 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1371 /* Return a new, initialized image cache that is allocated from the
1372 heap. Call free_image_cache to free an image cache. */
1374 struct image_cache
*
1377 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1380 bzero (c
, sizeof *c
);
1382 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1383 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1384 c
->buckets
= (struct image
**) xmalloc (size
);
1385 bzero (c
->buckets
, size
);
1390 /* Free image cache of frame F. Be aware that X frames share images
1394 free_image_cache (f
)
1397 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1402 /* Cache should not be referenced by any frame when freed. */
1403 xassert (c
->refcount
== 0);
1405 for (i
= 0; i
< c
->used
; ++i
)
1406 free_image (f
, c
->images
[i
]);
1410 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1415 /* Clear image cache of frame F. FORCE_P non-zero means free all
1416 images. FORCE_P zero means clear only images that haven't been
1417 displayed for some time. Should be called from time to time to
1418 reduce the number of loaded images. If image-eviction-seconds is
1419 non-nil, this frees images in the cache which weren't displayed for
1420 at least that many seconds. */
1423 clear_image_cache (f
, force_p
)
1427 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1429 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1436 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1438 /* Block input so that we won't be interrupted by a SIGIO
1439 while being in an inconsistent state. */
1442 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1444 struct image
*img
= c
->images
[i
];
1446 && (force_p
|| img
->timestamp
< old
))
1448 free_image (f
, img
);
1453 /* We may be clearing the image cache because, for example,
1454 Emacs was iconified for a longer period of time. In that
1455 case, current matrices may still contain references to
1456 images freed above. So, clear these matrices. */
1459 Lisp_Object tail
, frame
;
1461 FOR_EACH_FRAME (tail
, frame
)
1463 struct frame
*f
= XFRAME (frame
);
1464 if (FRAME_WINDOW_P (f
)
1465 && FRAME_X_IMAGE_CACHE (f
) == c
)
1466 clear_current_matrices (f
);
1469 ++windows_or_buffers_changed
;
1477 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1479 doc
: /* Clear the image cache of FRAME.
1480 FRAME nil or omitted means use the selected frame.
1481 FRAME t means clear the image caches of all frames. */)
1489 FOR_EACH_FRAME (tail
, frame
)
1490 if (FRAME_WINDOW_P (XFRAME (frame
)))
1491 clear_image_cache (XFRAME (frame
), 1);
1494 clear_image_cache (check_x_frame (frame
), 1);
1500 /* Compute masks and transform image IMG on frame F, as specified
1501 by the image's specification, */
1504 postprocess_image (f
, img
)
1508 /* Manipulation of the image's mask. */
1511 Lisp_Object conversion
, spec
;
1516 /* `:heuristic-mask t'
1518 means build a mask heuristically.
1519 `:heuristic-mask (R G B)'
1520 `:mask (heuristic (R G B))'
1521 means build a mask from color (R G B) in the
1524 means remove a mask, if any. */
1526 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1528 x_build_heuristic_mask (f
, img
, mask
);
1533 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1535 if (EQ (mask
, Qheuristic
))
1536 x_build_heuristic_mask (f
, img
, Qt
);
1537 else if (CONSP (mask
)
1538 && EQ (XCAR (mask
), Qheuristic
))
1540 if (CONSP (XCDR (mask
)))
1541 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1543 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1545 else if (NILP (mask
) && found_p
&& img
->mask
)
1547 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1548 img
->mask
= NO_PIXMAP
;
1553 /* Should we apply an image transformation algorithm? */
1554 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1555 if (EQ (conversion
, Qdisabled
))
1556 x_disable_image (f
, img
);
1557 else if (EQ (conversion
, Qlaplace
))
1559 else if (EQ (conversion
, Qemboss
))
1561 else if (CONSP (conversion
)
1562 && EQ (XCAR (conversion
), Qedge_detection
))
1565 tem
= XCDR (conversion
);
1567 x_edge_detection (f
, img
,
1568 Fplist_get (tem
, QCmatrix
),
1569 Fplist_get (tem
, QCcolor_adjustment
));
1575 /* Return the id of image with Lisp specification SPEC on frame F.
1576 SPEC must be a valid Lisp image specification (see valid_image_p). */
1579 lookup_image (f
, spec
)
1583 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1587 struct gcpro gcpro1
;
1590 /* F must be a window-system frame, and SPEC must be a valid image
1592 xassert (FRAME_WINDOW_P (f
));
1593 xassert (valid_image_p (spec
));
1597 /* Look up SPEC in the hash table of the image cache. */
1598 hash
= sxhash (spec
, 0);
1599 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1601 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1602 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1605 /* If not found, create a new image and cache it. */
1608 extern Lisp_Object Qpostscript
;
1611 img
= make_image (spec
, hash
);
1612 cache_image (f
, img
);
1613 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1615 /* If we can't load the image, and we don't have a width and
1616 height, use some arbitrary width and height so that we can
1617 draw a rectangle for it. */
1618 if (img
->load_failed_p
)
1622 value
= image_spec_value (spec
, QCwidth
, NULL
);
1623 img
->width
= (INTEGERP (value
)
1624 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1625 value
= image_spec_value (spec
, QCheight
, NULL
);
1626 img
->height
= (INTEGERP (value
)
1627 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1631 /* Handle image type independent image attributes
1632 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1633 `:background COLOR'. */
1634 Lisp_Object ascent
, margin
, relief
, bg
;
1636 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1637 if (INTEGERP (ascent
))
1638 img
->ascent
= XFASTINT (ascent
);
1639 else if (EQ (ascent
, Qcenter
))
1640 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1642 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1643 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1644 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1645 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1646 && INTEGERP (XCDR (margin
)))
1648 if (XINT (XCAR (margin
)) > 0)
1649 img
->hmargin
= XFASTINT (XCAR (margin
));
1650 if (XINT (XCDR (margin
)) > 0)
1651 img
->vmargin
= XFASTINT (XCDR (margin
));
1654 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1655 if (INTEGERP (relief
))
1657 img
->relief
= XINT (relief
);
1658 img
->hmargin
+= abs (img
->relief
);
1659 img
->vmargin
+= abs (img
->relief
);
1662 if (! img
->background_valid
)
1664 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1668 = x_alloc_image_color (f
, img
, bg
,
1669 FRAME_BACKGROUND_PIXEL (f
));
1670 img
->background_valid
= 1;
1674 /* Do image transformations and compute masks, unless we
1675 don't have the image yet. */
1676 if (!EQ (*img
->type
->type
, Qpostscript
))
1677 postprocess_image (f
, img
);
1683 /* We're using IMG, so set its timestamp to `now'. */
1684 EMACS_GET_TIME (now
);
1685 img
->timestamp
= EMACS_SECS (now
);
1689 /* Value is the image id. */
1694 /* Cache image IMG in the image cache of frame F. */
1697 cache_image (f
, img
)
1701 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1704 /* Find a free slot in c->images. */
1705 for (i
= 0; i
< c
->used
; ++i
)
1706 if (c
->images
[i
] == NULL
)
1709 /* If no free slot found, maybe enlarge c->images. */
1710 if (i
== c
->used
&& c
->used
== c
->size
)
1713 c
->images
= (struct image
**) xrealloc (c
->images
,
1714 c
->size
* sizeof *c
->images
);
1717 /* Add IMG to c->images, and assign IMG an id. */
1723 /* Add IMG to the cache's hash table. */
1724 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1725 img
->next
= c
->buckets
[i
];
1727 img
->next
->prev
= img
;
1729 c
->buckets
[i
] = img
;
1733 /* Call FN on every image in the image cache of frame F. Used to mark
1734 Lisp Objects in the image cache. */
1737 forall_images_in_image_cache (f
, fn
)
1739 void (*fn
) P_ ((struct image
*img
));
1741 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1743 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1747 for (i
= 0; i
< c
->used
; ++i
)
1756 /***********************************************************************
1757 X / MAC / W32 support code
1758 ***********************************************************************/
1762 /* Macro for defining functions that will be loaded from image DLLs. */
1763 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1765 /* Macro for loading those image functions from the library. */
1766 #define LOAD_IMGLIB_FN(lib,func) { \
1767 fn_##func = (void *) GetProcAddress (lib, #func); \
1768 if (!fn_##func) return 0; \
1771 #endif /* HAVE_NTGUI */
1773 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
1774 XImagePtr
*, Pixmap
*));
1775 static void x_destroy_x_image
P_ ((XImagePtr
));
1776 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
1779 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1780 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1781 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1782 via xmalloc. Print error messages via image_error if an error
1783 occurs. Value is non-zero if successful.
1785 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1786 should indicate the bit depth of the image. */
1789 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
1791 int width
, height
, depth
;
1795 #ifdef HAVE_X_WINDOWS
1796 Display
*display
= FRAME_X_DISPLAY (f
);
1797 Window window
= FRAME_X_WINDOW (f
);
1798 Screen
*screen
= FRAME_X_SCREEN (f
);
1800 xassert (interrupt_input_blocked
);
1803 depth
= DefaultDepthOfScreen (screen
);
1804 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
1805 depth
, ZPixmap
, 0, NULL
, width
, height
,
1806 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
1809 image_error ("Unable to allocate X image", Qnil
, Qnil
);
1813 /* Allocate image raster. */
1814 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
1816 /* Allocate a pixmap of the same size. */
1817 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1818 if (*pixmap
== NO_PIXMAP
)
1820 x_destroy_x_image (*ximg
);
1822 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1827 #endif /* HAVE_X_WINDOWS */
1831 BITMAPINFOHEADER
*header
;
1833 int scanline_width_bits
;
1835 int palette_colors
= 0;
1840 if (depth
!= 1 && depth
!= 4 && depth
!= 8
1841 && depth
!= 16 && depth
!= 24 && depth
!= 32)
1843 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
1847 scanline_width_bits
= width
* depth
;
1848 remainder
= scanline_width_bits
% 32;
1851 scanline_width_bits
+= 32 - remainder
;
1853 /* Bitmaps with a depth less than 16 need a palette. */
1854 /* BITMAPINFO structure already contains the first RGBQUAD. */
1856 palette_colors
= 1 << depth
- 1;
1858 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
1861 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
1865 header
= &((*ximg
)->info
.bmiHeader
);
1866 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
1867 header
->biSize
= sizeof (*header
);
1868 header
->biWidth
= width
;
1869 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
1870 header
->biPlanes
= 1;
1871 header
->biBitCount
= depth
;
1872 header
->biCompression
= BI_RGB
;
1873 header
->biClrUsed
= palette_colors
;
1875 /* TODO: fill in palette. */
1878 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
1879 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
1880 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
1881 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
1882 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
1883 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
1884 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
1885 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
1888 hdc
= get_frame_dc (f
);
1890 /* Create a DIBSection and raster array for the bitmap,
1891 and store its handle in *pixmap. */
1892 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
1893 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
1894 &((*ximg
)->data
), NULL
, 0);
1896 /* Realize display palette and garbage all frames. */
1897 release_frame_dc (f
, hdc
);
1899 if (*pixmap
== NULL
)
1901 DWORD err
= GetLastError();
1902 Lisp_Object errcode
;
1903 /* All system errors are < 10000, so the following is safe. */
1904 XSETINT (errcode
, (int) err
);
1905 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
1906 x_destroy_x_image (*ximg
);
1912 #endif /* HAVE_NTGUI */
1915 Display
*display
= FRAME_X_DISPLAY (f
);
1916 Window window
= FRAME_X_WINDOW (f
);
1918 xassert (interrupt_input_blocked
);
1920 /* Allocate a pixmap of the same size. */
1921 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1922 if (*pixmap
== NO_PIXMAP
)
1924 x_destroy_x_image (*ximg
);
1926 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1930 LockPixels (GetGWorldPixMap (*pixmap
));
1938 /* Destroy XImage XIMG. Free XIMG->data. */
1941 x_destroy_x_image (ximg
)
1944 xassert (interrupt_input_blocked
);
1947 #ifdef HAVE_X_WINDOWS
1950 XDestroyImage (ximg
);
1951 #endif /* HAVE_X_WINDOWS */
1953 /* Data will be freed by DestroyObject. */
1956 #endif /* HAVE_NTGUI */
1958 XDestroyImage (ximg
);
1964 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
1965 are width and height of both the image and pixmap. */
1968 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
1974 #ifdef HAVE_X_WINDOWS
1977 xassert (interrupt_input_blocked
);
1978 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
1979 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
1980 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1981 #endif /* HAVE_X_WINDOWS */
1984 #if 0 /* I don't think this is necessary looking at where it is used. */
1985 HDC hdc
= get_frame_dc (f
);
1986 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
1987 release_frame_dc (f
, hdc
);
1989 #endif /* HAVE_NTGUI */
1992 xassert (ximg
== pixmap
);
1997 /***********************************************************************
1999 ***********************************************************************/
2001 static unsigned char *slurp_file
P_ ((char *, int *));
2004 /* Find image file FILE. Look in data-directory, then
2005 x-bitmap-file-path. Value is the full name of the file found, or
2006 nil if not found. */
2009 x_find_image_file (file
)
2012 Lisp_Object file_found
, search_path
;
2013 struct gcpro gcpro1
, gcpro2
;
2017 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2018 GCPRO2 (file_found
, search_path
);
2020 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2021 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2033 /* Read FILE into memory. Value is a pointer to a buffer allocated
2034 with xmalloc holding FILE's contents. Value is null if an error
2035 occurred. *SIZE is set to the size of the file. */
2037 static unsigned char *
2038 slurp_file (file
, size
)
2043 unsigned char *buf
= NULL
;
2046 if (stat (file
, &st
) == 0
2047 && (fp
= fopen (file
, "rb")) != NULL
2048 && (buf
= (char *) xmalloc (st
.st_size
),
2049 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2072 /***********************************************************************
2073 MAC Image Load Functions
2074 ***********************************************************************/
2076 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2079 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2083 find_image_fsspec (specified_file
, file
, fss
)
2084 Lisp_Object specified_file
, *file
;
2087 #if TARGET_API_MAC_CARBON
2090 Str255 mac_pathname
;
2094 *file
= x_find_image_file (specified_file
);
2095 if (!STRINGP (*file
))
2096 return fnfErr
; /* file or directory not found;
2097 incomplete pathname */
2098 /* Try to open the image file. */
2099 #if TARGET_API_MAC_CARBON
2100 err
= FSPathMakeRef (SDATA (*file
), &fsr
, NULL
);
2102 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
2104 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
2106 c2pstr (mac_pathname
);
2107 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
2113 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2121 GraphicsImportComponent gi
;
2124 short draw_all_pixels
;
2125 Lisp_Object specified_bg
;
2130 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2134 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2139 /* read from file system spec */
2140 err
= GraphicsImportSetDataFile (gi
, fss
);
2143 image_error ("Cannot set fsspec to graphics importer for '%s'",
2150 /* read from data handle */
2151 err
= GraphicsImportSetDataHandle (gi
, dh
);
2154 image_error ("Cannot set data handle to graphics importer for `%s'",
2159 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
2162 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2165 width
= img
->width
= rect
.right
- rect
.left
;
2166 height
= img
->height
= rect
.bottom
- rect
.top
;
2167 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2169 /* Don't check the error code here. It may have an undocumented
2173 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2177 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2179 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2180 if (!STRINGP (specified_bg
) ||
2181 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2183 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2184 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2185 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2186 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2190 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2192 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2194 SetGWorld (ximg
, NULL
);
2195 bg_color
.red
= color
.red
;
2196 bg_color
.green
= color
.green
;
2197 bg_color
.blue
= color
.blue
;
2198 RGBBackColor (&bg_color
);
2199 #if TARGET_API_MAC_CARBON
2200 GetPortBounds (ximg
, &rect
);
2203 EraseRect (&(ximg
->portRect
));
2206 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2207 GraphicsImportDraw (gi
);
2208 CloseComponent (gi
);
2210 /* Maybe fill in the background field while we have ximg handy. */
2211 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2212 IMAGE_BACKGROUND (img
, f
, ximg
);
2214 /* Put the image into the pixmap. */
2215 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2216 x_destroy_x_image (ximg
);
2220 CloseComponent (gi
);
2225 /* Load an image using the QuickTime Graphics Importer.
2226 Note: The alpha channel does not work for PNG images. */
2228 image_load_quicktime (f
, img
, type
)
2233 Lisp_Object specified_file
;
2234 Lisp_Object specified_data
;
2237 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2238 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2240 if (NILP (specified_data
))
2242 /* Read from a file */
2246 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2250 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2252 image_error ("Cannot open `%s'", file
, Qnil
);
2255 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2259 /* Memory source! */
2263 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2266 image_error ("Cannot allocate data handle for `%s'",
2270 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2278 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2279 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2280 So don't use this function directly but determine at runtime
2281 whether it exists. */
2282 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2283 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2284 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2288 init_image_func_pointer ()
2290 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2292 MyCGImageCreateWithPNGDataProvider
2293 = (CGImageCreateWithPNGDataProviderProcType
)
2294 NSAddressOfSymbol (NSLookupAndBindSymbol
2295 ("_CGImageCreateWithPNGDataProvider"));
2298 MyCGImageCreateWithPNGDataProvider
= NULL
;
2303 image_load_quartz2d (f
, img
, png_p
)
2308 Lisp_Object file
, specified_file
;
2309 Lisp_Object specified_data
, specified_bg
;
2310 struct gcpro gcpro1
;
2311 CGDataProviderRef source
;
2315 XImagePtr ximg
= NULL
;
2316 CGContextRef context
;
2319 /* Open the file. */
2320 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2321 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2326 if (NILP (specified_data
))
2331 file
= x_find_image_file (specified_file
);
2332 if (!STRINGP (file
))
2334 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2338 path
= CFStringCreateWithCString (NULL
, SDATA (file
),
2339 kCFStringEncodingUTF8
);
2340 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2341 kCFURLPOSIXPathStyle
, 0);
2343 source
= CGDataProviderCreateWithURL (url
);
2347 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2348 SBYTES (specified_data
), NULL
);
2351 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2352 kCGRenderingIntentDefault
);
2354 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2355 kCGRenderingIntentDefault
);
2357 CGDataProviderRelease (source
);
2361 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2367 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2368 if (!STRINGP (specified_bg
) ||
2369 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2371 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2372 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2373 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2374 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2377 width
= img
->width
= CGImageGetWidth (image
);
2378 height
= img
->height
= CGImageGetHeight (image
);
2379 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2381 CGImageRelease (image
);
2385 rectangle
= CGRectMake (0, 0, width
, height
);
2386 QDBeginCGContext (ximg
, &context
);
2389 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2390 color
.green
/ 65535.0,
2391 color
.blue
/ 65535.0, 1.0);
2392 CGContextFillRect (context
, rectangle
);
2394 CGContextDrawImage (context
, rectangle
, image
);
2395 QDEndCGContext (ximg
, &context
);
2396 CGImageRelease (image
);
2398 /* Maybe fill in the background field while we have ximg handy. */
2399 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2400 IMAGE_BACKGROUND (img
, f
, ximg
);
2402 /* Put the image into the pixmap. */
2403 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2404 x_destroy_x_image (ximg
);
2413 /***********************************************************************
2415 ***********************************************************************/
2417 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2418 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2419 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2420 unsigned char *, unsigned char *));
2421 static int xbm_image_p
P_ ((Lisp_Object object
));
2422 static int xbm_read_bitmap_data
P_ ((unsigned char *, unsigned char *,
2423 int *, int *, unsigned char **));
2424 static int xbm_file_p
P_ ((Lisp_Object
));
2427 /* Indices of image specification fields in xbm_format, below. */
2429 enum xbm_keyword_index
2447 /* Vector of image_keyword structures describing the format
2448 of valid XBM image specifications. */
2450 static struct image_keyword xbm_format
[XBM_LAST
] =
2452 {":type", IMAGE_SYMBOL_VALUE
, 1},
2453 {":file", IMAGE_STRING_VALUE
, 0},
2454 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2455 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2456 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2457 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2458 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2459 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2460 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2461 {":relief", IMAGE_INTEGER_VALUE
, 0},
2462 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2463 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2464 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2467 /* Structure describing the image type XBM. */
2469 static struct image_type xbm_type
=
2478 /* Tokens returned from xbm_scan. */
2487 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2488 A valid specification is a list starting with the symbol `image'
2489 The rest of the list is a property list which must contain an
2492 If the specification specifies a file to load, it must contain
2493 an entry `:file FILENAME' where FILENAME is a string.
2495 If the specification is for a bitmap loaded from memory it must
2496 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2497 WIDTH and HEIGHT are integers > 0. DATA may be:
2499 1. a string large enough to hold the bitmap data, i.e. it must
2500 have a size >= (WIDTH + 7) / 8 * HEIGHT
2502 2. a bool-vector of size >= WIDTH * HEIGHT
2504 3. a vector of strings or bool-vectors, one for each line of the
2507 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2508 may not be specified in this case because they are defined in the
2511 Both the file and data forms may contain the additional entries
2512 `:background COLOR' and `:foreground COLOR'. If not present,
2513 foreground and background of the frame on which the image is
2514 displayed is used. */
2517 xbm_image_p (object
)
2520 struct image_keyword kw
[XBM_LAST
];
2522 bcopy (xbm_format
, kw
, sizeof kw
);
2523 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2526 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2528 if (kw
[XBM_FILE
].count
)
2530 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2533 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2535 /* In-memory XBM file. */
2536 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2544 /* Entries for `:width', `:height' and `:data' must be present. */
2545 if (!kw
[XBM_WIDTH
].count
2546 || !kw
[XBM_HEIGHT
].count
2547 || !kw
[XBM_DATA
].count
)
2550 data
= kw
[XBM_DATA
].value
;
2551 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2552 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2554 /* Check type of data, and width and height against contents of
2560 /* Number of elements of the vector must be >= height. */
2561 if (XVECTOR (data
)->size
< height
)
2564 /* Each string or bool-vector in data must be large enough
2565 for one line of the image. */
2566 for (i
= 0; i
< height
; ++i
)
2568 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2573 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2576 else if (BOOL_VECTOR_P (elt
))
2578 if (XBOOL_VECTOR (elt
)->size
< width
)
2585 else if (STRINGP (data
))
2588 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2591 else if (BOOL_VECTOR_P (data
))
2593 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2604 /* Scan a bitmap file. FP is the stream to read from. Value is
2605 either an enumerator from enum xbm_token, or a character for a
2606 single-character token, or 0 at end of file. If scanning an
2607 identifier, store the lexeme of the identifier in SVAL. If
2608 scanning a number, store its value in *IVAL. */
2611 xbm_scan (s
, end
, sval
, ival
)
2612 unsigned char **s
, *end
;
2620 /* Skip white space. */
2621 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2626 else if (isdigit (c
))
2628 int value
= 0, digit
;
2630 if (c
== '0' && *s
< end
)
2633 if (c
== 'x' || c
== 'X')
2640 else if (c
>= 'a' && c
<= 'f')
2641 digit
= c
- 'a' + 10;
2642 else if (c
>= 'A' && c
<= 'F')
2643 digit
= c
- 'A' + 10;
2646 value
= 16 * value
+ digit
;
2649 else if (isdigit (c
))
2653 && (c
= *(*s
)++, isdigit (c
)))
2654 value
= 8 * value
+ c
- '0';
2661 && (c
= *(*s
)++, isdigit (c
)))
2662 value
= 10 * value
+ c
- '0';
2670 else if (isalpha (c
) || c
== '_')
2674 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2681 else if (c
== '/' && **s
== '*')
2683 /* C-style comment. */
2685 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2699 /* Create a Windows bitmap from X bitmap data. */
2701 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2703 static unsigned char swap_nibble
[16]
2704 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2705 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2706 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2707 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2709 unsigned char *bits
, *p
;
2712 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2713 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2714 bits
= (unsigned char *) alloca (height
* w2
);
2715 bzero (bits
, height
* w2
);
2716 for (i
= 0; i
< height
; i
++)
2719 for (j
= 0; j
< w1
; j
++)
2721 /* Bitswap XBM bytes to match how Windows does things. */
2722 unsigned char c
= *data
++;
2723 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2724 | (swap_nibble
[(c
>>4) & 0xf]));
2727 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2732 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
2735 COLORREF foreground
, background
;
2737 HDC hdc
, old_img_dc
, new_img_dc
;
2738 HGDIOBJ old_prev
, new_prev
;
2741 hdc
= get_frame_dc (f
);
2742 old_img_dc
= CreateCompatibleDC (hdc
);
2743 new_img_dc
= CreateCompatibleDC (hdc
);
2744 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2745 release_frame_dc (f
, hdc
);
2746 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2747 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2748 SetTextColor (new_img_dc
, foreground
);
2749 SetBkColor (new_img_dc
, background
);
2751 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2754 SelectObject (old_img_dc
, old_prev
);
2755 SelectObject (new_img_dc
, new_prev
);
2756 DeleteDC (old_img_dc
);
2757 DeleteDC (new_img_dc
);
2758 DeleteObject (img
->pixmap
);
2759 if (new_pixmap
== 0)
2760 fprintf (stderr
, "Failed to convert image to color.\n");
2762 img
->pixmap
= new_pixmap
;
2765 #define XBM_BIT_SHUFFLE(b) (~(b))
2769 #define XBM_BIT_SHUFFLE(b) (b)
2771 #endif /* HAVE_NTGUI */
2775 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
2779 RGB_PIXEL_COLOR fg
, bg
;
2780 int non_default_colors
;
2784 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2786 /* If colors were specified, transfer the bitmap to a color one. */
2787 if (non_default_colors
)
2788 convert_mono_to_color_image (f
, img
, fg
, bg
);
2791 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2794 img
->width
, img
->height
,
2796 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2797 #endif /* HAVE_NTGUI */
2802 /* Replacement for XReadBitmapFileData which isn't available under old
2803 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2804 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2805 the image. Return in *DATA the bitmap data allocated with xmalloc.
2806 Value is non-zero if successful. DATA null means just test if
2807 CONTENTS looks like an in-memory XBM file. */
2810 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
2811 unsigned char *contents
, *end
;
2812 int *width
, *height
;
2813 unsigned char **data
;
2815 unsigned char *s
= contents
;
2816 char buffer
[BUFSIZ
];
2819 int bytes_per_line
, i
, nbytes
;
2825 LA1 = xbm_scan (&s, end, buffer, &value)
2827 #define expect(TOKEN) \
2828 if (LA1 != (TOKEN)) \
2833 #define expect_ident(IDENT) \
2834 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2839 *width
= *height
= -1;
2842 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2844 /* Parse defines for width, height and hot-spots. */
2848 expect_ident ("define");
2849 expect (XBM_TK_IDENT
);
2851 if (LA1
== XBM_TK_NUMBER
);
2853 char *p
= strrchr (buffer
, '_');
2854 p
= p
? p
+ 1 : buffer
;
2855 if (strcmp (p
, "width") == 0)
2857 else if (strcmp (p
, "height") == 0)
2860 expect (XBM_TK_NUMBER
);
2863 if (*width
< 0 || *height
< 0)
2865 else if (data
== NULL
)
2868 /* Parse bits. Must start with `static'. */
2869 expect_ident ("static");
2870 if (LA1
== XBM_TK_IDENT
)
2872 if (strcmp (buffer
, "unsigned") == 0)
2875 expect_ident ("char");
2877 else if (strcmp (buffer
, "short") == 0)
2881 if (*width
% 16 && *width
% 16 < 9)
2884 else if (strcmp (buffer
, "char") == 0)
2892 expect (XBM_TK_IDENT
);
2898 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
2899 nbytes
= bytes_per_line
* *height
;
2900 p
= *data
= (char *) xmalloc (nbytes
);
2904 for (i
= 0; i
< nbytes
; i
+= 2)
2907 expect (XBM_TK_NUMBER
);
2909 *p
++ = XBM_BIT_SHUFFLE (val
);
2910 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
2911 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
2913 if (LA1
== ',' || LA1
== '}')
2921 for (i
= 0; i
< nbytes
; ++i
)
2924 expect (XBM_TK_NUMBER
);
2926 *p
++ = XBM_BIT_SHUFFLE (val
);
2928 if (LA1
== ',' || LA1
== '}')
2953 /* Load XBM image IMG which will be displayed on frame F from buffer
2954 CONTENTS. END is the end of the buffer. Value is non-zero if
2958 xbm_load_image (f
, img
, contents
, end
)
2961 unsigned char *contents
, *end
;
2964 unsigned char *data
;
2967 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
2970 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
2971 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
2972 int non_default_colors
= 0;
2975 xassert (img
->width
> 0 && img
->height
> 0);
2977 /* Get foreground and background colors, maybe allocate colors. */
2978 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
2981 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
2982 non_default_colors
= 1;
2984 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2987 background
= x_alloc_image_color (f
, img
, value
, background
);
2988 img
->background
= background
;
2989 img
->background_valid
= 1;
2990 non_default_colors
= 1;
2993 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
2994 foreground
, background
,
2995 non_default_colors
);
2998 if (img
->pixmap
== NO_PIXMAP
)
3000 x_clear_image (f
, img
);
3001 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3007 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3013 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3020 return (STRINGP (data
)
3021 && xbm_read_bitmap_data (SDATA (data
),
3028 /* Fill image IMG which is used on frame F with pixmap data. Value is
3029 non-zero if successful. */
3037 Lisp_Object file_name
;
3039 xassert (xbm_image_p (img
->spec
));
3041 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3042 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3043 if (STRINGP (file_name
))
3046 unsigned char *contents
;
3048 struct gcpro gcpro1
;
3050 file
= x_find_image_file (file_name
);
3052 if (!STRINGP (file
))
3054 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3059 contents
= slurp_file (SDATA (file
), &size
);
3060 if (contents
== NULL
)
3062 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3067 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3072 struct image_keyword fmt
[XBM_LAST
];
3074 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3075 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3076 int non_default_colors
= 0;
3079 int in_memory_file_p
= 0;
3081 /* See if data looks like an in-memory XBM file. */
3082 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3083 in_memory_file_p
= xbm_file_p (data
);
3085 /* Parse the image specification. */
3086 bcopy (xbm_format
, fmt
, sizeof fmt
);
3087 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3090 /* Get specified width, and height. */
3091 if (!in_memory_file_p
)
3093 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3094 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3095 xassert (img
->width
> 0 && img
->height
> 0);
3098 /* Get foreground and background colors, maybe allocate colors. */
3099 if (fmt
[XBM_FOREGROUND
].count
3100 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3102 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3104 non_default_colors
= 1;
3107 if (fmt
[XBM_BACKGROUND
].count
3108 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3110 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3112 non_default_colors
= 1;
3115 if (in_memory_file_p
)
3116 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3125 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3127 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3128 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3130 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3132 bcopy (SDATA (line
), p
, nbytes
);
3134 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3137 else if (STRINGP (data
))
3138 bits
= SDATA (data
);
3140 bits
= XBOOL_VECTOR (data
)->data
;
3142 /* Create the pixmap. */
3144 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3145 foreground
, background
,
3146 non_default_colors
);
3151 image_error ("Unable to create pixmap for XBM image `%s'",
3153 x_clear_image (f
, img
);
3163 /***********************************************************************
3165 ***********************************************************************/
3169 static int xpm_image_p
P_ ((Lisp_Object object
));
3170 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3171 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3174 /* Indicate to xpm.h that we don't have Xlib. */
3176 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3177 #define XColor xpm_XColor
3178 #define XImage xpm_XImage
3179 #define PIXEL_ALREADY_TYPEDEFED
3180 #include "X11/xpm.h"
3184 #undef PIXEL_ALREADY_TYPEDEFED
3186 #include "X11/xpm.h"
3187 #endif /* HAVE_NTGUI */
3189 /* The symbol `xpm' identifying XPM-format images. */
3193 /* Indices of image specification fields in xpm_format, below. */
3195 enum xpm_keyword_index
3211 /* Vector of image_keyword structures describing the format
3212 of valid XPM image specifications. */
3214 static struct image_keyword xpm_format
[XPM_LAST
] =
3216 {":type", IMAGE_SYMBOL_VALUE
, 1},
3217 {":file", IMAGE_STRING_VALUE
, 0},
3218 {":data", IMAGE_STRING_VALUE
, 0},
3219 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3220 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3221 {":relief", IMAGE_INTEGER_VALUE
, 0},
3222 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3223 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3224 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3225 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3226 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3229 /* Structure describing the image type XPM. */
3231 static struct image_type xpm_type
=
3240 #ifdef HAVE_X_WINDOWS
3242 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3243 functions for allocating image colors. Our own functions handle
3244 color allocation failures more gracefully than the ones on the XPM
3247 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3248 #define ALLOC_XPM_COLORS
3250 #endif /* HAVE_X_WINDOWS */
3252 #ifdef ALLOC_XPM_COLORS
3254 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3255 static void xpm_free_color_cache
P_ ((void));
3256 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3257 static int xpm_color_bucket
P_ ((char *));
3258 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3261 /* An entry in a hash table used to cache color definitions of named
3262 colors. This cache is necessary to speed up XPM image loading in
3263 case we do color allocations ourselves. Without it, we would need
3264 a call to XParseColor per pixel in the image. */
3266 struct xpm_cached_color
3268 /* Next in collision chain. */
3269 struct xpm_cached_color
*next
;
3271 /* Color definition (RGB and pixel color). */
3278 /* The hash table used for the color cache, and its bucket vector
3281 #define XPM_COLOR_CACHE_BUCKETS 1001
3282 struct xpm_cached_color
**xpm_color_cache
;
3284 /* Initialize the color cache. */
3287 xpm_init_color_cache (f
, attrs
)
3289 XpmAttributes
*attrs
;
3291 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3292 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3293 memset (xpm_color_cache
, 0, nbytes
);
3294 init_color_table ();
3296 if (attrs
->valuemask
& XpmColorSymbols
)
3301 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3302 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3303 attrs
->colorsymbols
[i
].value
, &color
))
3305 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3307 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3312 /* Free the color cache. */
3315 xpm_free_color_cache ()
3317 struct xpm_cached_color
*p
, *next
;
3320 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3321 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3327 xfree (xpm_color_cache
);
3328 xpm_color_cache
= NULL
;
3329 free_color_table ();
3332 /* Return the bucket index for color named COLOR_NAME in the color
3336 xpm_color_bucket (color_name
)
3342 for (s
= color_name
; *s
; ++s
)
3344 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3348 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3349 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3352 static struct xpm_cached_color
*
3353 xpm_cache_color (f
, color_name
, color
, bucket
)
3360 struct xpm_cached_color
*p
;
3363 bucket
= xpm_color_bucket (color_name
);
3365 nbytes
= sizeof *p
+ strlen (color_name
);
3366 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3367 strcpy (p
->name
, color_name
);
3369 p
->next
= xpm_color_cache
[bucket
];
3370 xpm_color_cache
[bucket
] = p
;
3374 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3375 return the cached definition in *COLOR. Otherwise, make a new
3376 entry in the cache and allocate the color. Value is zero if color
3377 allocation failed. */
3380 xpm_lookup_color (f
, color_name
, color
)
3385 struct xpm_cached_color
*p
;
3386 int h
= xpm_color_bucket (color_name
);
3388 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3389 if (strcmp (p
->name
, color_name
) == 0)
3394 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3397 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3399 p
= xpm_cache_color (f
, color_name
, color
, h
);
3401 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3402 with transparency, and it's useful. */
3403 else if (strcmp ("opaque", color_name
) == 0)
3405 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3406 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3407 p
= xpm_cache_color (f
, color_name
, color
, h
);
3414 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3415 CLOSURE is a pointer to the frame on which we allocate the
3416 color. Return in *COLOR the allocated color. Value is non-zero
3420 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3427 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3431 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3432 is a pointer to the frame on which we allocate the color. Value is
3433 non-zero if successful. */
3436 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3446 #endif /* ALLOC_XPM_COLORS */
3451 /* XPM library details. */
3453 DEF_IMGLIB_FN (XpmFreeAttributes
);
3454 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3455 DEF_IMGLIB_FN (XpmReadFileToImage
);
3456 DEF_IMGLIB_FN (XImageFree
);
3460 init_xpm_functions (void)
3464 if (!(library
= LoadLibrary ("libXpm.dll")))
3467 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3468 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3469 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3470 LOAD_IMGLIB_FN (library
, XImageFree
);
3474 #endif /* HAVE_NTGUI */
3477 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3478 for XPM images. Such a list must consist of conses whose car and
3482 xpm_valid_color_symbols_p (color_symbols
)
3483 Lisp_Object color_symbols
;
3485 while (CONSP (color_symbols
))
3487 Lisp_Object sym
= XCAR (color_symbols
);
3489 || !STRINGP (XCAR (sym
))
3490 || !STRINGP (XCDR (sym
)))
3492 color_symbols
= XCDR (color_symbols
);
3495 return NILP (color_symbols
);
3499 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3502 xpm_image_p (object
)
3505 struct image_keyword fmt
[XPM_LAST
];
3506 bcopy (xpm_format
, fmt
, sizeof fmt
);
3507 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3508 /* Either `:file' or `:data' must be present. */
3509 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3510 /* Either no `:color-symbols' or it's a list of conses
3511 whose car and cdr are strings. */
3512 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3513 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3517 /* Load image IMG which will be displayed on frame F. Value is
3518 non-zero if successful. */
3526 XpmAttributes attrs
;
3527 Lisp_Object specified_file
, color_symbols
;
3530 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3531 #endif /* HAVE_NTGUI */
3533 /* Configure the XPM lib. Use the visual of frame F. Allocate
3534 close colors. Return colors allocated. */
3535 bzero (&attrs
, sizeof attrs
);
3538 attrs
.visual
= FRAME_X_VISUAL (f
);
3539 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3540 attrs
.valuemask
|= XpmVisual
;
3541 attrs
.valuemask
|= XpmColormap
;
3542 #endif /* HAVE_NTGUI */
3544 #ifdef ALLOC_XPM_COLORS
3545 /* Allocate colors with our own functions which handle
3546 failing color allocation more gracefully. */
3547 attrs
.color_closure
= f
;
3548 attrs
.alloc_color
= xpm_alloc_color
;
3549 attrs
.free_colors
= xpm_free_colors
;
3550 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3551 #else /* not ALLOC_XPM_COLORS */
3552 /* Let the XPM lib allocate colors. */
3553 attrs
.valuemask
|= XpmReturnAllocPixels
;
3554 #ifdef XpmAllocCloseColors
3555 attrs
.alloc_close_colors
= 1;
3556 attrs
.valuemask
|= XpmAllocCloseColors
;
3557 #else /* not XpmAllocCloseColors */
3558 attrs
.closeness
= 600;
3559 attrs
.valuemask
|= XpmCloseness
;
3560 #endif /* not XpmAllocCloseColors */
3561 #endif /* ALLOC_XPM_COLORS */
3563 /* If image specification contains symbolic color definitions, add
3564 these to `attrs'. */
3565 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3566 if (CONSP (color_symbols
))
3569 XpmColorSymbol
*xpm_syms
;
3572 attrs
.valuemask
|= XpmColorSymbols
;
3574 /* Count number of symbols. */
3575 attrs
.numsymbols
= 0;
3576 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3579 /* Allocate an XpmColorSymbol array. */
3580 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3581 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3582 bzero (xpm_syms
, size
);
3583 attrs
.colorsymbols
= xpm_syms
;
3585 /* Fill the color symbol array. */
3586 for (tail
= color_symbols
, i
= 0;
3588 ++i
, tail
= XCDR (tail
))
3590 Lisp_Object name
= XCAR (XCAR (tail
));
3591 Lisp_Object color
= XCDR (XCAR (tail
));
3592 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3593 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3594 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3595 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3599 /* Create a pixmap for the image, either from a file, or from a
3600 string buffer containing data in the same format as an XPM file. */
3601 #ifdef ALLOC_XPM_COLORS
3602 xpm_init_color_cache (f
, &attrs
);
3605 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3609 HDC frame_dc
= get_frame_dc (f
);
3610 hdc
= CreateCompatibleDC (frame_dc
);
3611 release_frame_dc (f
, frame_dc
);
3613 #endif /* HAVE_NTGUI */
3615 if (STRINGP (specified_file
))
3617 Lisp_Object file
= x_find_image_file (specified_file
);
3618 if (!STRINGP (file
))
3620 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3625 /* XpmReadFileToPixmap is not available in the Windows port of
3626 libxpm. But XpmReadFileToImage almost does what we want. */
3627 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3628 &xpm_image
, &xpm_mask
,
3631 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3632 SDATA (file
), &img
->pixmap
, &img
->mask
,
3634 #endif /* HAVE_NTGUI */
3638 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3640 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3641 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3642 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3643 &xpm_image
, &xpm_mask
,
3646 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3648 &img
->pixmap
, &img
->mask
,
3650 #endif /* HAVE_NTGUI */
3653 if (rc
== XpmSuccess
)
3655 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3656 img
->colors
= colors_in_color_table (&img
->ncolors
);
3657 #else /* not ALLOC_XPM_COLORS */
3661 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3662 plus some duplicate attributes. */
3663 if (xpm_image
&& xpm_image
->bitmap
)
3665 img
->pixmap
= xpm_image
->bitmap
;
3666 /* XImageFree in libXpm frees XImage struct without destroying
3667 the bitmap, which is what we want. */
3668 fn_XImageFree (xpm_image
);
3670 if (xpm_mask
&& xpm_mask
->bitmap
)
3672 /* The mask appears to be inverted compared with what we expect.
3673 TODO: invert our expectations. See other places where we
3674 have to invert bits because our idea of masks is backwards. */
3676 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3678 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3679 SelectObject (hdc
, old_obj
);
3681 img
->mask
= xpm_mask
->bitmap
;
3682 fn_XImageFree (xpm_mask
);
3687 #endif /* HAVE_NTGUI */
3689 /* Remember allocated colors. */
3690 img
->ncolors
= attrs
.nalloc_pixels
;
3691 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3692 * sizeof *img
->colors
);
3693 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3695 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3696 #ifdef DEBUG_X_COLORS
3697 register_color (img
->colors
[i
]);
3700 #endif /* not ALLOC_XPM_COLORS */
3702 img
->width
= attrs
.width
;
3703 img
->height
= attrs
.height
;
3704 xassert (img
->width
> 0 && img
->height
> 0);
3706 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3708 fn_XpmFreeAttributes (&attrs
);
3710 XpmFreeAttributes (&attrs
);
3711 #endif /* HAVE_NTGUI */
3717 #endif /* HAVE_NTGUI */
3722 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3725 case XpmFileInvalid
:
3726 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3730 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3733 case XpmColorFailed
:
3734 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3738 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3743 #ifdef ALLOC_XPM_COLORS
3744 xpm_free_color_cache ();
3746 return rc
== XpmSuccess
;
3749 #endif /* HAVE_XPM */
3752 /***********************************************************************
3754 ***********************************************************************/
3756 #ifdef COLOR_TABLE_SUPPORT
3758 /* An entry in the color table mapping an RGB color to a pixel color. */
3763 unsigned long pixel
;
3765 /* Next in color table collision list. */
3766 struct ct_color
*next
;
3769 /* The bucket vector size to use. Must be prime. */
3773 /* Value is a hash of the RGB color given by R, G, and B. */
3775 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
3777 /* The color hash table. */
3779 struct ct_color
**ct_table
;
3781 /* Number of entries in the color table. */
3783 int ct_colors_allocated
;
3785 /* Initialize the color table. */
3790 int size
= CT_SIZE
* sizeof (*ct_table
);
3791 ct_table
= (struct ct_color
**) xmalloc (size
);
3792 bzero (ct_table
, size
);
3793 ct_colors_allocated
= 0;
3797 /* Free memory associated with the color table. */
3803 struct ct_color
*p
, *next
;
3805 for (i
= 0; i
< CT_SIZE
; ++i
)
3806 for (p
= ct_table
[i
]; p
; p
= next
)
3817 /* Value is a pixel color for RGB color R, G, B on frame F. If an
3818 entry for that color already is in the color table, return the
3819 pixel color of that entry. Otherwise, allocate a new color for R,
3820 G, B, and make an entry in the color table. */
3822 static unsigned long
3823 lookup_rgb_color (f
, r
, g
, b
)
3827 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
3828 int i
= hash
% CT_SIZE
;
3830 Display_Info
*dpyinfo
;
3832 /* Handle TrueColor visuals specially, which improves performance by
3833 two orders of magnitude. Freeing colors on TrueColor visuals is
3834 a nop, and pixel colors specify RGB values directly. See also
3835 the Xlib spec, chapter 3.1. */
3836 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3837 if (dpyinfo
->red_bits
> 0)
3839 unsigned long pr
, pg
, pb
;
3841 /* Apply gamma-correction like normal color allocation does. */
3845 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
3846 gamma_correct (f
, &color
);
3847 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
3850 /* Scale down RGB values to the visual's bits per RGB, and shift
3851 them to the right position in the pixel color. Note that the
3852 original RGB values are 16-bit values, as usual in X. */
3853 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
3854 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
3855 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
3857 /* Assemble the pixel color. */
3858 return pr
| pg
| pb
;
3861 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3862 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
3868 #ifdef HAVE_X_WINDOWS
3877 cmap
= FRAME_X_COLORMAP (f
);
3878 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3881 ++ct_colors_allocated
;
3882 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3886 p
->pixel
= color
.pixel
;
3887 p
->next
= ct_table
[i
];
3891 return FRAME_FOREGROUND_PIXEL (f
);
3896 color
= PALETTERGB (r
, g
, b
);
3898 color
= RGB_TO_ULONG (r
, g
, b
);
3899 #endif /* HAVE_NTGUI */
3900 ++ct_colors_allocated
;
3901 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3906 p
->next
= ct_table
[i
];
3908 #endif /* HAVE_X_WINDOWS */
3916 /* Look up pixel color PIXEL which is used on frame F in the color
3917 table. If not already present, allocate it. Value is PIXEL. */
3919 static unsigned long
3920 lookup_pixel_color (f
, pixel
)
3922 unsigned long pixel
;
3924 int i
= pixel
% CT_SIZE
;
3927 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3928 if (p
->pixel
== pixel
)
3937 #ifdef HAVE_X_WINDOWS
3938 cmap
= FRAME_X_COLORMAP (f
);
3939 color
.pixel
= pixel
;
3940 x_query_color (f
, &color
);
3941 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3944 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
3945 color
.pixel
= pixel
;
3946 XQueryColor (NULL
, cmap
, &color
);
3947 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3949 #endif /* HAVE_X_WINDOWS */
3953 ++ct_colors_allocated
;
3955 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3960 p
->next
= ct_table
[i
];
3964 return FRAME_FOREGROUND_PIXEL (f
);
3970 /* Value is a vector of all pixel colors contained in the color table,
3971 allocated via xmalloc. Set *N to the number of colors. */
3973 static unsigned long *
3974 colors_in_color_table (n
)
3979 unsigned long *colors
;
3981 if (ct_colors_allocated
== 0)
3988 colors
= (unsigned long *) xmalloc (ct_colors_allocated
3990 *n
= ct_colors_allocated
;
3992 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
3993 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3994 colors
[j
++] = p
->pixel
;
4000 #else /* COLOR_TABLE_SUPPORT */
4002 static unsigned long
4003 lookup_rgb_color (f
, r
, g
, b
)
4007 unsigned long pixel
;
4010 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4011 gamma_correct (f
, &pixel
);
4015 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4016 #endif /* HAVE_NTGUI */
4025 #endif /* COLOR_TABLE_SUPPORT */
4028 /***********************************************************************
4030 ***********************************************************************/
4032 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4033 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4034 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4037 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4038 #endif /* HAVE_NTGUI */
4040 /* Non-zero means draw a cross on images having `:conversion
4043 int cross_disabled_images
;
4045 /* Edge detection matrices for different edge-detection
4048 static int emboss_matrix
[9] = {
4050 2, -1, 0, /* y - 1 */
4052 0, 1, -2 /* y + 1 */
4055 static int laplace_matrix
[9] = {
4057 1, 0, 0, /* y - 1 */
4059 0, 0, -1 /* y + 1 */
4062 /* Value is the intensity of the color whose red/green/blue values
4065 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4068 /* On frame F, return an array of XColor structures describing image
4069 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4070 non-zero means also fill the red/green/blue members of the XColor
4071 structures. Value is a pointer to the array of XColors structures,
4072 allocated with xmalloc; it must be freed by the caller. */
4075 x_to_xcolors (f
, img
, rgb_p
)
4082 XImagePtr_or_DC ximg
;
4086 #endif /* HAVE_NTGUI */
4088 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4091 /* Get the X image IMG->pixmap. */
4092 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4093 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4095 /* Load the image into a memory device context. */
4096 hdc
= get_frame_dc (f
);
4097 ximg
= CreateCompatibleDC (hdc
);
4098 release_frame_dc (f
, hdc
);
4099 prev
= SelectObject (ximg
, img
->pixmap
);
4100 #endif /* HAVE_NTGUI */
4102 /* Fill the `pixel' members of the XColor array. I wished there
4103 were an easy and portable way to circumvent XGetPixel. */
4105 for (y
= 0; y
< img
->height
; ++y
)
4109 #ifdef HAVE_X_WINDOWS
4110 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4111 p
->pixel
= XGetPixel (ximg
, x
, y
);
4113 x_query_colors (f
, row
, img
->width
);
4117 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4119 /* W32_TODO: palette support needed here? */
4120 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4124 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4125 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4126 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4129 p
->red
= 256 * GetRValue (p
->pixel
);
4130 p
->green
= 256 * GetGValue (p
->pixel
);
4131 p
->blue
= 256 * GetBValue (p
->pixel
);
4132 #endif /* HAVE_NTGUI */
4135 #endif /* HAVE_X_WINDOWS */
4138 Destroy_Image (ximg
, prev
);
4145 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4146 created with CreateDIBSection, with the pointer to the bit values
4147 stored in ximg->data. */
4149 static void XPutPixel (ximg
, x
, y
, color
)
4154 int width
= ximg
->info
.bmiHeader
.biWidth
;
4155 int height
= ximg
->info
.bmiHeader
.biHeight
;
4156 unsigned char * pixel
;
4158 /* True color images. */
4159 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4161 int rowbytes
= width
* 3;
4162 /* Ensure scanlines are aligned on 4 byte boundaries. */
4164 rowbytes
+= 4 - (rowbytes
% 4);
4166 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4167 /* Windows bitmaps are in BGR order. */
4168 *pixel
= GetBValue (color
);
4169 *(pixel
+ 1) = GetGValue (color
);
4170 *(pixel
+ 2) = GetRValue (color
);
4172 /* Monochrome images. */
4173 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4175 int rowbytes
= width
/ 8;
4176 /* Ensure scanlines are aligned on 4 byte boundaries. */
4178 rowbytes
+= 4 - (rowbytes
% 4);
4179 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4180 /* Filter out palette info. */
4181 if (color
& 0x00ffffff)
4182 *pixel
= *pixel
| (1 << x
% 8);
4184 *pixel
= *pixel
& ~(1 << x
% 8);
4187 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4190 #endif /* HAVE_NTGUI */
4192 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4193 RGB members are set. F is the frame on which this all happens.
4194 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4197 x_from_xcolors (f
, img
, colors
)
4207 init_color_table ();
4209 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4212 for (y
= 0; y
< img
->height
; ++y
)
4213 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4215 unsigned long pixel
;
4216 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4217 XPutPixel (oimg
, x
, y
, pixel
);
4221 x_clear_image_1 (f
, img
, 1, 0, 1);
4223 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4224 x_destroy_x_image (oimg
);
4225 img
->pixmap
= pixmap
;
4226 #ifdef COLOR_TABLE_SUPPORT
4227 img
->colors
= colors_in_color_table (&img
->ncolors
);
4228 free_color_table ();
4229 #endif /* COLOR_TABLE_SUPPORT */
4233 /* On frame F, perform edge-detection on image IMG.
4235 MATRIX is a nine-element array specifying the transformation
4236 matrix. See emboss_matrix for an example.
4238 COLOR_ADJUST is a color adjustment added to each pixel of the
4242 x_detect_edges (f
, img
, matrix
, color_adjust
)
4245 int matrix
[9], color_adjust
;
4247 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4251 for (i
= sum
= 0; i
< 9; ++i
)
4252 sum
+= abs (matrix
[i
]);
4254 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4256 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4258 for (y
= 0; y
< img
->height
; ++y
)
4260 p
= COLOR (new, 0, y
);
4261 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4262 p
= COLOR (new, img
->width
- 1, y
);
4263 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4266 for (x
= 1; x
< img
->width
- 1; ++x
)
4268 p
= COLOR (new, x
, 0);
4269 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4270 p
= COLOR (new, x
, img
->height
- 1);
4271 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4274 for (y
= 1; y
< img
->height
- 1; ++y
)
4276 p
= COLOR (new, 1, y
);
4278 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4280 int r
, g
, b
, y1
, x1
;
4283 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4284 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4287 XColor
*t
= COLOR (colors
, x1
, y1
);
4288 r
+= matrix
[i
] * t
->red
;
4289 g
+= matrix
[i
] * t
->green
;
4290 b
+= matrix
[i
] * t
->blue
;
4293 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4294 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4295 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4296 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4301 x_from_xcolors (f
, img
, new);
4307 /* Perform the pre-defined `emboss' edge-detection on image IMG
4315 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4319 /* Transform image IMG which is used on frame F with a Laplace
4320 edge-detection algorithm. The result is an image that can be used
4321 to draw disabled buttons, for example. */
4328 x_detect_edges (f
, img
, laplace_matrix
, 45000);
4332 /* Perform edge-detection on image IMG on frame F, with specified
4333 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4335 MATRIX must be either
4337 - a list of at least 9 numbers in row-major form
4338 - a vector of at least 9 numbers
4340 COLOR_ADJUST nil means use a default; otherwise it must be a
4344 x_edge_detection (f
, img
, matrix
, color_adjust
)
4347 Lisp_Object matrix
, color_adjust
;
4355 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
4356 ++i
, matrix
= XCDR (matrix
))
4357 trans
[i
] = XFLOATINT (XCAR (matrix
));
4359 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
4361 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
4362 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
4365 if (NILP (color_adjust
))
4366 color_adjust
= make_number (0xffff / 2);
4368 if (i
== 9 && NUMBERP (color_adjust
))
4369 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
4373 /* Transform image IMG on frame F so that it looks disabled. */
4376 x_disable_image (f
, img
)
4380 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4382 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
4384 int n_planes
= dpyinfo
->n_planes
;
4385 #endif /* HAVE_NTGUI */
4389 /* Color (or grayscale). Convert to gray, and equalize. Just
4390 drawing such images with a stipple can look very odd, so
4391 we're using this method instead. */
4392 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4394 const int h
= 15000;
4395 const int l
= 30000;
4397 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
4401 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
4402 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
4403 p
->red
= p
->green
= p
->blue
= i2
;
4406 x_from_xcolors (f
, img
, colors
);
4409 /* Draw a cross over the disabled image, if we must or if we
4411 if (n_planes
< 2 || cross_disabled_images
)
4414 Display
*dpy
= FRAME_X_DISPLAY (f
);
4418 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4419 #define MaskForeground(f) PIX_MASK_DRAW (f)
4421 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4422 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4425 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
4426 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
4427 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
4428 img
->width
- 1, img
->height
- 1);
4429 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
4435 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
4436 XSetForeground (dpy
, gc
, MaskForeground (f
));
4437 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
4438 img
->width
- 1, img
->height
- 1);
4439 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
4447 hdc
= get_frame_dc (f
);
4448 bmpdc
= CreateCompatibleDC (hdc
);
4449 release_frame_dc (f
, hdc
);
4451 prev
= SelectObject (bmpdc
, img
->pixmap
);
4453 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
4454 MoveToEx (bmpdc
, 0, 0, NULL
);
4455 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4456 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4457 LineTo (bmpdc
, img
->width
- 1, 0);
4461 SelectObject (bmpdc
, img
->mask
);
4462 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
4463 MoveToEx (bmpdc
, 0, 0, NULL
);
4464 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4465 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4466 LineTo (bmpdc
, img
->width
- 1, 0);
4468 SelectObject (bmpdc
, prev
);
4470 #endif /* HAVE_NTGUI */
4475 /* Build a mask for image IMG which is used on frame F. FILE is the
4476 name of an image file, for error messages. HOW determines how to
4477 determine the background color of IMG. If it is a list '(R G B)',
4478 with R, G, and B being integers >= 0, take that as the color of the
4479 background. Otherwise, determine the background color of IMG
4480 heuristically. Value is non-zero if successful. */
4483 x_build_heuristic_mask (f
, img
, how
)
4488 XImagePtr_or_DC ximg
;
4496 #endif /* HAVE_NTGUI */
4497 int x
, y
, rc
, use_img_background
;
4498 unsigned long bg
= 0;
4502 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4503 img
->mask
= NO_PIXMAP
;
4504 img
->background_transparent_valid
= 0;
4508 /* Create an image and pixmap serving as mask. */
4509 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
4510 &mask_img
, &img
->mask
);
4514 /* Get the X image of IMG->pixmap. */
4515 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
4516 img
->width
, img
->height
,
4519 /* Create the bit array serving as mask. */
4520 row_width
= (img
->width
+ 7) / 8;
4521 mask_img
= xmalloc (row_width
* img
->height
);
4522 bzero (mask_img
, row_width
* img
->height
);
4524 /* Create a memory device context for IMG->pixmap. */
4525 frame_dc
= get_frame_dc (f
);
4526 ximg
= CreateCompatibleDC (frame_dc
);
4527 release_frame_dc (f
, frame_dc
);
4528 prev
= SelectObject (ximg
, img
->pixmap
);
4529 #endif /* HAVE_NTGUI */
4531 /* Determine the background color of ximg. If HOW is `(R G B)'
4532 take that as color. Otherwise, use the image's background color. */
4533 use_img_background
= 1;
4539 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
4541 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
4545 if (i
== 3 && NILP (how
))
4547 char color_name
[30];
4548 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
4551 0x00ffffff & /* Filter out palette info. */
4552 #endif /* HAVE_NTGUI */
4553 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
4554 use_img_background
= 0;
4558 if (use_img_background
)
4559 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
4561 /* Set all bits in mask_img to 1 whose color in ximg is different
4562 from the background color bg. */
4564 for (y
= 0; y
< img
->height
; ++y
)
4565 for (x
= 0; x
< img
->width
; ++x
)
4566 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
4567 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
)));
4569 /* Fill in the background_transparent field while we have the mask handy. */
4570 image_background_transparent (img
, f
, mask_img
);
4572 /* Put mask_img into img->mask. */
4573 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
4574 x_destroy_x_image (mask_img
);
4577 for (y
= 0; y
< img
->height
; ++y
)
4578 for (x
= 0; x
< img
->width
; ++x
)
4580 COLORREF p
= GetPixel (ximg
, x
, y
);
4582 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
4585 /* Create the mask image. */
4586 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
4588 /* Fill in the background_transparent field while we have the mask handy. */
4589 SelectObject (ximg
, img
->mask
);
4590 image_background_transparent (img
, f
, ximg
);
4592 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
4594 #endif /* HAVE_NTGUI */
4596 Destroy_Image (ximg
, prev
);
4602 /***********************************************************************
4603 PBM (mono, gray, color)
4604 ***********************************************************************/
4606 static int pbm_image_p
P_ ((Lisp_Object object
));
4607 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
4608 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
4610 /* The symbol `pbm' identifying images of this type. */
4614 /* Indices of image specification fields in gs_format, below. */
4616 enum pbm_keyword_index
4632 /* Vector of image_keyword structures describing the format
4633 of valid user-defined image specifications. */
4635 static struct image_keyword pbm_format
[PBM_LAST
] =
4637 {":type", IMAGE_SYMBOL_VALUE
, 1},
4638 {":file", IMAGE_STRING_VALUE
, 0},
4639 {":data", IMAGE_STRING_VALUE
, 0},
4640 {":ascent", IMAGE_ASCENT_VALUE
, 0},
4641 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
4642 {":relief", IMAGE_INTEGER_VALUE
, 0},
4643 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4644 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4645 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4646 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
4647 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
4650 /* Structure describing the image type `pbm'. */
4652 static struct image_type pbm_type
=
4662 /* Return non-zero if OBJECT is a valid PBM image specification. */
4665 pbm_image_p (object
)
4668 struct image_keyword fmt
[PBM_LAST
];
4670 bcopy (pbm_format
, fmt
, sizeof fmt
);
4672 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
4675 /* Must specify either :data or :file. */
4676 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
4680 /* Scan a decimal number from *S and return it. Advance *S while
4681 reading the number. END is the end of the string. Value is -1 at
4685 pbm_scan_number (s
, end
)
4686 unsigned char **s
, *end
;
4688 int c
= 0, val
= -1;
4692 /* Skip white-space. */
4693 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4698 /* Skip comment to end of line. */
4699 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
4702 else if (isdigit (c
))
4704 /* Read decimal number. */
4706 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
4707 val
= 10 * val
+ c
- '0';
4719 #if 0 /* Unused. ++kfs */
4721 /* Read FILE into memory. Value is a pointer to a buffer allocated
4722 with xmalloc holding FILE's contents. Value is null if an error
4723 occurred. *SIZE is set to the size of the file. */
4726 pbm_read_file (file
, size
)
4734 if (stat (SDATA (file
), &st
) == 0
4735 && (fp
= fopen (SDATA (file
), "rb")) != NULL
4736 && (buf
= (char *) xmalloc (st
.st_size
),
4737 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
4756 #endif /* HAVE_NTGUI */
4758 /* Load PBM image IMG for use on frame F. */
4766 int width
, height
, max_color_idx
= 0;
4768 Lisp_Object file
, specified_file
;
4769 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
4770 struct gcpro gcpro1
;
4771 unsigned char *contents
= NULL
;
4772 unsigned char *end
, *p
;
4775 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4779 if (STRINGP (specified_file
))
4781 file
= x_find_image_file (specified_file
);
4782 if (!STRINGP (file
))
4784 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4789 contents
= slurp_file (SDATA (file
), &size
);
4790 if (contents
== NULL
)
4792 image_error ("Error reading `%s'", file
, Qnil
);
4798 end
= contents
+ size
;
4803 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4805 end
= p
+ SBYTES (data
);
4808 /* Check magic number. */
4809 if (end
- p
< 2 || *p
++ != 'P')
4811 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
4821 raw_p
= 0, type
= PBM_MONO
;
4825 raw_p
= 0, type
= PBM_GRAY
;
4829 raw_p
= 0, type
= PBM_COLOR
;
4833 raw_p
= 1, type
= PBM_MONO
;
4837 raw_p
= 1, type
= PBM_GRAY
;
4841 raw_p
= 1, type
= PBM_COLOR
;
4845 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
4849 /* Read width, height, maximum color-component. Characters
4850 starting with `#' up to the end of a line are ignored. */
4851 width
= pbm_scan_number (&p
, end
);
4852 height
= pbm_scan_number (&p
, end
);
4854 if (type
!= PBM_MONO
)
4856 max_color_idx
= pbm_scan_number (&p
, end
);
4857 if (raw_p
&& max_color_idx
> 255)
4858 max_color_idx
= 255;
4863 || (type
!= PBM_MONO
&& max_color_idx
< 0))
4866 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4867 &ximg
, &img
->pixmap
))
4870 /* Initialize the color hash table. */
4871 init_color_table ();
4873 if (type
== PBM_MONO
)
4876 struct image_keyword fmt
[PBM_LAST
];
4877 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
4878 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
4880 /* Parse the image specification. */
4881 bcopy (pbm_format
, fmt
, sizeof fmt
);
4882 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
4884 /* Get foreground and background colors, maybe allocate colors. */
4885 if (fmt
[PBM_FOREGROUND
].count
4886 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
4887 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
4888 if (fmt
[PBM_BACKGROUND
].count
4889 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
4891 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
4892 img
->background
= bg
;
4893 img
->background_valid
= 1;
4896 for (y
= 0; y
< height
; ++y
)
4897 for (x
= 0; x
< width
; ++x
)
4907 g
= pbm_scan_number (&p
, end
);
4909 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
4914 for (y
= 0; y
< height
; ++y
)
4915 for (x
= 0; x
< width
; ++x
)
4919 if (type
== PBM_GRAY
)
4920 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
4929 r
= pbm_scan_number (&p
, end
);
4930 g
= pbm_scan_number (&p
, end
);
4931 b
= pbm_scan_number (&p
, end
);
4934 if (r
< 0 || g
< 0 || b
< 0)
4936 x_destroy_x_image (ximg
);
4937 image_error ("Invalid pixel value in image `%s'",
4942 /* RGB values are now in the range 0..max_color_idx.
4943 Scale this to the range 0..0xffff supported by X. */
4944 r
= (double) r
* 65535 / max_color_idx
;
4945 g
= (double) g
* 65535 / max_color_idx
;
4946 b
= (double) b
* 65535 / max_color_idx
;
4947 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
4951 #ifdef COLOR_TABLE_SUPPORT
4952 /* Store in IMG->colors the colors allocated for the image, and
4953 free the color table. */
4954 img
->colors
= colors_in_color_table (&img
->ncolors
);
4955 free_color_table ();
4956 #endif /* COLOR_TABLE_SUPPORT */
4959 img
->height
= height
;
4961 /* Maybe fill in the background field while we have ximg handy. */
4963 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4964 IMAGE_BACKGROUND (img
, f
, ximg
);
4966 /* Put the image into a pixmap. */
4967 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4968 x_destroy_x_image (ximg
);
4970 /* X and W32 versions did it here, MAC version above. ++kfs
4972 img->height = height; */
4980 /***********************************************************************
4982 ***********************************************************************/
4984 #if defined (HAVE_PNG) || defined (MAC_OS)
4986 /* Function prototypes. */
4988 static int png_image_p
P_ ((Lisp_Object object
));
4989 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
4991 /* The symbol `png' identifying images of this type. */
4995 /* Indices of image specification fields in png_format, below. */
4997 enum png_keyword_index
5012 /* Vector of image_keyword structures describing the format
5013 of valid user-defined image specifications. */
5015 static struct image_keyword png_format
[PNG_LAST
] =
5017 {":type", IMAGE_SYMBOL_VALUE
, 1},
5018 {":data", IMAGE_STRING_VALUE
, 0},
5019 {":file", IMAGE_STRING_VALUE
, 0},
5020 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5021 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5022 {":relief", IMAGE_INTEGER_VALUE
, 0},
5023 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5024 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5025 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5026 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5029 /* Structure describing the image type `png'. */
5031 static struct image_type png_type
=
5040 /* Return non-zero if OBJECT is a valid PNG image specification. */
5043 png_image_p (object
)
5046 struct image_keyword fmt
[PNG_LAST
];
5047 bcopy (png_format
, fmt
, sizeof fmt
);
5049 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5052 /* Must specify either the :data or :file keyword. */
5053 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5056 #endif /* HAVE_PNG || MAC_OS */
5061 #if defined HAVE_LIBPNG_PNG_H
5062 # include <libpng/png.h>
5068 /* PNG library details. */
5070 DEF_IMGLIB_FN (png_get_io_ptr
);
5071 DEF_IMGLIB_FN (png_check_sig
);
5072 DEF_IMGLIB_FN (png_create_read_struct
);
5073 DEF_IMGLIB_FN (png_create_info_struct
);
5074 DEF_IMGLIB_FN (png_destroy_read_struct
);
5075 DEF_IMGLIB_FN (png_set_read_fn
);
5076 DEF_IMGLIB_FN (png_init_io
);
5077 DEF_IMGLIB_FN (png_set_sig_bytes
);
5078 DEF_IMGLIB_FN (png_read_info
);
5079 DEF_IMGLIB_FN (png_get_IHDR
);
5080 DEF_IMGLIB_FN (png_get_valid
);
5081 DEF_IMGLIB_FN (png_set_strip_16
);
5082 DEF_IMGLIB_FN (png_set_expand
);
5083 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5084 DEF_IMGLIB_FN (png_set_background
);
5085 DEF_IMGLIB_FN (png_get_bKGD
);
5086 DEF_IMGLIB_FN (png_read_update_info
);
5087 DEF_IMGLIB_FN (png_get_channels
);
5088 DEF_IMGLIB_FN (png_get_rowbytes
);
5089 DEF_IMGLIB_FN (png_read_image
);
5090 DEF_IMGLIB_FN (png_read_end
);
5091 DEF_IMGLIB_FN (png_error
);
5094 init_png_functions (void)
5098 /* Ensure zlib is loaded. Try debug version first. */
5099 if (!LoadLibrary ("zlibd.dll")
5100 && !LoadLibrary ("zlib.dll"))
5103 /* Try loading libpng under probable names. */
5104 if (!(library
= LoadLibrary ("libpng13d.dll"))
5105 && !(library
= LoadLibrary ("libpng13.dll"))
5106 && !(library
= LoadLibrary ("libpng12d.dll"))
5107 && !(library
= LoadLibrary ("libpng12.dll"))
5108 && !(library
= LoadLibrary ("libpng.dll")))
5111 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5112 LOAD_IMGLIB_FN (library
, png_check_sig
);
5113 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5114 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5115 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5116 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5117 LOAD_IMGLIB_FN (library
, png_init_io
);
5118 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5119 LOAD_IMGLIB_FN (library
, png_read_info
);
5120 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5121 LOAD_IMGLIB_FN (library
, png_get_valid
);
5122 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5123 LOAD_IMGLIB_FN (library
, png_set_expand
);
5124 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5125 LOAD_IMGLIB_FN (library
, png_set_background
);
5126 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5127 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5128 LOAD_IMGLIB_FN (library
, png_get_channels
);
5129 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5130 LOAD_IMGLIB_FN (library
, png_read_image
);
5131 LOAD_IMGLIB_FN (library
, png_read_end
);
5132 LOAD_IMGLIB_FN (library
, png_error
);
5137 #define fn_png_get_io_ptr png_get_io_ptr
5138 #define fn_png_check_sig png_check_sig
5139 #define fn_png_create_read_struct png_create_read_struct
5140 #define fn_png_create_info_struct png_create_info_struct
5141 #define fn_png_destroy_read_struct png_destroy_read_struct
5142 #define fn_png_set_read_fn png_set_read_fn
5143 #define fn_png_init_io png_init_io
5144 #define fn_png_set_sig_bytes png_set_sig_bytes
5145 #define fn_png_read_info png_read_info
5146 #define fn_png_get_IHDR png_get_IHDR
5147 #define fn_png_get_valid png_get_valid
5148 #define fn_png_set_strip_16 png_set_strip_16
5149 #define fn_png_set_expand png_set_expand
5150 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5151 #define fn_png_set_background png_set_background
5152 #define fn_png_get_bKGD png_get_bKGD
5153 #define fn_png_read_update_info png_read_update_info
5154 #define fn_png_get_channels png_get_channels
5155 #define fn_png_get_rowbytes png_get_rowbytes
5156 #define fn_png_read_image png_read_image
5157 #define fn_png_read_end png_read_end
5158 #define fn_png_error png_error
5160 #endif /* HAVE_NTGUI */
5162 /* Error and warning handlers installed when the PNG library
5166 my_png_error (png_ptr
, msg
)
5167 png_struct
*png_ptr
;
5170 xassert (png_ptr
!= NULL
);
5171 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5172 longjmp (png_ptr
->jmpbuf
, 1);
5177 my_png_warning (png_ptr
, msg
)
5178 png_struct
*png_ptr
;
5181 xassert (png_ptr
!= NULL
);
5182 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5185 /* Memory source for PNG decoding. */
5187 struct png_memory_storage
5189 unsigned char *bytes
; /* The data */
5190 size_t len
; /* How big is it? */
5191 int index
; /* Where are we? */
5195 /* Function set as reader function when reading PNG image from memory.
5196 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5197 bytes from the input to DATA. */
5200 png_read_from_memory (png_ptr
, data
, length
)
5201 png_structp png_ptr
;
5205 struct png_memory_storage
*tbr
5206 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5208 if (length
> tbr
->len
- tbr
->index
)
5209 fn_png_error (png_ptr
, "Read error");
5211 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5212 tbr
->index
= tbr
->index
+ length
;
5215 /* Load PNG image IMG for use on frame F. Value is non-zero if
5223 Lisp_Object file
, specified_file
;
5224 Lisp_Object specified_data
;
5226 XImagePtr ximg
, mask_img
= NULL
;
5227 struct gcpro gcpro1
;
5228 png_struct
*png_ptr
= NULL
;
5229 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5230 FILE *volatile fp
= NULL
;
5232 png_byte
* volatile pixels
= NULL
;
5233 png_byte
** volatile rows
= NULL
;
5234 png_uint_32 width
, height
;
5235 int bit_depth
, color_type
, interlace_type
;
5237 png_uint_32 row_bytes
;
5239 double screen_gamma
;
5240 struct png_memory_storage tbr
; /* Data to be read */
5242 /* Find out what file to load. */
5243 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5244 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5248 if (NILP (specified_data
))
5250 file
= x_find_image_file (specified_file
);
5251 if (!STRINGP (file
))
5253 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5258 /* Open the image file. */
5259 fp
= fopen (SDATA (file
), "rb");
5262 image_error ("Cannot open image file `%s'", file
, Qnil
);
5268 /* Check PNG signature. */
5269 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5270 || !fn_png_check_sig (sig
, sizeof sig
))
5272 image_error ("Not a PNG file: `%s'", file
, Qnil
);
5280 /* Read from memory. */
5281 tbr
.bytes
= SDATA (specified_data
);
5282 tbr
.len
= SBYTES (specified_data
);
5285 /* Check PNG signature. */
5286 if (tbr
.len
< sizeof sig
5287 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
5289 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
5294 /* Need to skip past the signature. */
5295 tbr
.bytes
+= sizeof (sig
);
5298 /* Initialize read and info structs for PNG lib. */
5299 png_ptr
= fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
5300 my_png_error
, my_png_warning
);
5303 if (fp
) fclose (fp
);
5308 info_ptr
= fn_png_create_info_struct (png_ptr
);
5311 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
5312 if (fp
) fclose (fp
);
5317 end_info
= fn_png_create_info_struct (png_ptr
);
5320 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
5321 if (fp
) fclose (fp
);
5326 /* Set error jump-back. We come back here when the PNG library
5327 detects an error. */
5328 if (setjmp (png_ptr
->jmpbuf
))
5332 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5335 if (fp
) fclose (fp
);
5340 /* Read image info. */
5341 if (!NILP (specified_data
))
5342 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
5344 fn_png_init_io (png_ptr
, fp
);
5346 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
5347 fn_png_read_info (png_ptr
, info_ptr
);
5348 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
5349 &interlace_type
, NULL
, NULL
);
5351 /* If image contains simply transparency data, we prefer to
5352 construct a clipping mask. */
5353 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
5358 /* This function is easier to write if we only have to handle
5359 one data format: RGB or RGBA with 8 bits per channel. Let's
5360 transform other formats into that format. */
5362 /* Strip more than 8 bits per channel. */
5363 if (bit_depth
== 16)
5364 fn_png_set_strip_16 (png_ptr
);
5366 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5368 fn_png_set_expand (png_ptr
);
5370 /* Convert grayscale images to RGB. */
5371 if (color_type
== PNG_COLOR_TYPE_GRAY
5372 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5373 fn_png_set_gray_to_rgb (png_ptr
);
5375 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
5377 #if 0 /* Avoid double gamma correction for PNG images. */
5378 { /* Tell the PNG lib to handle gamma correction for us. */
5381 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5382 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
5383 /* The libpng documentation says this is right in this case. */
5384 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5387 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
5388 /* Image contains gamma information. */
5389 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
5391 /* Use the standard default for the image gamma. */
5392 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5396 /* Handle alpha channel by combining the image with a background
5397 color. Do this only if a real alpha channel is supplied. For
5398 simple transparency, we prefer a clipping mask. */
5401 png_color_16
*image_bg
;
5402 Lisp_Object specified_bg
5403 = image_spec_value (img
->spec
, QCbackground
, NULL
);
5405 if (STRINGP (specified_bg
))
5406 /* The user specified `:background', use that. */
5408 /* W32 version incorrectly used COLORREF here!! ++kfs */
5410 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
5412 png_color_16 user_bg
;
5414 bzero (&user_bg
, sizeof user_bg
);
5415 user_bg
.red
= color
.red
>> PNG_BG_COLOR_SHIFT
;
5416 user_bg
.green
= color
.green
>> PNG_BG_COLOR_SHIFT
;
5417 user_bg
.blue
= color
.blue
>> PNG_BG_COLOR_SHIFT
;
5419 fn_png_set_background (png_ptr
, &user_bg
,
5420 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5423 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
5424 /* Image contains a background color with which to
5425 combine the image. */
5426 fn_png_set_background (png_ptr
, image_bg
,
5427 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
5430 /* Image does not contain a background color with which
5431 to combine the image data via an alpha channel. Use
5432 the frame's background instead. */
5433 #ifdef HAVE_X_WINDOWS
5435 png_color_16 frame_background
;
5437 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
5438 x_query_color (f
, &color
);
5440 bzero (&frame_background
, sizeof frame_background
);
5441 frame_background
.red
= color
.red
;
5442 frame_background
.green
= color
.green
;
5443 frame_background
.blue
= color
.blue
;
5444 #endif /* HAVE_X_WINDOWS */
5448 png_color_16 frame_background
;
5449 color
= FRAME_BACKGROUND_PIXEL (f
);
5450 #if 0 /* W32 TODO : Colormap support. */
5451 x_query_color (f
, &color
);
5453 bzero (&frame_background
, sizeof frame_background
);
5454 frame_background
.red
= 256 * GetRValue (color
);
5455 frame_background
.green
= 256 * GetGValue (color
);
5456 frame_background
.blue
= 256 * GetBValue (color
);
5457 #endif /* HAVE_NTGUI */
5460 unsigned long color
;
5461 png_color_16 frame_background
;
5462 color
= FRAME_BACKGROUND_PIXEL (f
);
5463 #if 0 /* MAC/W32 TODO : Colormap support. */
5464 x_query_color (f
, &color
);
5466 bzero (&frame_background
, sizeof frame_background
);
5467 frame_background
.red
= RED_FROM_ULONG (color
);
5468 frame_background
.green
= GREEN_FROM_ULONG (color
);
5469 frame_background
.blue
= BLUE_FROM_ULONG (color
);
5472 fn_png_set_background (png_ptr
, &frame_background
,
5473 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5477 /* Update info structure. */
5478 fn_png_read_update_info (png_ptr
, info_ptr
);
5480 /* Get number of channels. Valid values are 1 for grayscale images
5481 and images with a palette, 2 for grayscale images with transparency
5482 information (alpha channel), 3 for RGB images, and 4 for RGB
5483 images with alpha channel, i.e. RGBA. If conversions above were
5484 sufficient we should only have 3 or 4 channels here. */
5485 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
5486 xassert (channels
== 3 || channels
== 4);
5488 /* Number of bytes needed for one row of the image. */
5489 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
5491 /* Allocate memory for the image. */
5492 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
5493 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
5494 for (i
= 0; i
< height
; ++i
)
5495 rows
[i
] = pixels
+ i
* row_bytes
;
5497 /* Read the entire image. */
5498 fn_png_read_image (png_ptr
, rows
);
5499 fn_png_read_end (png_ptr
, info_ptr
);
5506 /* Create the X image and pixmap. */
5507 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
5511 /* Create an image and pixmap serving as mask if the PNG image
5512 contains an alpha channel. */
5515 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
5516 &mask_img
, &img
->mask
))
5518 x_destroy_x_image (ximg
);
5519 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5520 img
->pixmap
= NO_PIXMAP
;
5524 /* Fill the X image and mask from PNG data. */
5525 init_color_table ();
5527 for (y
= 0; y
< height
; ++y
)
5529 png_byte
*p
= rows
[y
];
5531 for (x
= 0; x
< width
; ++x
)
5538 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5539 /* An alpha channel, aka mask channel, associates variable
5540 transparency with an image. Where other image formats
5541 support binary transparency---fully transparent or fully
5542 opaque---PNG allows up to 254 levels of partial transparency.
5543 The PNG library implements partial transparency by combining
5544 the image with a specified background color.
5546 I'm not sure how to handle this here nicely: because the
5547 background on which the image is displayed may change, for
5548 real alpha channel support, it would be necessary to create
5549 a new image for each possible background.
5551 What I'm doing now is that a mask is created if we have
5552 boolean transparency information. Otherwise I'm using
5553 the frame's background color to combine the image with. */
5558 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
5564 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5565 /* Set IMG's background color from the PNG image, unless the user
5569 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
5571 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
5572 img
->background_valid
= 1;
5576 #ifdef COLOR_TABLE_SUPPORT
5577 /* Remember colors allocated for this image. */
5578 img
->colors
= colors_in_color_table (&img
->ncolors
);
5579 free_color_table ();
5580 #endif /* COLOR_TABLE_SUPPORT */
5583 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5588 img
->height
= height
;
5590 /* Maybe fill in the background field while we have ximg handy. */
5591 IMAGE_BACKGROUND (img
, f
, ximg
);
5593 /* Put the image into the pixmap, then free the X image and its buffer. */
5594 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5595 x_destroy_x_image (ximg
);
5597 /* Same for the mask. */
5600 /* Fill in the background_transparent field while we have the mask
5602 image_background_transparent (img
, f
, mask_img
);
5604 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5605 x_destroy_x_image (mask_img
);
5612 #else /* HAVE_PNG */
5621 if (MyCGImageCreateWithPNGDataProvider
)
5622 return image_load_quartz2d (f
, img
, 1);
5625 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
5629 #endif /* !HAVE_PNG */
5633 /***********************************************************************
5635 ***********************************************************************/
5637 #if defined (HAVE_JPEG) || defined (MAC_OS)
5639 static int jpeg_image_p
P_ ((Lisp_Object object
));
5640 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
5642 /* The symbol `jpeg' identifying images of this type. */
5646 /* Indices of image specification fields in gs_format, below. */
5648 enum jpeg_keyword_index
5657 JPEG_HEURISTIC_MASK
,
5663 /* Vector of image_keyword structures describing the format
5664 of valid user-defined image specifications. */
5666 static struct image_keyword jpeg_format
[JPEG_LAST
] =
5668 {":type", IMAGE_SYMBOL_VALUE
, 1},
5669 {":data", IMAGE_STRING_VALUE
, 0},
5670 {":file", IMAGE_STRING_VALUE
, 0},
5671 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5672 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5673 {":relief", IMAGE_INTEGER_VALUE
, 0},
5674 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5675 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5676 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5677 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5680 /* Structure describing the image type `jpeg'. */
5682 static struct image_type jpeg_type
=
5691 /* Return non-zero if OBJECT is a valid JPEG image specification. */
5694 jpeg_image_p (object
)
5697 struct image_keyword fmt
[JPEG_LAST
];
5699 bcopy (jpeg_format
, fmt
, sizeof fmt
);
5701 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
5704 /* Must specify either the :data or :file keyword. */
5705 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
5708 #endif /* HAVE_JPEG || MAC_OS */
5712 /* Work around a warning about HAVE_STDLIB_H being redefined in
5714 #ifdef HAVE_STDLIB_H
5715 #define HAVE_STDLIB_H_1
5716 #undef HAVE_STDLIB_H
5717 #endif /* HAVE_STLIB_H */
5719 #include <jpeglib.h>
5723 #ifdef HAVE_STLIB_H_1
5724 #define HAVE_STDLIB_H 1
5729 /* JPEG library details. */
5730 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
5731 DEF_IMGLIB_FN (jpeg_start_decompress
);
5732 DEF_IMGLIB_FN (jpeg_finish_decompress
);
5733 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
5734 DEF_IMGLIB_FN (jpeg_read_header
);
5735 DEF_IMGLIB_FN (jpeg_read_scanlines
);
5736 DEF_IMGLIB_FN (jpeg_stdio_src
);
5737 DEF_IMGLIB_FN (jpeg_std_error
);
5738 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
5741 init_jpeg_functions (void)
5745 if (!(library
= LoadLibrary ("libjpeg.dll"))
5746 && !(library
= LoadLibrary ("jpeg-62.dll"))
5747 && !(library
= LoadLibrary ("jpeg.dll")))
5750 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
5751 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
5752 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
5753 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
5754 LOAD_IMGLIB_FN (library
, jpeg_stdio_src
);
5755 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
5756 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
5757 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
5758 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
5762 /* Wrapper since we can't directly assign the function pointer
5763 to another function pointer that was declared more completely easily. */
5765 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
5766 j_decompress_ptr cinfo
;
5769 return fn_jpeg_resync_to_restart (cinfo
, desired
);
5774 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
5775 #define fn_jpeg_start_decompress jpeg_start_decompress
5776 #define fn_jpeg_finish_decompress jpeg_finish_decompress
5777 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
5778 #define fn_jpeg_read_header jpeg_read_header
5779 #define fn_jpeg_read_scanlines jpeg_read_scanlines
5780 #define fn_jpeg_stdio_src jpeg_stdio_src
5781 #define fn_jpeg_std_error jpeg_std_error
5782 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
5784 #endif /* HAVE_NTGUI */
5786 struct my_jpeg_error_mgr
5788 struct jpeg_error_mgr pub
;
5789 jmp_buf setjmp_buffer
;
5794 my_error_exit (cinfo
)
5797 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
5798 longjmp (mgr
->setjmp_buffer
, 1);
5802 /* Init source method for JPEG data source manager. Called by
5803 jpeg_read_header() before any data is actually read. See
5804 libjpeg.doc from the JPEG lib distribution. */
5807 our_init_source (cinfo
)
5808 j_decompress_ptr cinfo
;
5813 /* Fill input buffer method for JPEG data source manager. Called
5814 whenever more data is needed. We read the whole image in one step,
5815 so this only adds a fake end of input marker at the end. */
5818 our_fill_input_buffer (cinfo
)
5819 j_decompress_ptr cinfo
;
5821 /* Insert a fake EOI marker. */
5822 struct jpeg_source_mgr
*src
= cinfo
->src
;
5823 static JOCTET buffer
[2];
5825 buffer
[0] = (JOCTET
) 0xFF;
5826 buffer
[1] = (JOCTET
) JPEG_EOI
;
5828 src
->next_input_byte
= buffer
;
5829 src
->bytes_in_buffer
= 2;
5834 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
5835 is the JPEG data source manager. */
5838 our_skip_input_data (cinfo
, num_bytes
)
5839 j_decompress_ptr cinfo
;
5842 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5846 if (num_bytes
> src
->bytes_in_buffer
)
5847 ERREXIT (cinfo
, JERR_INPUT_EOF
);
5849 src
->bytes_in_buffer
-= num_bytes
;
5850 src
->next_input_byte
+= num_bytes
;
5855 /* Method to terminate data source. Called by
5856 jpeg_finish_decompress() after all data has been processed. */
5859 our_term_source (cinfo
)
5860 j_decompress_ptr cinfo
;
5865 /* Set up the JPEG lib for reading an image from DATA which contains
5866 LEN bytes. CINFO is the decompression info structure created for
5867 reading the image. */
5870 jpeg_memory_src (cinfo
, data
, len
)
5871 j_decompress_ptr cinfo
;
5875 struct jpeg_source_mgr
*src
;
5877 if (cinfo
->src
== NULL
)
5879 /* First time for this JPEG object? */
5880 cinfo
->src
= (struct jpeg_source_mgr
*)
5881 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
5882 sizeof (struct jpeg_source_mgr
));
5883 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5884 src
->next_input_byte
= data
;
5887 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5888 src
->init_source
= our_init_source
;
5889 src
->fill_input_buffer
= our_fill_input_buffer
;
5890 src
->skip_input_data
= our_skip_input_data
;
5891 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
5892 src
->term_source
= our_term_source
;
5893 src
->bytes_in_buffer
= len
;
5894 src
->next_input_byte
= data
;
5898 /* Load image IMG for use on frame F. Patterned after example.c
5899 from the JPEG lib. */
5906 struct jpeg_decompress_struct cinfo
;
5907 struct my_jpeg_error_mgr mgr
;
5908 Lisp_Object file
, specified_file
;
5909 Lisp_Object specified_data
;
5910 FILE * volatile fp
= NULL
;
5912 int row_stride
, x
, y
;
5913 XImagePtr ximg
= NULL
;
5915 unsigned long *colors
;
5917 struct gcpro gcpro1
;
5919 /* Open the JPEG file. */
5920 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5921 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5925 if (NILP (specified_data
))
5927 file
= x_find_image_file (specified_file
);
5928 if (!STRINGP (file
))
5930 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5935 fp
= fopen (SDATA (file
), "rb");
5938 image_error ("Cannot open `%s'", file
, Qnil
);
5944 /* Customize libjpeg's error handling to call my_error_exit when an
5945 error is detected. This function will perform a longjmp. */
5946 cinfo
.err
= fn_jpeg_std_error (&mgr
.pub
);
5947 mgr
.pub
.error_exit
= my_error_exit
;
5949 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
5953 /* Called from my_error_exit. Display a JPEG error. */
5954 char buffer
[JMSG_LENGTH_MAX
];
5955 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
5956 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
5957 build_string (buffer
));
5960 /* Close the input file and destroy the JPEG object. */
5962 fclose ((FILE *) fp
);
5963 fn_jpeg_destroy_decompress (&cinfo
);
5965 /* If we already have an XImage, free that. */
5966 x_destroy_x_image (ximg
);
5968 /* Free pixmap and colors. */
5969 x_clear_image (f
, img
);
5975 /* Create the JPEG decompression object. Let it read from fp.
5976 Read the JPEG image header. */
5977 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
5979 if (NILP (specified_data
))
5980 fn_jpeg_stdio_src (&cinfo
, (FILE *) fp
);
5982 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
5983 SBYTES (specified_data
));
5985 fn_jpeg_read_header (&cinfo
, TRUE
);
5987 /* Customize decompression so that color quantization will be used.
5988 Start decompression. */
5989 cinfo
.quantize_colors
= TRUE
;
5990 fn_jpeg_start_decompress (&cinfo
);
5991 width
= img
->width
= cinfo
.output_width
;
5992 height
= img
->height
= cinfo
.output_height
;
5994 /* Create X image and pixmap. */
5995 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
5996 longjmp (mgr
.setjmp_buffer
, 2);
5998 /* Allocate colors. When color quantization is used,
5999 cinfo.actual_number_of_colors has been set with the number of
6000 colors generated, and cinfo.colormap is a two-dimensional array
6001 of color indices in the range 0..cinfo.actual_number_of_colors.
6002 No more than 255 colors will be generated. */
6006 if (cinfo
.out_color_components
> 2)
6007 ir
= 0, ig
= 1, ib
= 2;
6008 else if (cinfo
.out_color_components
> 1)
6009 ir
= 0, ig
= 1, ib
= 0;
6011 ir
= 0, ig
= 0, ib
= 0;
6013 /* Use the color table mechanism because it handles colors that
6014 cannot be allocated nicely. Such colors will be replaced with
6015 a default color, and we don't have to care about which colors
6016 can be freed safely, and which can't. */
6017 init_color_table ();
6018 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6021 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6023 /* Multiply RGB values with 255 because X expects RGB values
6024 in the range 0..0xffff. */
6025 int r
= cinfo
.colormap
[ir
][i
] << 8;
6026 int g
= cinfo
.colormap
[ig
][i
] << 8;
6027 int b
= cinfo
.colormap
[ib
][i
] << 8;
6028 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6031 #ifdef COLOR_TABLE_SUPPORT
6032 /* Remember those colors actually allocated. */
6033 img
->colors
= colors_in_color_table (&img
->ncolors
);
6034 free_color_table ();
6035 #endif /* COLOR_TABLE_SUPPORT */
6039 row_stride
= width
* cinfo
.output_components
;
6040 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6042 for (y
= 0; y
< height
; ++y
)
6044 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6045 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6046 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6050 fn_jpeg_finish_decompress (&cinfo
);
6051 fn_jpeg_destroy_decompress (&cinfo
);
6053 fclose ((FILE *) fp
);
6055 /* Maybe fill in the background field while we have ximg handy. */
6056 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6057 IMAGE_BACKGROUND (img
, f
, ximg
);
6059 /* Put the image into the pixmap. */
6060 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6061 x_destroy_x_image (ximg
);
6066 #else /* HAVE_JPEG */
6075 return image_load_quartz2d (f
, img
, 0);
6077 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
6082 #endif /* !HAVE_JPEG */
6086 /***********************************************************************
6088 ***********************************************************************/
6090 #if defined (HAVE_TIFF) || defined (MAC_OS)
6092 static int tiff_image_p
P_ ((Lisp_Object object
));
6093 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6095 /* The symbol `tiff' identifying images of this type. */
6099 /* Indices of image specification fields in tiff_format, below. */
6101 enum tiff_keyword_index
6110 TIFF_HEURISTIC_MASK
,
6116 /* Vector of image_keyword structures describing the format
6117 of valid user-defined image specifications. */
6119 static struct image_keyword tiff_format
[TIFF_LAST
] =
6121 {":type", IMAGE_SYMBOL_VALUE
, 1},
6122 {":data", IMAGE_STRING_VALUE
, 0},
6123 {":file", IMAGE_STRING_VALUE
, 0},
6124 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6125 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6126 {":relief", IMAGE_INTEGER_VALUE
, 0},
6127 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6128 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6129 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6130 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6133 /* Structure describing the image type `tiff'. */
6135 static struct image_type tiff_type
=
6144 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6147 tiff_image_p (object
)
6150 struct image_keyword fmt
[TIFF_LAST
];
6151 bcopy (tiff_format
, fmt
, sizeof fmt
);
6153 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6156 /* Must specify either the :data or :file keyword. */
6157 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6160 #endif /* HAVE_TIFF || MAC_OS */
6168 /* TIFF library details. */
6169 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6170 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6171 DEF_IMGLIB_FN (TIFFOpen
);
6172 DEF_IMGLIB_FN (TIFFClientOpen
);
6173 DEF_IMGLIB_FN (TIFFGetField
);
6174 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6175 DEF_IMGLIB_FN (TIFFClose
);
6178 init_tiff_functions (void)
6182 if (!(library
= LoadLibrary ("libtiff.dll")))
6185 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6186 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6187 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6188 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6189 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6190 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6191 LOAD_IMGLIB_FN (library
, TIFFClose
);
6197 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6198 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6199 #define fn_TIFFOpen TIFFOpen
6200 #define fn_TIFFClientOpen TIFFClientOpen
6201 #define fn_TIFFGetField TIFFGetField
6202 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6203 #define fn_TIFFClose TIFFClose
6205 #endif /* HAVE_NTGUI */
6208 /* Reading from a memory buffer for TIFF images Based on the PNG
6209 memory source, but we have to provide a lot of extra functions.
6212 We really only need to implement read and seek, but I am not
6213 convinced that the TIFF library is smart enough not to destroy
6214 itself if we only hand it the function pointers we need to
6219 unsigned char *bytes
;
6226 tiff_read_from_memory (data
, buf
, size
)
6231 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6233 if (size
> src
->len
- src
->index
)
6235 bcopy (src
->bytes
+ src
->index
, buf
, size
);
6241 tiff_write_from_memory (data
, buf
, size
)
6250 tiff_seek_in_memory (data
, off
, whence
)
6255 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6260 case SEEK_SET
: /* Go from beginning of source. */
6264 case SEEK_END
: /* Go from end of source. */
6265 idx
= src
->len
+ off
;
6268 case SEEK_CUR
: /* Go from current position. */
6269 idx
= src
->index
+ off
;
6272 default: /* Invalid `whence'. */
6276 if (idx
> src
->len
|| idx
< 0)
6284 tiff_close_memory (data
)
6292 tiff_mmap_memory (data
, pbase
, psize
)
6297 /* It is already _IN_ memory. */
6302 tiff_unmap_memory (data
, base
, size
)
6307 /* We don't need to do this. */
6311 tiff_size_of_memory (data
)
6314 return ((tiff_memory_source
*) data
)->len
;
6319 tiff_error_handler (title
, format
, ap
)
6320 const char *title
, *format
;
6326 len
= sprintf (buf
, "TIFF error: %s ", title
);
6327 vsprintf (buf
+ len
, format
, ap
);
6328 add_to_log (buf
, Qnil
, Qnil
);
6333 tiff_warning_handler (title
, format
, ap
)
6334 const char *title
, *format
;
6340 len
= sprintf (buf
, "TIFF warning: %s ", title
);
6341 vsprintf (buf
+ len
, format
, ap
);
6342 add_to_log (buf
, Qnil
, Qnil
);
6346 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6354 Lisp_Object file
, specified_file
;
6355 Lisp_Object specified_data
;
6357 int width
, height
, x
, y
;
6361 struct gcpro gcpro1
;
6362 tiff_memory_source memsrc
;
6364 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6365 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6369 fn_TIFFSetErrorHandler (tiff_error_handler
);
6370 fn_TIFFSetWarningHandler (tiff_warning_handler
);
6372 if (NILP (specified_data
))
6374 /* Read from a file */
6375 file
= x_find_image_file (specified_file
);
6376 if (!STRINGP (file
))
6378 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6383 /* Try to open the image file. */
6384 tiff
= fn_TIFFOpen (SDATA (file
), "r");
6387 image_error ("Cannot open `%s'", file
, Qnil
);
6394 /* Memory source! */
6395 memsrc
.bytes
= SDATA (specified_data
);
6396 memsrc
.len
= SBYTES (specified_data
);
6399 tiff
= fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
6400 (TIFFReadWriteProc
) tiff_read_from_memory
,
6401 (TIFFReadWriteProc
) tiff_write_from_memory
,
6402 tiff_seek_in_memory
,
6404 tiff_size_of_memory
,
6410 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
6416 /* Get width and height of the image, and allocate a raster buffer
6417 of width x height 32-bit values. */
6418 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
6419 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
6420 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
6422 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
6423 fn_TIFFClose (tiff
);
6426 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
6432 /* Create the X image and pixmap. */
6433 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6440 /* Initialize the color table. */
6441 init_color_table ();
6443 /* Process the pixel raster. Origin is in the lower-left corner. */
6444 for (y
= 0; y
< height
; ++y
)
6446 uint32
*row
= buf
+ y
* width
;
6448 for (x
= 0; x
< width
; ++x
)
6450 uint32 abgr
= row
[x
];
6451 int r
= TIFFGetR (abgr
) << 8;
6452 int g
= TIFFGetG (abgr
) << 8;
6453 int b
= TIFFGetB (abgr
) << 8;
6454 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
6458 #ifdef COLOR_TABLE_SUPPORT
6459 /* Remember the colors allocated for the image. Free the color table. */
6460 img
->colors
= colors_in_color_table (&img
->ncolors
);
6461 free_color_table ();
6462 #endif /* COLOR_TABLE_SUPPORT */
6465 img
->height
= height
;
6467 /* Maybe fill in the background field while we have ximg handy. */
6468 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6469 IMAGE_BACKGROUND (img
, f
, ximg
);
6471 /* Put the image into the pixmap, then free the X image and its buffer. */
6472 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6473 x_destroy_x_image (ximg
);
6480 #else /* HAVE_TIFF */
6488 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
6492 #endif /* !HAVE_TIFF */
6496 /***********************************************************************
6498 ***********************************************************************/
6500 #if defined (HAVE_GIF) || defined (MAC_OS)
6502 static int gif_image_p
P_ ((Lisp_Object object
));
6503 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
6505 /* The symbol `gif' identifying images of this type. */
6509 /* Indices of image specification fields in gif_format, below. */
6511 enum gif_keyword_index
6527 /* Vector of image_keyword structures describing the format
6528 of valid user-defined image specifications. */
6530 static struct image_keyword gif_format
[GIF_LAST
] =
6532 {":type", IMAGE_SYMBOL_VALUE
, 1},
6533 {":data", IMAGE_STRING_VALUE
, 0},
6534 {":file", IMAGE_STRING_VALUE
, 0},
6535 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6536 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6537 {":relief", IMAGE_INTEGER_VALUE
, 0},
6538 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6539 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6540 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6541 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6542 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6545 /* Structure describing the image type `gif'. */
6547 static struct image_type gif_type
=
6556 /* Return non-zero if OBJECT is a valid GIF image specification. */
6559 gif_image_p (object
)
6562 struct image_keyword fmt
[GIF_LAST
];
6563 bcopy (gif_format
, fmt
, sizeof fmt
);
6565 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
6568 /* Must specify either the :data or :file keyword. */
6569 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
6572 #endif /* HAVE_GIF || MAC_OS */
6576 #if defined (HAVE_NTGUI) || defined (MAC_OS)
6577 /* avoid conflict with QuickdrawText.h */
6578 #define DrawText gif_DrawText
6579 #include <gif_lib.h>
6582 #else /* HAVE_NTGUI || MAC_OS */
6584 #include <gif_lib.h>
6586 #endif /* HAVE_NTGUI || MAC_OS */
6591 /* GIF library details. */
6592 DEF_IMGLIB_FN (DGifCloseFile
);
6593 DEF_IMGLIB_FN (DGifSlurp
);
6594 DEF_IMGLIB_FN (DGifOpen
);
6595 DEF_IMGLIB_FN (DGifOpenFileName
);
6598 init_gif_functions (void)
6602 if (!(library
= LoadLibrary ("libungif.dll")))
6605 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
6606 LOAD_IMGLIB_FN (library
, DGifSlurp
);
6607 LOAD_IMGLIB_FN (library
, DGifOpen
);
6608 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
6614 #define fn_DGifCloseFile DGifCloseFile
6615 #define fn_DGifSlurp DGifSlurp
6616 #define fn_DGifOpen DGifOpen
6617 #define fn_DGifOpenFileName DGifOpenFileName
6619 #endif /* HAVE_NTGUI */
6621 /* Reading a GIF image from memory
6622 Based on the PNG memory stuff to a certain extent. */
6626 unsigned char *bytes
;
6632 /* Make the current memory source available to gif_read_from_memory.
6633 It's done this way because not all versions of libungif support
6634 a UserData field in the GifFileType structure. */
6635 static gif_memory_source
*current_gif_memory_src
;
6638 gif_read_from_memory (file
, buf
, len
)
6643 gif_memory_source
*src
= current_gif_memory_src
;
6645 if (len
> src
->len
- src
->index
)
6648 bcopy (src
->bytes
+ src
->index
, buf
, len
);
6654 /* Load GIF image IMG for use on frame F. Value is non-zero if
6662 Lisp_Object file
, specified_file
;
6663 Lisp_Object specified_data
;
6664 int rc
, width
, height
, x
, y
, i
;
6666 ColorMapObject
*gif_color_map
;
6667 unsigned long pixel_colors
[256];
6669 struct gcpro gcpro1
;
6671 int ino
, image_left
, image_top
, image_width
, image_height
;
6672 gif_memory_source memsrc
;
6673 unsigned char *raster
;
6675 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6676 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6680 if (NILP (specified_data
))
6682 file
= x_find_image_file (specified_file
);
6683 if (!STRINGP (file
))
6685 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6690 /* Open the GIF file. */
6691 gif
= fn_DGifOpenFileName (SDATA (file
));
6694 image_error ("Cannot open `%s'", file
, Qnil
);
6701 /* Read from memory! */
6702 current_gif_memory_src
= &memsrc
;
6703 memsrc
.bytes
= SDATA (specified_data
);
6704 memsrc
.len
= SBYTES (specified_data
);
6707 gif
= fn_DGifOpen(&memsrc
, gif_read_from_memory
);
6710 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
6716 /* Read entire contents. */
6717 rc
= fn_DGifSlurp (gif
);
6718 if (rc
== GIF_ERROR
)
6720 image_error ("Error reading `%s'", img
->spec
, Qnil
);
6721 fn_DGifCloseFile (gif
);
6726 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
6727 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
6728 if (ino
>= gif
->ImageCount
)
6730 image_error ("Invalid image number `%s' in image `%s'",
6732 fn_DGifCloseFile (gif
);
6737 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
6738 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
6740 /* Create the X image and pixmap. */
6741 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6743 fn_DGifCloseFile (gif
);
6748 /* Allocate colors. */
6749 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
6751 gif_color_map
= gif
->SColorMap
;
6752 init_color_table ();
6753 bzero (pixel_colors
, sizeof pixel_colors
);
6755 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
6757 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
6758 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
6759 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
6760 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6763 #ifdef COLOR_TABLE_SUPPORT
6764 img
->colors
= colors_in_color_table (&img
->ncolors
);
6765 free_color_table ();
6766 #endif /* COLOR_TABLE_SUPPORT */
6768 /* Clear the part of the screen image that are not covered by
6769 the image from the GIF file. Full animated GIF support
6770 requires more than can be done here (see the gif89 spec,
6771 disposal methods). Let's simply assume that the part
6772 not covered by a sub-image is in the frame's background color. */
6773 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
6774 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
6775 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
6776 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
6778 for (y
= 0; y
< image_top
; ++y
)
6779 for (x
= 0; x
< width
; ++x
)
6780 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6782 for (y
= image_top
+ image_height
; y
< height
; ++y
)
6783 for (x
= 0; x
< width
; ++x
)
6784 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6786 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
6788 for (x
= 0; x
< image_left
; ++x
)
6789 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6790 for (x
= image_left
+ image_width
; x
< width
; ++x
)
6791 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6794 /* Read the GIF image into the X image. We use a local variable
6795 `raster' here because RasterBits below is a char *, and invites
6796 problems with bytes >= 0x80. */
6797 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
6799 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
6801 static int interlace_start
[] = {0, 4, 2, 1};
6802 static int interlace_increment
[] = {8, 8, 4, 2};
6804 int row
= interlace_start
[0];
6808 for (y
= 0; y
< image_height
; y
++)
6810 if (row
>= image_height
)
6812 row
= interlace_start
[++pass
];
6813 while (row
>= image_height
)
6814 row
= interlace_start
[++pass
];
6817 for (x
= 0; x
< image_width
; x
++)
6819 int i
= raster
[(y
* image_width
) + x
];
6820 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
6824 row
+= interlace_increment
[pass
];
6829 for (y
= 0; y
< image_height
; ++y
)
6830 for (x
= 0; x
< image_width
; ++x
)
6832 int i
= raster
[y
* image_width
+ x
];
6833 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
6837 fn_DGifCloseFile (gif
);
6839 /* Maybe fill in the background field while we have ximg handy. */
6840 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6841 IMAGE_BACKGROUND (img
, f
, ximg
);
6843 /* Put the image into the pixmap, then free the X image and its buffer. */
6844 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6845 x_destroy_x_image (ximg
);
6859 Lisp_Object specified_file
, file
;
6860 Lisp_Object specified_data
;
6862 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
6870 Lisp_Object specified_bg
;
6876 struct gcpro gcpro1
;
6879 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6880 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6882 if (NILP (specified_data
))
6884 /* Read from a file */
6888 err
= find_image_fsspec (specified_file
, &file
, &fss
);
6892 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6897 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
6898 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
6902 if (!graphic_p
&& !movie_p
)
6904 if (prefer_graphic_p
)
6905 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
6906 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
6909 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
6910 CloseMovieFile (refnum
);
6913 image_error ("Error reading `%s'", file
, Qnil
);
6919 /* Memory source! */
6921 long file_type_atom
[3];
6923 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
6926 image_error ("Cannot allocate data handle for `%s'",
6931 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
6932 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
6933 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
6934 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
6937 err
= PtrAndHand ("\p", dref
, 1);
6939 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
6942 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
6945 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
6946 &movie_p
, &prefer_graphic_p
, 0);
6950 if (!graphic_p
&& !movie_p
)
6952 if (prefer_graphic_p
)
6956 DisposeHandle (dref
);
6957 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
6961 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
6962 HandleDataHandlerSubType
);
6963 DisposeHandle (dref
);
6968 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
6969 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
6970 track
= GetMovieIndTrack (movie
, 1);
6971 media
= GetTrackMedia (track
);
6972 nsamples
= GetMediaSampleCount (media
);
6973 if (ino
>= nsamples
)
6975 image_error ("Invalid image number `%s' in image `%s'",
6980 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6981 if (!STRINGP (specified_bg
) ||
6982 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6984 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6985 color
.red
= RED16_FROM_ULONG (color
.pixel
);
6986 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
6987 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
6989 GetMovieBox (movie
, &rect
);
6990 width
= img
->width
= rect
.right
- rect
.left
;
6991 height
= img
->height
= rect
.bottom
- rect
.top
;
6992 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6995 SetGWorld (ximg
, NULL
);
6996 bg_color
.red
= color
.red
;
6997 bg_color
.green
= color
.green
;
6998 bg_color
.blue
= color
.blue
;
6999 RGBBackColor (&bg_color
);
7000 SetMovieActive (movie
, TRUE
);
7001 SetMovieGWorld (movie
, ximg
, NULL
);
7002 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7003 SetMovieTimeValue (movie
, time
);
7004 MoviesTask (movie
, 0L);
7005 DisposeTrackMedia (media
);
7006 DisposeMovieTrack (track
);
7007 DisposeMovie (movie
);
7010 /* Maybe fill in the background field while we have ximg handy. */
7011 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7012 IMAGE_BACKGROUND (img
, f
, ximg
);
7014 /* Put the image into the pixmap. */
7015 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7016 x_destroy_x_image (ximg
);
7020 image_error ("Cannot open `%s'", file
, Qnil
);
7023 DisposeTrackMedia (media
);
7025 DisposeMovieTrack (track
);
7027 DisposeMovie (movie
);
7034 #endif /* HAVE_GIF */
7038 /***********************************************************************
7040 ***********************************************************************/
7042 #ifdef HAVE_X_WINDOWS
7043 #define HAVE_GHOSTSCRIPT 1
7044 #endif /* HAVE_X_WINDOWS */
7046 /* The symbol `postscript' identifying images of this type. */
7048 Lisp_Object Qpostscript
;
7050 #ifdef HAVE_GHOSTSCRIPT
7052 static int gs_image_p
P_ ((Lisp_Object object
));
7053 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
7054 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7056 /* Keyword symbols. */
7058 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
7060 /* Indices of image specification fields in gs_format, below. */
7062 enum gs_keyword_index
7080 /* Vector of image_keyword structures describing the format
7081 of valid user-defined image specifications. */
7083 static struct image_keyword gs_format
[GS_LAST
] =
7085 {":type", IMAGE_SYMBOL_VALUE
, 1},
7086 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7087 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7088 {":file", IMAGE_STRING_VALUE
, 1},
7089 {":loader", IMAGE_FUNCTION_VALUE
, 0},
7090 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
7091 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7092 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7093 {":relief", IMAGE_INTEGER_VALUE
, 0},
7094 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7095 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7096 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7097 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7100 /* Structure describing the image type `ghostscript'. */
7102 static struct image_type gs_type
=
7112 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7115 gs_clear_image (f
, img
)
7119 /* IMG->data.ptr_val may contain a recorded colormap. */
7120 xfree (img
->data
.ptr_val
);
7121 x_clear_image (f
, img
);
7125 /* Return non-zero if OBJECT is a valid Ghostscript image
7132 struct image_keyword fmt
[GS_LAST
];
7136 bcopy (gs_format
, fmt
, sizeof fmt
);
7138 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
7141 /* Bounding box must be a list or vector containing 4 integers. */
7142 tem
= fmt
[GS_BOUNDING_BOX
].value
;
7145 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
7146 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
7151 else if (VECTORP (tem
))
7153 if (XVECTOR (tem
)->size
!= 4)
7155 for (i
= 0; i
< 4; ++i
)
7156 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
7166 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7175 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
7176 struct gcpro gcpro1
, gcpro2
;
7178 double in_width
, in_height
;
7179 Lisp_Object pixel_colors
= Qnil
;
7181 /* Compute pixel size of pixmap needed from the given size in the
7182 image specification. Sizes in the specification are in pt. 1 pt
7183 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7185 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
7186 in_width
= XFASTINT (pt_width
) / 72.0;
7187 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
7188 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
7189 in_height
= XFASTINT (pt_height
) / 72.0;
7190 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
7192 /* Create the pixmap. */
7193 xassert (img
->pixmap
== NO_PIXMAP
);
7195 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7197 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7198 img
->width
, img
->height
,
7199 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
7204 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
7208 /* Call the loader to fill the pixmap. It returns a process object
7209 if successful. We do not record_unwind_protect here because
7210 other places in redisplay like calling window scroll functions
7211 don't either. Let the Lisp loader use `unwind-protect' instead. */
7212 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
7214 sprintf (buffer
, "%lu %lu",
7215 (unsigned long) FRAME_X_WINDOW (f
),
7216 (unsigned long) img
->pixmap
);
7217 window_and_pixmap_id
= build_string (buffer
);
7219 sprintf (buffer
, "%lu %lu",
7220 FRAME_FOREGROUND_PIXEL (f
),
7221 FRAME_BACKGROUND_PIXEL (f
));
7222 pixel_colors
= build_string (buffer
);
7224 XSETFRAME (frame
, f
);
7225 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
7227 loader
= intern ("gs-load-image");
7229 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
7230 make_number (img
->width
),
7231 make_number (img
->height
),
7232 window_and_pixmap_id
,
7235 return PROCESSP (img
->data
.lisp_val
);
7239 /* Kill the Ghostscript process that was started to fill PIXMAP on
7240 frame F. Called from XTread_socket when receiving an event
7241 telling Emacs that Ghostscript has finished drawing. */
7244 x_kill_gs_process (pixmap
, f
)
7248 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7252 /* Find the image containing PIXMAP. */
7253 for (i
= 0; i
< c
->used
; ++i
)
7254 if (c
->images
[i
]->pixmap
== pixmap
)
7257 /* Should someone in between have cleared the image cache, for
7258 instance, give up. */
7262 /* Kill the GS process. We should have found PIXMAP in the image
7263 cache and its image should contain a process object. */
7265 xassert (PROCESSP (img
->data
.lisp_val
));
7266 Fkill_process (img
->data
.lisp_val
, Qnil
);
7267 img
->data
.lisp_val
= Qnil
;
7269 #if defined (HAVE_X_WINDOWS)
7271 /* On displays with a mutable colormap, figure out the colors
7272 allocated for the image by looking at the pixels of an XImage for
7274 class = FRAME_X_VISUAL (f
)->class;
7275 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
7281 /* Try to get an XImage for img->pixmep. */
7282 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7283 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7288 /* Initialize the color table. */
7289 init_color_table ();
7291 /* For each pixel of the image, look its color up in the
7292 color table. After having done so, the color table will
7293 contain an entry for each color used by the image. */
7294 for (y
= 0; y
< img
->height
; ++y
)
7295 for (x
= 0; x
< img
->width
; ++x
)
7297 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
7298 lookup_pixel_color (f
, pixel
);
7301 /* Record colors in the image. Free color table and XImage. */
7302 #ifdef COLOR_TABLE_SUPPORT
7303 img
->colors
= colors_in_color_table (&img
->ncolors
);
7304 free_color_table ();
7306 XDestroyImage (ximg
);
7308 #if 0 /* This doesn't seem to be the case. If we free the colors
7309 here, we get a BadAccess later in x_clear_image when
7310 freeing the colors. */
7311 /* We have allocated colors once, but Ghostscript has also
7312 allocated colors on behalf of us. So, to get the
7313 reference counts right, free them once. */
7315 x_free_colors (f
, img
->colors
, img
->ncolors
);
7319 image_error ("Cannot get X image of `%s'; colors will not be freed",
7324 #endif /* HAVE_X_WINDOWS */
7326 /* Now that we have the pixmap, compute mask and transform the
7327 image if requested. */
7329 postprocess_image (f
, img
);
7333 #endif /* HAVE_GHOSTSCRIPT */
7336 /***********************************************************************
7338 ***********************************************************************/
7342 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
7343 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
7347 return valid_image_p (spec
) ? Qt
: Qnil
;
7351 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
7357 if (valid_image_p (spec
))
7358 id
= lookup_image (SELECTED_FRAME (), spec
);
7361 return make_number (id
);
7364 #endif /* GLYPH_DEBUG != 0 */
7367 /***********************************************************************
7369 ***********************************************************************/
7374 QCascent
= intern (":ascent");
7375 staticpro (&QCascent
);
7376 QCmargin
= intern (":margin");
7377 staticpro (&QCmargin
);
7378 QCrelief
= intern (":relief");
7379 staticpro (&QCrelief
);
7380 QCconversion
= intern (":conversion");
7381 staticpro (&QCconversion
);
7382 QCcolor_symbols
= intern (":color-symbols");
7383 staticpro (&QCcolor_symbols
);
7384 QCheuristic_mask
= intern (":heuristic-mask");
7385 staticpro (&QCheuristic_mask
);
7386 QCindex
= intern (":index");
7387 staticpro (&QCindex
);
7388 QCmatrix
= intern (":matrix");
7389 staticpro (&QCmatrix
);
7390 QCcolor_adjustment
= intern (":color-adjustment");
7391 staticpro (&QCcolor_adjustment
);
7392 QCmask
= intern (":mask");
7393 staticpro (&QCmask
);
7395 Qlaplace
= intern ("laplace");
7396 staticpro (&Qlaplace
);
7397 Qemboss
= intern ("emboss");
7398 staticpro (&Qemboss
);
7399 Qedge_detection
= intern ("edge-detection");
7400 staticpro (&Qedge_detection
);
7401 Qheuristic
= intern ("heuristic");
7402 staticpro (&Qheuristic
);
7404 Qpostscript
= intern ("postscript");
7405 staticpro (&Qpostscript
);
7406 #ifdef HAVE_GHOSTSCRIPT
7407 QCloader
= intern (":loader");
7408 staticpro (&QCloader
);
7409 QCbounding_box
= intern (":bounding-box");
7410 staticpro (&QCbounding_box
);
7411 QCpt_width
= intern (":pt-width");
7412 staticpro (&QCpt_width
);
7413 QCpt_height
= intern (":pt-height");
7414 staticpro (&QCpt_height
);
7415 #endif /* HAVE_GHOSTSCRIPT */
7417 Qpbm
= intern ("pbm");
7420 Qxbm
= intern ("xbm");
7424 Qxpm
= intern ("xpm");
7428 #if defined (HAVE_JPEG) || defined (MAC_OS)
7429 Qjpeg
= intern ("jpeg");
7433 #if defined (HAVE_TIFF) || defined (MAC_OS)
7434 Qtiff
= intern ("tiff");
7438 #if defined (HAVE_GIF) || defined (MAC_OS)
7439 Qgif
= intern ("gif");
7443 #if defined (HAVE_PNG) || defined (MAC_OS)
7444 Qpng
= intern ("png");
7448 defsubr (&Sclear_image_cache
);
7449 defsubr (&Simage_size
);
7450 defsubr (&Simage_mask_p
);
7454 defsubr (&Slookup_image
);
7457 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
7458 doc
: /* Non-nil means always draw a cross over disabled images.
7459 Disabled images are those having an `:conversion disabled' property.
7460 A cross is always drawn on black & white displays. */);
7461 cross_disabled_images
= 0;
7463 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
7464 doc
: /* List of directories to search for window system bitmap files. */);
7465 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
7467 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
7468 doc
: /* Time after which cached images are removed from the cache.
7469 When an image has not been displayed this many seconds, remove it
7470 from the image cache. Value must be an integer or nil with nil
7471 meaning don't clear the cache. */);
7472 Vimage_cache_eviction_delay
= make_number (30 * 60);
7477 /* Image types that rely on external libraries are loaded dynamically
7478 if the library is available. */
7479 #define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn())
7481 #define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */
7482 #endif /* HAVE_NTGUI */
7488 Vimage_types
= Qnil
;
7490 define_image_type (&xbm_type
);
7491 define_image_type (&pbm_type
);
7494 IF_LIB_AVAILABLE(init_xpm_functions
)
7495 define_image_type (&xpm_type
);
7498 #if defined (HAVE_JPEG) || defined (MAC_OS)
7499 IF_LIB_AVAILABLE(init_jpeg_functions
)
7500 define_image_type (&jpeg_type
);
7503 #if defined (HAVE_TIFF) || defined (MAC_OS)
7504 IF_LIB_AVAILABLE(init_tiff_functions
)
7505 define_image_type (&tiff_type
);
7508 #if defined (HAVE_GIF) || defined (MAC_OS)
7509 IF_LIB_AVAILABLE(init_gif_functions
)
7510 define_image_type (&gif_type
);
7513 #if defined (HAVE_PNG) || defined (MAC_OS)
7514 IF_LIB_AVAILABLE(init_png_functions
)
7515 define_image_type (&png_type
);
7518 #ifdef HAVE_GHOSTSCRIPT
7519 define_image_type (&gs_type
);
7523 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7526 init_image_func_pointer ();
7531 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
7532 (do not change this comment) */