1 /* Functions for image support on window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000,01,02,03,04
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
38 #include "dispextern.h"
39 #include "blockinput.h"
46 #include <sys/types.h>
49 #define COLOR_TABLE_SUPPORT 1
51 typedef struct x_bitmap_record Bitmap_Record
;
52 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
53 #define NO_PIXMAP None
55 #define RGB_PIXEL_COLOR unsigned long
57 #define PIX_MASK_RETAIN(f) 0
58 #define PIX_MASK_DRAW(f) 1
59 #endif /* HAVE_X_WINDOWS */
65 /* W32_TODO : Color tables on W32. */
66 #undef COLOR_TABLE_SUPPORT
68 typedef struct w32_bitmap_record Bitmap_Record
;
69 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
72 #define RGB_PIXEL_COLOR COLORREF
74 #define PIX_MASK_RETAIN(f) 0
75 #define PIX_MASK_DRAW(f) 1
77 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
78 #define x_defined_color w32_defined_color
79 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
80 #endif /* HAVE_NTGUI */
90 #include <QuickTime/QuickTime.h>
91 #else /* not MAC_OSX */
94 #include <TextUtils.h>
95 #endif /* not MAC_OSX */
97 /* MAC_TODO : Color tables on Mac. */
98 #undef COLOR_TABLE_SUPPORT
100 #define ZPixmap 0 /* arbitrary */
101 typedef struct mac_bitmap_record Bitmap_Record
;
103 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
106 #define RGB_PIXEL_COLOR unsigned long
108 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
109 #define x_defined_color mac_defined_color
110 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
111 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
112 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
117 /* Search path for bitmap files. */
119 Lisp_Object Vx_bitmap_file_path
;
122 static void x_disable_image
P_ ((struct frame
*, struct image
*));
123 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
126 static void init_color_table
P_ ((void));
127 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
128 #ifdef COLOR_TABLE_SUPPORT
129 static void free_color_table
P_ ((void));
130 static unsigned long *colors_in_color_table
P_ ((int *n
));
131 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
134 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
135 id, which is just an int that this section returns. Bitmaps are
136 reference counted so they can be shared among frames.
138 Bitmap indices are guaranteed to be > 0, so a negative number can
139 be used to indicate no bitmap.
141 If you use x_create_bitmap_from_data, then you must keep track of
142 the bitmaps yourself. That is, creating a bitmap from the same
143 data more than once will not be caught. */
148 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
149 Display
*display
; /* not used */
151 int x
, y
; /* not used */
152 unsigned int width
, height
; /* not used */
153 unsigned long plane_mask
; /* not used */
154 int format
; /* not used */
157 xassert (x
== 0 && y
== 0);
160 SetRect (&ri
, 0, 0, width
, height
);
161 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
163 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
166 LockPixels (GetGWorldPixMap (pixmap
));
172 XPutPixel (ximage
, x
, y
, pixel
)
179 SetGWorld (ximage
, NULL
);
181 color
.red
= RED16_FROM_ULONG (pixel
);
182 color
.green
= GREEN16_FROM_ULONG (pixel
);
183 color
.blue
= BLUE16_FROM_ULONG (pixel
);
184 SetCPixel (x
, y
, &color
);
188 XGetPixel (ximage
, x
, y
)
194 SetGWorld (ximage
, NULL
);
196 GetCPixel (x
, y
, &color
);
197 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
204 UnlockPixels (GetGWorldPixMap (ximg
));
209 /* Functions to access the contents of a bitmap, given an id. */
212 x_bitmap_height (f
, id
)
216 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
220 x_bitmap_width (f
, id
)
224 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
227 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
229 x_bitmap_pixmap (f
, id
)
233 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
237 #ifdef HAVE_X_WINDOWS
239 x_bitmap_mask (f
, id
)
243 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
247 /* Allocate a new bitmap record. Returns index of new record. */
250 x_allocate_bitmap_record (f
)
253 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
256 if (dpyinfo
->bitmaps
== NULL
)
258 dpyinfo
->bitmaps_size
= 10;
260 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
261 dpyinfo
->bitmaps_last
= 1;
265 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
266 return ++dpyinfo
->bitmaps_last
;
268 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
269 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
272 dpyinfo
->bitmaps_size
*= 2;
274 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
275 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
276 return ++dpyinfo
->bitmaps_last
;
279 /* Add one reference to the reference count of the bitmap with id ID. */
282 x_reference_bitmap (f
, id
)
286 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
289 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
292 x_create_bitmap_from_data (f
, bits
, width
, height
)
295 unsigned int width
, height
;
297 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
300 #ifdef HAVE_X_WINDOWS
302 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
303 bits
, width
, height
);
306 #endif /* HAVE_X_WINDOWS */
310 bitmap
= CreateBitmap (width
, height
,
311 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
312 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
316 #endif /* HAVE_NTGUI */
319 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
324 id
= x_allocate_bitmap_record (f
);
326 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
327 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
329 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
332 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
333 dpyinfo
->bitmaps
[id
- 1].height
= height
;
334 dpyinfo
->bitmaps
[id
- 1].width
= width
;
335 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
337 #ifdef HAVE_X_WINDOWS
338 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
339 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
340 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
341 #endif /* HAVE_X_WINDOWS */
344 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
345 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
346 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
347 #endif /* HAVE_NTGUI */
352 /* Create bitmap from file FILE for frame F. */
355 x_create_bitmap_from_file (f
, file
)
360 return -1; /* MAC_TODO : bitmap support */
364 return -1; /* W32_TODO : bitmap support */
365 #endif /* HAVE_NTGUI */
367 #ifdef HAVE_X_WINDOWS
368 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
369 unsigned int width
, height
;
371 int xhot
, yhot
, result
, id
;
376 /* Look for an existing bitmap with the same name. */
377 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
379 if (dpyinfo
->bitmaps
[id
].refcount
380 && dpyinfo
->bitmaps
[id
].file
381 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
383 ++dpyinfo
->bitmaps
[id
].refcount
;
388 /* Search bitmap-file-path for the file, if appropriate. */
389 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
394 filename
= (char *) SDATA (found
);
396 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
397 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
398 if (result
!= BitmapSuccess
)
401 id
= x_allocate_bitmap_record (f
);
402 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
403 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
404 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
405 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
406 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
407 dpyinfo
->bitmaps
[id
- 1].height
= height
;
408 dpyinfo
->bitmaps
[id
- 1].width
= width
;
409 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
412 #endif /* HAVE_X_WINDOWS */
418 Free_Bitmap_Record (dpyinfo
, bm
)
419 Display_Info
*dpyinfo
;
422 #ifdef HAVE_X_WINDOWS
423 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
425 XFreePixmap (dpyinfo
->display
, bm
->mask
);
426 #endif /* HAVE_X_WINDOWS */
429 DeleteObject (bm
->pixmap
);
430 #endif /* HAVE_NTGUI */
433 xfree (bm
->bitmap_data
); /* Added ++kfs */
434 bm
->bitmap_data
= NULL
;
444 /* Remove reference to bitmap with id number ID. */
447 x_destroy_bitmap (f
, id
)
451 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
455 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
457 if (--bm
->refcount
== 0)
460 Free_Bitmap_Record (dpyinfo
, bm
);
466 /* Free all the bitmaps for the display specified by DPYINFO. */
469 x_destroy_all_bitmaps (dpyinfo
)
470 Display_Info
*dpyinfo
;
473 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
475 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
476 if (bm
->refcount
> 0)
477 Free_Bitmap_Record (dpyinfo
, bm
);
479 dpyinfo
->bitmaps_last
= 0;
483 #ifdef HAVE_X_WINDOWS
485 /* Useful functions defined in the section
486 `Image type independent image structures' below. */
488 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
489 unsigned long height
));
491 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
492 int depth
, XImagePtr
*ximg
,
495 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
498 /* Create a mask of a bitmap. Note is this not a perfect mask.
499 It's nicer with some borders in this context */
502 x_create_bitmap_mask (f
, id
)
507 XImagePtr ximg
, mask_img
;
508 unsigned long width
, height
;
511 unsigned long x
, y
, xp
, xm
, yp
, ym
;
514 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
519 pixmap
= x_bitmap_pixmap (f
, id
);
520 width
= x_bitmap_width (f
, id
);
521 height
= x_bitmap_height (f
, id
);
524 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
533 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
538 XDestroyImage (ximg
);
542 bg
= four_corners_best (ximg
, width
, height
);
544 for (y
= 0; y
< ximg
->height
; ++y
)
546 for (x
= 0; x
< ximg
->width
; ++x
)
548 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
549 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
550 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
551 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
552 if (XGetPixel (ximg
, x
, y
) == bg
553 && XGetPixel (ximg
, x
, yp
) == bg
554 && XGetPixel (ximg
, x
, ym
) == bg
555 && XGetPixel (ximg
, xp
, y
) == bg
556 && XGetPixel (ximg
, xp
, yp
) == bg
557 && XGetPixel (ximg
, xp
, ym
) == bg
558 && XGetPixel (ximg
, xm
, y
) == bg
559 && XGetPixel (ximg
, xm
, yp
) == bg
560 && XGetPixel (ximg
, xm
, ym
) == bg
)
561 XPutPixel (mask_img
, x
, y
, 0);
563 XPutPixel (mask_img
, x
, y
, 1);
567 xassert (interrupt_input_blocked
);
568 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
569 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
571 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
573 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
574 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
576 XDestroyImage (ximg
);
577 x_destroy_x_image (mask_img
);
582 #endif /* HAVE_X_WINDOWS */
585 /***********************************************************************
587 ***********************************************************************/
589 /* Value is the number of elements of vector VECTOR. */
591 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
593 /* List of supported image types. Use define_image_type to add new
594 types. Use lookup_image_type to find a type for a given symbol. */
596 static struct image_type
*image_types
;
598 /* The symbol `xbm' which is used as the type symbol for XBM images. */
604 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
605 extern Lisp_Object QCdata
, QCtype
;
606 extern Lisp_Object Qcenter
;
607 Lisp_Object QCascent
, QCmargin
, QCrelief
;
608 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
609 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
613 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
615 /* Time in seconds after which images should be removed from the cache
618 Lisp_Object Vimage_cache_eviction_delay
;
620 /* Function prototypes. */
622 static void define_image_type
P_ ((struct image_type
*type
));
623 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
624 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
625 static void x_laplace
P_ ((struct frame
*, struct image
*));
626 static void x_emboss
P_ ((struct frame
*, struct image
*));
627 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
631 /* Define a new image type from TYPE. This adds a copy of TYPE to
632 image_types and adds the symbol *TYPE->type to Vimage_types. */
635 define_image_type (type
)
636 struct image_type
*type
;
638 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
639 The initialized data segment is read-only. */
640 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
641 bcopy (type
, p
, sizeof *p
);
642 p
->next
= image_types
;
644 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
648 /* Look up image type SYMBOL, and return a pointer to its image_type
649 structure. Value is null if SYMBOL is not a known image type. */
651 static INLINE
struct image_type
*
652 lookup_image_type (symbol
)
655 struct image_type
*type
;
657 for (type
= image_types
; type
; type
= type
->next
)
658 if (EQ (symbol
, *type
->type
))
665 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
666 valid image specification is a list whose car is the symbol
667 `image', and whose rest is a property list. The property list must
668 contain a value for key `:type'. That value must be the name of a
669 supported image type. The rest of the property list depends on the
673 valid_image_p (object
)
682 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
683 if (EQ (XCAR (tem
), QCtype
))
686 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
688 struct image_type
*type
;
689 type
= lookup_image_type (XCAR (tem
));
691 valid_p
= type
->valid_p (object
);
702 /* Log error message with format string FORMAT and argument ARG.
703 Signaling an error, e.g. when an image cannot be loaded, is not a
704 good idea because this would interrupt redisplay, and the error
705 message display would lead to another redisplay. This function
706 therefore simply displays a message. */
709 image_error (format
, arg1
, arg2
)
711 Lisp_Object arg1
, arg2
;
713 add_to_log (format
, arg1
, arg2
);
718 /***********************************************************************
720 ***********************************************************************/
722 enum image_value_type
724 IMAGE_DONT_CHECK_VALUE_TYPE
,
726 IMAGE_STRING_OR_NIL_VALUE
,
728 IMAGE_POSITIVE_INTEGER_VALUE
,
729 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
730 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
733 IMAGE_FUNCTION_VALUE
,
738 /* Structure used when parsing image specifications. */
742 /* Name of keyword. */
745 /* The type of value allowed. */
746 enum image_value_type type
;
748 /* Non-zero means key must be present. */
751 /* Used to recognize duplicate keywords in a property list. */
754 /* The value that was found. */
759 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
761 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
764 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
765 has the format (image KEYWORD VALUE ...). One of the keyword/
766 value pairs must be `:type TYPE'. KEYWORDS is a vector of
767 image_keywords structures of size NKEYWORDS describing other
768 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
771 parse_image_spec (spec
, keywords
, nkeywords
, type
)
773 struct image_keyword
*keywords
;
784 while (CONSP (plist
))
786 Lisp_Object key
, value
;
788 /* First element of a pair must be a symbol. */
790 plist
= XCDR (plist
);
794 /* There must follow a value. */
797 value
= XCAR (plist
);
798 plist
= XCDR (plist
);
800 /* Find key in KEYWORDS. Error if not found. */
801 for (i
= 0; i
< nkeywords
; ++i
)
802 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
808 /* Record that we recognized the keyword. If a keywords
809 was found more than once, it's an error. */
810 keywords
[i
].value
= value
;
813 if (keywords
[i
].count
> 1)
816 /* Check type of value against allowed type. */
817 switch (keywords
[i
].type
)
819 case IMAGE_STRING_VALUE
:
820 if (!STRINGP (value
))
824 case IMAGE_STRING_OR_NIL_VALUE
:
825 if (!STRINGP (value
) && !NILP (value
))
829 case IMAGE_SYMBOL_VALUE
:
830 if (!SYMBOLP (value
))
834 case IMAGE_POSITIVE_INTEGER_VALUE
:
835 if (!INTEGERP (value
) || XINT (value
) <= 0)
839 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
840 if (INTEGERP (value
) && XINT (value
) >= 0)
843 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
844 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
848 case IMAGE_ASCENT_VALUE
:
849 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
851 else if (INTEGERP (value
)
853 && XINT (value
) <= 100)
857 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
858 if (!INTEGERP (value
) || XINT (value
) < 0)
862 case IMAGE_DONT_CHECK_VALUE_TYPE
:
865 case IMAGE_FUNCTION_VALUE
:
866 value
= indirect_function (value
);
869 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
873 case IMAGE_NUMBER_VALUE
:
874 if (!INTEGERP (value
) && !FLOATP (value
))
878 case IMAGE_INTEGER_VALUE
:
879 if (!INTEGERP (value
))
883 case IMAGE_BOOL_VALUE
:
884 if (!NILP (value
) && !EQ (value
, Qt
))
893 if (EQ (key
, QCtype
) && !EQ (type
, value
))
897 /* Check that all mandatory fields are present. */
898 for (i
= 0; i
< nkeywords
; ++i
)
899 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
906 /* Return the value of KEY in image specification SPEC. Value is nil
907 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
908 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
911 image_spec_value (spec
, key
, found
)
912 Lisp_Object spec
, key
;
917 xassert (valid_image_p (spec
));
919 for (tail
= XCDR (spec
);
920 CONSP (tail
) && CONSP (XCDR (tail
));
921 tail
= XCDR (XCDR (tail
)))
923 if (EQ (XCAR (tail
), key
))
927 return XCAR (XCDR (tail
));
937 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
938 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
939 PIXELS non-nil means return the size in pixels, otherwise return the
940 size in canonical character units.
941 FRAME is the frame on which the image will be displayed. FRAME nil
942 or omitted means use the selected frame. */)
943 (spec
, pixels
, frame
)
944 Lisp_Object spec
, pixels
, frame
;
949 if (valid_image_p (spec
))
951 struct frame
*f
= check_x_frame (frame
);
952 int id
= lookup_image (f
, spec
);
953 struct image
*img
= IMAGE_FROM_ID (f
, id
);
954 int width
= img
->width
+ 2 * img
->hmargin
;
955 int height
= img
->height
+ 2 * img
->vmargin
;
958 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
959 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
961 size
= Fcons (make_number (width
), make_number (height
));
964 error ("Invalid image specification");
970 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
971 doc
: /* Return t if image SPEC has a mask bitmap.
972 FRAME is the frame on which the image will be displayed. FRAME nil
973 or omitted means use the selected frame. */)
975 Lisp_Object spec
, frame
;
980 if (valid_image_p (spec
))
982 struct frame
*f
= check_x_frame (frame
);
983 int id
= lookup_image (f
, spec
);
984 struct image
*img
= IMAGE_FROM_ID (f
, id
);
989 error ("Invalid image specification");
995 /***********************************************************************
996 Image type independent image structures
997 ***********************************************************************/
999 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1000 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1003 /* Allocate and return a new image structure for image specification
1004 SPEC. SPEC has a hash value of HASH. */
1006 static struct image
*
1007 make_image (spec
, hash
)
1011 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1013 xassert (valid_image_p (spec
));
1014 bzero (img
, sizeof *img
);
1015 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1016 xassert (img
->type
!= NULL
);
1018 img
->data
.lisp_val
= Qnil
;
1019 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1025 /* Free image IMG which was used on frame F, including its resources. */
1034 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1036 /* Remove IMG from the hash table of its cache. */
1038 img
->prev
->next
= img
->next
;
1040 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1043 img
->next
->prev
= img
->prev
;
1045 c
->images
[img
->id
] = NULL
;
1047 /* Free resources, then free IMG. */
1048 img
->type
->free (f
, img
);
1054 /* Prepare image IMG for display on frame F. Must be called before
1055 drawing an image. */
1058 prepare_image_for_display (f
, img
)
1064 /* We're about to display IMG, so set its timestamp to `now'. */
1066 img
->timestamp
= EMACS_SECS (t
);
1068 /* If IMG doesn't have a pixmap yet, load it now, using the image
1069 type dependent loader function. */
1070 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1071 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1075 /* Value is the number of pixels for the ascent of image IMG when
1076 drawn in face FACE. */
1079 image_ascent (img
, face
, slice
)
1082 struct glyph_slice
*slice
;
1087 if (slice
->height
== img
->height
)
1088 height
= img
->height
+ img
->vmargin
;
1089 else if (slice
->y
== 0)
1090 height
= slice
->height
+ img
->vmargin
;
1092 height
= slice
->height
;
1094 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1099 /* W32 specific version. Why?. ++kfs */
1100 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1101 - FONT_BASE(face
->font
)) / 2;
1103 /* This expression is arranged so that if the image can't be
1104 exactly centered, it will be moved slightly up. This is
1105 because a typical font is `top-heavy' (due to the presence
1106 uppercase letters), so the image placement should err towards
1107 being top-heavy too. It also just generally looks better. */
1108 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1109 #endif /* HAVE_NTGUI */
1112 ascent
= height
/ 2;
1115 ascent
= (int) (height
* img
->ascent
/ 100.0);
1121 /* Image background colors. */
1123 /* Find the "best" corner color of a bitmap.
1124 On W32, XIMG is assumed to a device context with the bitmap selected. */
1126 static RGB_PIXEL_COLOR
1127 four_corners_best (ximg
, width
, height
)
1128 XImagePtr_or_DC ximg
;
1129 unsigned long width
, height
;
1131 RGB_PIXEL_COLOR corners
[4], best
;
1134 /* Get the colors at the corners of ximg. */
1135 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1136 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1137 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1138 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1140 /* Choose the most frequently found color as background. */
1141 for (i
= best_count
= 0; i
< 4; ++i
)
1145 for (j
= n
= 0; j
< 4; ++j
)
1146 if (corners
[i
] == corners
[j
])
1150 best
= corners
[i
], best_count
= n
;
1156 /* Portability macros */
1160 #define Destroy_Image(img_dc, prev) \
1161 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1163 #define Free_Pixmap(display, pixmap) \
1164 DeleteObject (pixmap)
1168 #define Destroy_Image(ximg, dummy) \
1169 XDestroyImage (ximg)
1171 #define Free_Pixmap(display, pixmap) \
1172 XFreePixmap (display, pixmap)
1174 #endif /* HAVE_NTGUI */
1177 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1178 it is guessed heuristically. If non-zero, XIMG is an existing
1179 XImage object (or device context with the image selected on W32) to
1180 use for the heuristic. */
1183 image_background (img
, f
, ximg
)
1186 XImagePtr_or_DC ximg
;
1188 if (! img
->background_valid
)
1189 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1191 int free_ximg
= !ximg
;
1194 #endif /* HAVE_NTGUI */
1199 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1200 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1202 HDC frame_dc
= get_frame_dc (f
);
1203 ximg
= CreateCompatibleDC (frame_dc
);
1204 release_frame_dc (f
, frame_dc
);
1205 prev
= SelectObject (ximg
, img
->pixmap
);
1206 #endif /* !HAVE_NTGUI */
1209 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1212 Destroy_Image (ximg
, prev
);
1214 img
->background_valid
= 1;
1217 return img
->background
;
1220 /* Return the `background_transparent' field of IMG. If IMG doesn't
1221 have one yet, it is guessed heuristically. If non-zero, MASK is an
1222 existing XImage object to use for the heuristic. */
1225 image_background_transparent (img
, f
, mask
)
1228 XImagePtr_or_DC mask
;
1230 if (! img
->background_transparent_valid
)
1231 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1235 int free_mask
= !mask
;
1238 #endif /* HAVE_NTGUI */
1243 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1244 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1246 HDC frame_dc
= get_frame_dc (f
);
1247 mask
= CreateCompatibleDC (frame_dc
);
1248 release_frame_dc (f
, frame_dc
);
1249 prev
= SelectObject (mask
, img
->mask
);
1250 #endif /* HAVE_NTGUI */
1253 img
->background_transparent
1254 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN (f
));
1257 Destroy_Image (mask
, prev
);
1260 img
->background_transparent
= 0;
1262 img
->background_transparent_valid
= 1;
1265 return img
->background_transparent
;
1269 /***********************************************************************
1270 Helper functions for X image types
1271 ***********************************************************************/
1273 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1275 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1276 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1278 Lisp_Object color_name
,
1279 unsigned long dflt
));
1282 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1283 free the pixmap if any. MASK_P non-zero means clear the mask
1284 pixmap if any. COLORS_P non-zero means free colors allocated for
1285 the image, if any. */
1288 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1291 int pixmap_p
, mask_p
, colors_p
;
1293 if (pixmap_p
&& img
->pixmap
)
1295 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1296 img
->pixmap
= NO_PIXMAP
;
1297 img
->background_valid
= 0;
1300 if (mask_p
&& img
->mask
)
1302 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1303 img
->mask
= NO_PIXMAP
;
1304 img
->background_transparent_valid
= 0;
1307 if (colors_p
&& img
->ncolors
)
1309 /* MAC_TODO: color table support. */
1310 /* W32_TODO: color table support. */
1311 #ifdef HAVE_X_WINDOWS
1312 x_free_colors (f
, img
->colors
, img
->ncolors
);
1313 #endif /* HAVE_X_WINDOWS */
1314 xfree (img
->colors
);
1320 /* Free X resources of image IMG which is used on frame F. */
1323 x_clear_image (f
, img
)
1328 x_clear_image_1 (f
, img
, 1, 1, 1);
1333 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1334 cannot be allocated, use DFLT. Add a newly allocated color to
1335 IMG->colors, so that it can be freed again. Value is the pixel
1338 static unsigned long
1339 x_alloc_image_color (f
, img
, color_name
, dflt
)
1342 Lisp_Object color_name
;
1346 unsigned long result
;
1348 xassert (STRINGP (color_name
));
1350 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1352 /* This isn't called frequently so we get away with simply
1353 reallocating the color vector to the needed size, here. */
1356 (unsigned long *) xrealloc (img
->colors
,
1357 img
->ncolors
* sizeof *img
->colors
);
1358 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1359 result
= color
.pixel
;
1369 /***********************************************************************
1371 ***********************************************************************/
1373 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1374 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1376 /* Return a new, initialized image cache that is allocated from the
1377 heap. Call free_image_cache to free an image cache. */
1379 struct image_cache
*
1382 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1385 bzero (c
, sizeof *c
);
1387 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1388 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1389 c
->buckets
= (struct image
**) xmalloc (size
);
1390 bzero (c
->buckets
, size
);
1395 /* Free image cache of frame F. Be aware that X frames share images
1399 free_image_cache (f
)
1402 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1407 /* Cache should not be referenced by any frame when freed. */
1408 xassert (c
->refcount
== 0);
1410 for (i
= 0; i
< c
->used
; ++i
)
1411 free_image (f
, c
->images
[i
]);
1415 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1420 /* Clear image cache of frame F. FORCE_P non-zero means free all
1421 images. FORCE_P zero means clear only images that haven't been
1422 displayed for some time. Should be called from time to time to
1423 reduce the number of loaded images. If image-eviction-seconds is
1424 non-nil, this frees images in the cache which weren't displayed for
1425 at least that many seconds. */
1428 clear_image_cache (f
, force_p
)
1432 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1434 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1441 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1443 /* Block input so that we won't be interrupted by a SIGIO
1444 while being in an inconsistent state. */
1447 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1449 struct image
*img
= c
->images
[i
];
1451 && (force_p
|| img
->timestamp
< old
))
1453 free_image (f
, img
);
1458 /* We may be clearing the image cache because, for example,
1459 Emacs was iconified for a longer period of time. In that
1460 case, current matrices may still contain references to
1461 images freed above. So, clear these matrices. */
1464 Lisp_Object tail
, frame
;
1466 FOR_EACH_FRAME (tail
, frame
)
1468 struct frame
*f
= XFRAME (frame
);
1469 if (FRAME_WINDOW_P (f
)
1470 && FRAME_X_IMAGE_CACHE (f
) == c
)
1471 clear_current_matrices (f
);
1474 ++windows_or_buffers_changed
;
1482 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1484 doc
: /* Clear the image cache of FRAME.
1485 FRAME nil or omitted means use the selected frame.
1486 FRAME t means clear the image caches of all frames. */)
1494 FOR_EACH_FRAME (tail
, frame
)
1495 if (FRAME_WINDOW_P (XFRAME (frame
)))
1496 clear_image_cache (XFRAME (frame
), 1);
1499 clear_image_cache (check_x_frame (frame
), 1);
1505 /* Compute masks and transform image IMG on frame F, as specified
1506 by the image's specification, */
1509 postprocess_image (f
, img
)
1513 /* Manipulation of the image's mask. */
1516 Lisp_Object conversion
, spec
;
1521 /* `:heuristic-mask t'
1523 means build a mask heuristically.
1524 `:heuristic-mask (R G B)'
1525 `:mask (heuristic (R G B))'
1526 means build a mask from color (R G B) in the
1529 means remove a mask, if any. */
1531 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1533 x_build_heuristic_mask (f
, img
, mask
);
1538 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1540 if (EQ (mask
, Qheuristic
))
1541 x_build_heuristic_mask (f
, img
, Qt
);
1542 else if (CONSP (mask
)
1543 && EQ (XCAR (mask
), Qheuristic
))
1545 if (CONSP (XCDR (mask
)))
1546 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1548 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1550 else if (NILP (mask
) && found_p
&& img
->mask
)
1552 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1553 img
->mask
= NO_PIXMAP
;
1558 /* Should we apply an image transformation algorithm? */
1559 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1560 if (EQ (conversion
, Qdisabled
))
1561 x_disable_image (f
, img
);
1562 else if (EQ (conversion
, Qlaplace
))
1564 else if (EQ (conversion
, Qemboss
))
1566 else if (CONSP (conversion
)
1567 && EQ (XCAR (conversion
), Qedge_detection
))
1570 tem
= XCDR (conversion
);
1572 x_edge_detection (f
, img
,
1573 Fplist_get (tem
, QCmatrix
),
1574 Fplist_get (tem
, QCcolor_adjustment
));
1580 /* Return the id of image with Lisp specification SPEC on frame F.
1581 SPEC must be a valid Lisp image specification (see valid_image_p). */
1584 lookup_image (f
, spec
)
1588 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1592 struct gcpro gcpro1
;
1595 /* F must be a window-system frame, and SPEC must be a valid image
1597 xassert (FRAME_WINDOW_P (f
));
1598 xassert (valid_image_p (spec
));
1602 /* Look up SPEC in the hash table of the image cache. */
1603 hash
= sxhash (spec
, 0);
1604 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1606 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1607 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1610 /* If not found, create a new image and cache it. */
1613 extern Lisp_Object Qpostscript
;
1616 img
= make_image (spec
, hash
);
1617 cache_image (f
, img
);
1618 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1620 /* If we can't load the image, and we don't have a width and
1621 height, use some arbitrary width and height so that we can
1622 draw a rectangle for it. */
1623 if (img
->load_failed_p
)
1627 value
= image_spec_value (spec
, QCwidth
, NULL
);
1628 img
->width
= (INTEGERP (value
)
1629 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1630 value
= image_spec_value (spec
, QCheight
, NULL
);
1631 img
->height
= (INTEGERP (value
)
1632 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1636 /* Handle image type independent image attributes
1637 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1638 `:background COLOR'. */
1639 Lisp_Object ascent
, margin
, relief
, bg
;
1641 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1642 if (INTEGERP (ascent
))
1643 img
->ascent
= XFASTINT (ascent
);
1644 else if (EQ (ascent
, Qcenter
))
1645 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1647 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1648 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1649 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1650 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1651 && INTEGERP (XCDR (margin
)))
1653 if (XINT (XCAR (margin
)) > 0)
1654 img
->hmargin
= XFASTINT (XCAR (margin
));
1655 if (XINT (XCDR (margin
)) > 0)
1656 img
->vmargin
= XFASTINT (XCDR (margin
));
1659 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1660 if (INTEGERP (relief
))
1662 img
->relief
= XINT (relief
);
1663 img
->hmargin
+= abs (img
->relief
);
1664 img
->vmargin
+= abs (img
->relief
);
1667 if (! img
->background_valid
)
1669 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1673 = x_alloc_image_color (f
, img
, bg
,
1674 FRAME_BACKGROUND_PIXEL (f
));
1675 img
->background_valid
= 1;
1679 /* Do image transformations and compute masks, unless we
1680 don't have the image yet. */
1681 if (!EQ (*img
->type
->type
, Qpostscript
))
1682 postprocess_image (f
, img
);
1688 /* We're using IMG, so set its timestamp to `now'. */
1689 EMACS_GET_TIME (now
);
1690 img
->timestamp
= EMACS_SECS (now
);
1694 /* Value is the image id. */
1699 /* Cache image IMG in the image cache of frame F. */
1702 cache_image (f
, img
)
1706 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1709 /* Find a free slot in c->images. */
1710 for (i
= 0; i
< c
->used
; ++i
)
1711 if (c
->images
[i
] == NULL
)
1714 /* If no free slot found, maybe enlarge c->images. */
1715 if (i
== c
->used
&& c
->used
== c
->size
)
1718 c
->images
= (struct image
**) xrealloc (c
->images
,
1719 c
->size
* sizeof *c
->images
);
1722 /* Add IMG to c->images, and assign IMG an id. */
1728 /* Add IMG to the cache's hash table. */
1729 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1730 img
->next
= c
->buckets
[i
];
1732 img
->next
->prev
= img
;
1734 c
->buckets
[i
] = img
;
1738 /* Call FN on every image in the image cache of frame F. Used to mark
1739 Lisp Objects in the image cache. */
1742 forall_images_in_image_cache (f
, fn
)
1744 void (*fn
) P_ ((struct image
*img
));
1746 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1748 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1752 for (i
= 0; i
< c
->used
; ++i
)
1761 /***********************************************************************
1762 X / MAC / W32 support code
1763 ***********************************************************************/
1767 /* Macro for defining functions that will be loaded from image DLLs. */
1768 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1770 /* Macro for loading those image functions from the library. */
1771 #define LOAD_IMGLIB_FN(lib,func) { \
1772 fn_##func = (void *) GetProcAddress (lib, #func); \
1773 if (!fn_##func) return 0; \
1776 #endif /* HAVE_NTGUI */
1778 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
1779 XImagePtr
*, Pixmap
*));
1780 static void x_destroy_x_image
P_ ((XImagePtr
));
1781 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
1784 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1785 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1786 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1787 via xmalloc. Print error messages via image_error if an error
1788 occurs. Value is non-zero if successful.
1790 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1791 should indicate the bit depth of the image. */
1794 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
1796 int width
, height
, depth
;
1800 #ifdef HAVE_X_WINDOWS
1801 Display
*display
= FRAME_X_DISPLAY (f
);
1802 Window window
= FRAME_X_WINDOW (f
);
1803 Screen
*screen
= FRAME_X_SCREEN (f
);
1805 xassert (interrupt_input_blocked
);
1808 depth
= DefaultDepthOfScreen (screen
);
1809 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
1810 depth
, ZPixmap
, 0, NULL
, width
, height
,
1811 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
1814 image_error ("Unable to allocate X image", Qnil
, Qnil
);
1818 /* Allocate image raster. */
1819 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
1821 /* Allocate a pixmap of the same size. */
1822 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1823 if (*pixmap
== NO_PIXMAP
)
1825 x_destroy_x_image (*ximg
);
1827 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1832 #endif /* HAVE_X_WINDOWS */
1836 BITMAPINFOHEADER
*header
;
1838 int scanline_width_bits
;
1840 int palette_colors
= 0;
1845 if (depth
!= 1 && depth
!= 4 && depth
!= 8
1846 && depth
!= 16 && depth
!= 24 && depth
!= 32)
1848 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
1852 scanline_width_bits
= width
* depth
;
1853 remainder
= scanline_width_bits
% 32;
1856 scanline_width_bits
+= 32 - remainder
;
1858 /* Bitmaps with a depth less than 16 need a palette. */
1859 /* BITMAPINFO structure already contains the first RGBQUAD. */
1861 palette_colors
= 1 << depth
- 1;
1863 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
1866 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
1870 header
= &((*ximg
)->info
.bmiHeader
);
1871 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
1872 header
->biSize
= sizeof (*header
);
1873 header
->biWidth
= width
;
1874 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
1875 header
->biPlanes
= 1;
1876 header
->biBitCount
= depth
;
1877 header
->biCompression
= BI_RGB
;
1878 header
->biClrUsed
= palette_colors
;
1880 /* TODO: fill in palette. */
1883 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
1884 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
1885 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
1886 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
1887 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
1888 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
1889 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
1890 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
1893 hdc
= get_frame_dc (f
);
1895 /* Create a DIBSection and raster array for the bitmap,
1896 and store its handle in *pixmap. */
1897 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
1898 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
1899 &((*ximg
)->data
), NULL
, 0);
1901 /* Realize display palette and garbage all frames. */
1902 release_frame_dc (f
, hdc
);
1904 if (*pixmap
== NULL
)
1906 DWORD err
= GetLastError();
1907 Lisp_Object errcode
;
1908 /* All system errors are < 10000, so the following is safe. */
1909 XSETINT (errcode
, (int) err
);
1910 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
1911 x_destroy_x_image (*ximg
);
1917 #endif /* HAVE_NTGUI */
1920 Display
*display
= FRAME_X_DISPLAY (f
);
1921 Window window
= FRAME_X_WINDOW (f
);
1923 xassert (interrupt_input_blocked
);
1925 /* Allocate a pixmap of the same size. */
1926 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1927 if (*pixmap
== NO_PIXMAP
)
1929 x_destroy_x_image (*ximg
);
1931 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1935 LockPixels (GetGWorldPixMap (*pixmap
));
1943 /* Destroy XImage XIMG. Free XIMG->data. */
1946 x_destroy_x_image (ximg
)
1949 xassert (interrupt_input_blocked
);
1952 #ifdef HAVE_X_WINDOWS
1955 XDestroyImage (ximg
);
1956 #endif /* HAVE_X_WINDOWS */
1958 /* Data will be freed by DestroyObject. */
1961 #endif /* HAVE_NTGUI */
1963 XDestroyImage (ximg
);
1969 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
1970 are width and height of both the image and pixmap. */
1973 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
1979 #ifdef HAVE_X_WINDOWS
1982 xassert (interrupt_input_blocked
);
1983 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
1984 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
1985 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1986 #endif /* HAVE_X_WINDOWS */
1989 #if 0 /* I don't think this is necessary looking at where it is used. */
1990 HDC hdc
= get_frame_dc (f
);
1991 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
1992 release_frame_dc (f
, hdc
);
1994 #endif /* HAVE_NTGUI */
1997 xassert (ximg
== pixmap
);
2002 /***********************************************************************
2004 ***********************************************************************/
2006 static unsigned char *slurp_file
P_ ((char *, int *));
2009 /* Find image file FILE. Look in data-directory, then
2010 x-bitmap-file-path. Value is the full name of the file found, or
2011 nil if not found. */
2014 x_find_image_file (file
)
2017 Lisp_Object file_found
, search_path
;
2018 struct gcpro gcpro1
, gcpro2
;
2022 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2023 GCPRO2 (file_found
, search_path
);
2025 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2026 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2038 /* Read FILE into memory. Value is a pointer to a buffer allocated
2039 with xmalloc holding FILE's contents. Value is null if an error
2040 occurred. *SIZE is set to the size of the file. */
2042 static unsigned char *
2043 slurp_file (file
, size
)
2048 unsigned char *buf
= NULL
;
2051 if (stat (file
, &st
) == 0
2052 && (fp
= fopen (file
, "rb")) != NULL
2053 && (buf
= (char *) xmalloc (st
.st_size
),
2054 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2077 /***********************************************************************
2078 MAC Image Load Functions
2079 ***********************************************************************/
2081 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2084 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2088 find_image_fsspec (specified_file
, file
, fss
)
2089 Lisp_Object specified_file
, *file
;
2092 #if TARGET_API_MAC_CARBON
2095 Str255 mac_pathname
;
2099 *file
= x_find_image_file (specified_file
);
2100 if (!STRINGP (*file
))
2101 return fnfErr
; /* file or directory not found;
2102 incomplete pathname */
2103 /* Try to open the image file. */
2104 #if TARGET_API_MAC_CARBON
2105 err
= FSPathMakeRef (SDATA (*file
), &fsr
, NULL
);
2107 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
2109 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
2111 c2pstr (mac_pathname
);
2112 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
2118 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2126 GraphicsImportComponent gi
;
2129 short draw_all_pixels
;
2130 Lisp_Object specified_bg
;
2135 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2139 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2144 /* read from file system spec */
2145 err
= GraphicsImportSetDataFile (gi
, fss
);
2148 image_error ("Cannot set fsspec to graphics importer for '%s'",
2155 /* read from data handle */
2156 err
= GraphicsImportSetDataHandle (gi
, dh
);
2159 image_error ("Cannot set data handle to graphics importer for `%s'",
2164 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
2167 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2170 width
= img
->width
= rect
.right
- rect
.left
;
2171 height
= img
->height
= rect
.bottom
- rect
.top
;
2172 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2174 /* Don't check the error code here. It may have an undocumented
2178 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2182 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2184 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2185 if (!STRINGP (specified_bg
) ||
2186 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2188 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2189 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2190 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2191 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2195 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2197 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2199 SetGWorld (ximg
, NULL
);
2200 bg_color
.red
= color
.red
;
2201 bg_color
.green
= color
.green
;
2202 bg_color
.blue
= color
.blue
;
2203 RGBBackColor (&bg_color
);
2204 #if TARGET_API_MAC_CARBON
2205 GetPortBounds (ximg
, &rect
);
2208 EraseRect (&(ximg
->portRect
));
2211 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2212 GraphicsImportDraw (gi
);
2213 CloseComponent (gi
);
2215 /* Maybe fill in the background field while we have ximg handy. */
2216 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2217 IMAGE_BACKGROUND (img
, f
, ximg
);
2219 /* Put the image into the pixmap. */
2220 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2221 x_destroy_x_image (ximg
);
2225 CloseComponent (gi
);
2230 /* Load an image using the QuickTime Graphics Importer.
2231 Note: The alpha channel does not work for PNG images. */
2233 image_load_quicktime (f
, img
, type
)
2238 Lisp_Object specified_file
;
2239 Lisp_Object specified_data
;
2242 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2243 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2245 if (NILP (specified_data
))
2247 /* Read from a file */
2251 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2255 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2257 image_error ("Cannot open `%s'", file
, Qnil
);
2260 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2264 /* Memory source! */
2268 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2271 image_error ("Cannot allocate data handle for `%s'",
2275 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2283 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2284 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2285 So don't use this function directly but determine at runtime
2286 whether it exists. */
2287 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2288 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2289 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2293 init_image_func_pointer ()
2295 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2297 MyCGImageCreateWithPNGDataProvider
2298 = (CGImageCreateWithPNGDataProviderProcType
)
2299 NSAddressOfSymbol (NSLookupAndBindSymbol
2300 ("_CGImageCreateWithPNGDataProvider"));
2303 MyCGImageCreateWithPNGDataProvider
= NULL
;
2308 image_load_quartz2d (f
, img
, png_p
)
2313 Lisp_Object file
, specified_file
;
2314 Lisp_Object specified_data
, specified_bg
;
2315 struct gcpro gcpro1
;
2316 CGDataProviderRef source
;
2320 XImagePtr ximg
= NULL
;
2321 CGContextRef context
;
2324 /* Open the file. */
2325 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2326 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2331 if (NILP (specified_data
))
2336 file
= x_find_image_file (specified_file
);
2337 if (!STRINGP (file
))
2339 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2343 path
= CFStringCreateWithCString (NULL
, SDATA (file
),
2344 kCFStringEncodingUTF8
);
2345 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2346 kCFURLPOSIXPathStyle
, 0);
2348 source
= CGDataProviderCreateWithURL (url
);
2352 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2353 SBYTES (specified_data
), NULL
);
2356 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2357 kCGRenderingIntentDefault
);
2359 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2360 kCGRenderingIntentDefault
);
2362 CGDataProviderRelease (source
);
2366 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2372 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2373 if (!STRINGP (specified_bg
) ||
2374 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2376 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2377 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2378 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2379 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2382 width
= img
->width
= CGImageGetWidth (image
);
2383 height
= img
->height
= CGImageGetHeight (image
);
2384 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2386 CGImageRelease (image
);
2390 rectangle
= CGRectMake (0, 0, width
, height
);
2391 QDBeginCGContext (ximg
, &context
);
2394 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2395 color
.green
/ 65535.0,
2396 color
.blue
/ 65535.0, 1.0);
2397 CGContextFillRect (context
, rectangle
);
2399 CGContextDrawImage (context
, rectangle
, image
);
2400 QDEndCGContext (ximg
, &context
);
2401 CGImageRelease (image
);
2403 /* Maybe fill in the background field while we have ximg handy. */
2404 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2405 IMAGE_BACKGROUND (img
, f
, ximg
);
2407 /* Put the image into the pixmap. */
2408 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2409 x_destroy_x_image (ximg
);
2418 /***********************************************************************
2420 ***********************************************************************/
2422 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2423 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2424 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2425 unsigned char *, unsigned char *));
2426 static int xbm_image_p
P_ ((Lisp_Object object
));
2427 static int xbm_read_bitmap_data
P_ ((unsigned char *, unsigned char *,
2428 int *, int *, unsigned char **));
2429 static int xbm_file_p
P_ ((Lisp_Object
));
2432 /* Indices of image specification fields in xbm_format, below. */
2434 enum xbm_keyword_index
2452 /* Vector of image_keyword structures describing the format
2453 of valid XBM image specifications. */
2455 static struct image_keyword xbm_format
[XBM_LAST
] =
2457 {":type", IMAGE_SYMBOL_VALUE
, 1},
2458 {":file", IMAGE_STRING_VALUE
, 0},
2459 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2460 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2461 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2462 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2463 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2464 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2465 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2466 {":relief", IMAGE_INTEGER_VALUE
, 0},
2467 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2468 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2469 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2472 /* Structure describing the image type XBM. */
2474 static struct image_type xbm_type
=
2483 /* Tokens returned from xbm_scan. */
2492 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2493 A valid specification is a list starting with the symbol `image'
2494 The rest of the list is a property list which must contain an
2497 If the specification specifies a file to load, it must contain
2498 an entry `:file FILENAME' where FILENAME is a string.
2500 If the specification is for a bitmap loaded from memory it must
2501 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2502 WIDTH and HEIGHT are integers > 0. DATA may be:
2504 1. a string large enough to hold the bitmap data, i.e. it must
2505 have a size >= (WIDTH + 7) / 8 * HEIGHT
2507 2. a bool-vector of size >= WIDTH * HEIGHT
2509 3. a vector of strings or bool-vectors, one for each line of the
2512 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2513 may not be specified in this case because they are defined in the
2516 Both the file and data forms may contain the additional entries
2517 `:background COLOR' and `:foreground COLOR'. If not present,
2518 foreground and background of the frame on which the image is
2519 displayed is used. */
2522 xbm_image_p (object
)
2525 struct image_keyword kw
[XBM_LAST
];
2527 bcopy (xbm_format
, kw
, sizeof kw
);
2528 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2531 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2533 if (kw
[XBM_FILE
].count
)
2535 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2538 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2540 /* In-memory XBM file. */
2541 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2549 /* Entries for `:width', `:height' and `:data' must be present. */
2550 if (!kw
[XBM_WIDTH
].count
2551 || !kw
[XBM_HEIGHT
].count
2552 || !kw
[XBM_DATA
].count
)
2555 data
= kw
[XBM_DATA
].value
;
2556 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2557 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2559 /* Check type of data, and width and height against contents of
2565 /* Number of elements of the vector must be >= height. */
2566 if (XVECTOR (data
)->size
< height
)
2569 /* Each string or bool-vector in data must be large enough
2570 for one line of the image. */
2571 for (i
= 0; i
< height
; ++i
)
2573 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2578 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2581 else if (BOOL_VECTOR_P (elt
))
2583 if (XBOOL_VECTOR (elt
)->size
< width
)
2590 else if (STRINGP (data
))
2593 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2596 else if (BOOL_VECTOR_P (data
))
2598 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2609 /* Scan a bitmap file. FP is the stream to read from. Value is
2610 either an enumerator from enum xbm_token, or a character for a
2611 single-character token, or 0 at end of file. If scanning an
2612 identifier, store the lexeme of the identifier in SVAL. If
2613 scanning a number, store its value in *IVAL. */
2616 xbm_scan (s
, end
, sval
, ival
)
2617 unsigned char **s
, *end
;
2625 /* Skip white space. */
2626 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2631 else if (isdigit (c
))
2633 int value
= 0, digit
;
2635 if (c
== '0' && *s
< end
)
2638 if (c
== 'x' || c
== 'X')
2645 else if (c
>= 'a' && c
<= 'f')
2646 digit
= c
- 'a' + 10;
2647 else if (c
>= 'A' && c
<= 'F')
2648 digit
= c
- 'A' + 10;
2651 value
= 16 * value
+ digit
;
2654 else if (isdigit (c
))
2658 && (c
= *(*s
)++, isdigit (c
)))
2659 value
= 8 * value
+ c
- '0';
2666 && (c
= *(*s
)++, isdigit (c
)))
2667 value
= 10 * value
+ c
- '0';
2675 else if (isalpha (c
) || c
== '_')
2679 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2686 else if (c
== '/' && **s
== '*')
2688 /* C-style comment. */
2690 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2704 /* Create a Windows bitmap from X bitmap data. */
2706 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2708 static unsigned char swap_nibble
[16]
2709 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2710 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2711 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2712 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2714 unsigned char *bits
, *p
;
2717 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2718 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2719 bits
= (unsigned char *) alloca (height
* w2
);
2720 bzero (bits
, height
* w2
);
2721 for (i
= 0; i
< height
; i
++)
2724 for (j
= 0; j
< w1
; j
++)
2726 /* Bitswap XBM bytes to match how Windows does things. */
2727 unsigned char c
= *data
++;
2728 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2729 | (swap_nibble
[(c
>>4) & 0xf]));
2732 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2737 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
2740 COLORREF foreground
, background
;
2742 HDC hdc
, old_img_dc
, new_img_dc
;
2743 HGDIOBJ old_prev
, new_prev
;
2746 hdc
= get_frame_dc (f
);
2747 old_img_dc
= CreateCompatibleDC (hdc
);
2748 new_img_dc
= CreateCompatibleDC (hdc
);
2749 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2750 release_frame_dc (f
, hdc
);
2751 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2752 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2753 SetTextColor (new_img_dc
, foreground
);
2754 SetBkColor (new_img_dc
, background
);
2756 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2759 SelectObject (old_img_dc
, old_prev
);
2760 SelectObject (new_img_dc
, new_prev
);
2761 DeleteDC (old_img_dc
);
2762 DeleteDC (new_img_dc
);
2763 DeleteObject (img
->pixmap
);
2764 if (new_pixmap
== 0)
2765 fprintf (stderr
, "Failed to convert image to color.\n");
2767 img
->pixmap
= new_pixmap
;
2770 #define XBM_BIT_SHUFFLE(b) (~(b))
2774 #define XBM_BIT_SHUFFLE(b) (b)
2776 #endif /* HAVE_NTGUI */
2780 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
2784 RGB_PIXEL_COLOR fg
, bg
;
2785 int non_default_colors
;
2789 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2791 /* If colors were specified, transfer the bitmap to a color one. */
2792 if (non_default_colors
)
2793 convert_mono_to_color_image (f
, img
, fg
, bg
);
2796 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2799 img
->width
, img
->height
,
2801 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2802 #endif /* HAVE_NTGUI */
2807 /* Replacement for XReadBitmapFileData which isn't available under old
2808 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2809 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2810 the image. Return in *DATA the bitmap data allocated with xmalloc.
2811 Value is non-zero if successful. DATA null means just test if
2812 CONTENTS looks like an in-memory XBM file. */
2815 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
2816 unsigned char *contents
, *end
;
2817 int *width
, *height
;
2818 unsigned char **data
;
2820 unsigned char *s
= contents
;
2821 char buffer
[BUFSIZ
];
2824 int bytes_per_line
, i
, nbytes
;
2830 LA1 = xbm_scan (&s, end, buffer, &value)
2832 #define expect(TOKEN) \
2833 if (LA1 != (TOKEN)) \
2838 #define expect_ident(IDENT) \
2839 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2844 *width
= *height
= -1;
2847 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2849 /* Parse defines for width, height and hot-spots. */
2853 expect_ident ("define");
2854 expect (XBM_TK_IDENT
);
2856 if (LA1
== XBM_TK_NUMBER
);
2858 char *p
= strrchr (buffer
, '_');
2859 p
= p
? p
+ 1 : buffer
;
2860 if (strcmp (p
, "width") == 0)
2862 else if (strcmp (p
, "height") == 0)
2865 expect (XBM_TK_NUMBER
);
2868 if (*width
< 0 || *height
< 0)
2870 else if (data
== NULL
)
2873 /* Parse bits. Must start with `static'. */
2874 expect_ident ("static");
2875 if (LA1
== XBM_TK_IDENT
)
2877 if (strcmp (buffer
, "unsigned") == 0)
2880 expect_ident ("char");
2882 else if (strcmp (buffer
, "short") == 0)
2886 if (*width
% 16 && *width
% 16 < 9)
2889 else if (strcmp (buffer
, "char") == 0)
2897 expect (XBM_TK_IDENT
);
2903 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
2904 nbytes
= bytes_per_line
* *height
;
2905 p
= *data
= (char *) xmalloc (nbytes
);
2909 for (i
= 0; i
< nbytes
; i
+= 2)
2912 expect (XBM_TK_NUMBER
);
2914 *p
++ = XBM_BIT_SHUFFLE (val
);
2915 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
2916 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
2918 if (LA1
== ',' || LA1
== '}')
2926 for (i
= 0; i
< nbytes
; ++i
)
2929 expect (XBM_TK_NUMBER
);
2931 *p
++ = XBM_BIT_SHUFFLE (val
);
2933 if (LA1
== ',' || LA1
== '}')
2958 /* Load XBM image IMG which will be displayed on frame F from buffer
2959 CONTENTS. END is the end of the buffer. Value is non-zero if
2963 xbm_load_image (f
, img
, contents
, end
)
2966 unsigned char *contents
, *end
;
2969 unsigned char *data
;
2972 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
2975 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
2976 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
2977 int non_default_colors
= 0;
2980 xassert (img
->width
> 0 && img
->height
> 0);
2982 /* Get foreground and background colors, maybe allocate colors. */
2983 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
2986 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
2987 non_default_colors
= 1;
2989 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2992 background
= x_alloc_image_color (f
, img
, value
, background
);
2993 img
->background
= background
;
2994 img
->background_valid
= 1;
2995 non_default_colors
= 1;
2998 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
2999 foreground
, background
,
3000 non_default_colors
);
3003 if (img
->pixmap
== NO_PIXMAP
)
3005 x_clear_image (f
, img
);
3006 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3012 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3018 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3025 return (STRINGP (data
)
3026 && xbm_read_bitmap_data (SDATA (data
),
3033 /* Fill image IMG which is used on frame F with pixmap data. Value is
3034 non-zero if successful. */
3042 Lisp_Object file_name
;
3044 xassert (xbm_image_p (img
->spec
));
3046 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3047 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3048 if (STRINGP (file_name
))
3051 unsigned char *contents
;
3053 struct gcpro gcpro1
;
3055 file
= x_find_image_file (file_name
);
3057 if (!STRINGP (file
))
3059 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3064 contents
= slurp_file (SDATA (file
), &size
);
3065 if (contents
== NULL
)
3067 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3072 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3077 struct image_keyword fmt
[XBM_LAST
];
3079 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3080 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3081 int non_default_colors
= 0;
3084 int in_memory_file_p
= 0;
3086 /* See if data looks like an in-memory XBM file. */
3087 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3088 in_memory_file_p
= xbm_file_p (data
);
3090 /* Parse the image specification. */
3091 bcopy (xbm_format
, fmt
, sizeof fmt
);
3092 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3095 /* Get specified width, and height. */
3096 if (!in_memory_file_p
)
3098 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3099 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3100 xassert (img
->width
> 0 && img
->height
> 0);
3103 /* Get foreground and background colors, maybe allocate colors. */
3104 if (fmt
[XBM_FOREGROUND
].count
3105 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3107 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3109 non_default_colors
= 1;
3112 if (fmt
[XBM_BACKGROUND
].count
3113 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3115 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3117 non_default_colors
= 1;
3120 if (in_memory_file_p
)
3121 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3130 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3132 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3133 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3135 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3137 bcopy (SDATA (line
), p
, nbytes
);
3139 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3142 else if (STRINGP (data
))
3143 bits
= SDATA (data
);
3145 bits
= XBOOL_VECTOR (data
)->data
;
3147 /* Create the pixmap. */
3149 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3150 foreground
, background
,
3151 non_default_colors
);
3156 image_error ("Unable to create pixmap for XBM image `%s'",
3158 x_clear_image (f
, img
);
3168 /***********************************************************************
3170 ***********************************************************************/
3174 static int xpm_image_p
P_ ((Lisp_Object object
));
3175 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3176 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3179 /* Indicate to xpm.h that we don't have Xlib. */
3181 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3182 #define XColor xpm_XColor
3183 #define XImage xpm_XImage
3184 #define PIXEL_ALREADY_TYPEDEFED
3185 #include "X11/xpm.h"
3189 #undef PIXEL_ALREADY_TYPEDEFED
3191 #include "X11/xpm.h"
3192 #endif /* HAVE_NTGUI */
3194 /* The symbol `xpm' identifying XPM-format images. */
3198 /* Indices of image specification fields in xpm_format, below. */
3200 enum xpm_keyword_index
3216 /* Vector of image_keyword structures describing the format
3217 of valid XPM image specifications. */
3219 static struct image_keyword xpm_format
[XPM_LAST
] =
3221 {":type", IMAGE_SYMBOL_VALUE
, 1},
3222 {":file", IMAGE_STRING_VALUE
, 0},
3223 {":data", IMAGE_STRING_VALUE
, 0},
3224 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3225 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3226 {":relief", IMAGE_INTEGER_VALUE
, 0},
3227 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3228 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3229 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3230 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3231 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3234 /* Structure describing the image type XPM. */
3236 static struct image_type xpm_type
=
3245 #ifdef HAVE_X_WINDOWS
3247 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3248 functions for allocating image colors. Our own functions handle
3249 color allocation failures more gracefully than the ones on the XPM
3252 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3253 #define ALLOC_XPM_COLORS
3255 #endif /* HAVE_X_WINDOWS */
3257 #ifdef ALLOC_XPM_COLORS
3259 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3260 static void xpm_free_color_cache
P_ ((void));
3261 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3262 static int xpm_color_bucket
P_ ((char *));
3263 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3266 /* An entry in a hash table used to cache color definitions of named
3267 colors. This cache is necessary to speed up XPM image loading in
3268 case we do color allocations ourselves. Without it, we would need
3269 a call to XParseColor per pixel in the image. */
3271 struct xpm_cached_color
3273 /* Next in collision chain. */
3274 struct xpm_cached_color
*next
;
3276 /* Color definition (RGB and pixel color). */
3283 /* The hash table used for the color cache, and its bucket vector
3286 #define XPM_COLOR_CACHE_BUCKETS 1001
3287 struct xpm_cached_color
**xpm_color_cache
;
3289 /* Initialize the color cache. */
3292 xpm_init_color_cache (f
, attrs
)
3294 XpmAttributes
*attrs
;
3296 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3297 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3298 memset (xpm_color_cache
, 0, nbytes
);
3299 init_color_table ();
3301 if (attrs
->valuemask
& XpmColorSymbols
)
3306 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3307 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3308 attrs
->colorsymbols
[i
].value
, &color
))
3310 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3312 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3317 /* Free the color cache. */
3320 xpm_free_color_cache ()
3322 struct xpm_cached_color
*p
, *next
;
3325 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3326 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3332 xfree (xpm_color_cache
);
3333 xpm_color_cache
= NULL
;
3334 free_color_table ();
3337 /* Return the bucket index for color named COLOR_NAME in the color
3341 xpm_color_bucket (color_name
)
3347 for (s
= color_name
; *s
; ++s
)
3349 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3353 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3354 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3357 static struct xpm_cached_color
*
3358 xpm_cache_color (f
, color_name
, color
, bucket
)
3365 struct xpm_cached_color
*p
;
3368 bucket
= xpm_color_bucket (color_name
);
3370 nbytes
= sizeof *p
+ strlen (color_name
);
3371 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3372 strcpy (p
->name
, color_name
);
3374 p
->next
= xpm_color_cache
[bucket
];
3375 xpm_color_cache
[bucket
] = p
;
3379 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3380 return the cached definition in *COLOR. Otherwise, make a new
3381 entry in the cache and allocate the color. Value is zero if color
3382 allocation failed. */
3385 xpm_lookup_color (f
, color_name
, color
)
3390 struct xpm_cached_color
*p
;
3391 int h
= xpm_color_bucket (color_name
);
3393 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3394 if (strcmp (p
->name
, color_name
) == 0)
3399 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3402 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3404 p
= xpm_cache_color (f
, color_name
, color
, h
);
3406 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3407 with transparency, and it's useful. */
3408 else if (strcmp ("opaque", color_name
) == 0)
3410 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3411 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3412 p
= xpm_cache_color (f
, color_name
, color
, h
);
3419 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3420 CLOSURE is a pointer to the frame on which we allocate the
3421 color. Return in *COLOR the allocated color. Value is non-zero
3425 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3432 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3436 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3437 is a pointer to the frame on which we allocate the color. Value is
3438 non-zero if successful. */
3441 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3451 #endif /* ALLOC_XPM_COLORS */
3456 /* XPM library details. */
3458 DEF_IMGLIB_FN (XpmFreeAttributes
);
3459 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3460 DEF_IMGLIB_FN (XpmReadFileToImage
);
3461 DEF_IMGLIB_FN (XImageFree
);
3465 init_xpm_functions (void)
3469 if (!(library
= LoadLibrary ("libXpm.dll")))
3472 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3473 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3474 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3475 LOAD_IMGLIB_FN (library
, XImageFree
);
3479 #endif /* HAVE_NTGUI */
3482 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3483 for XPM images. Such a list must consist of conses whose car and
3487 xpm_valid_color_symbols_p (color_symbols
)
3488 Lisp_Object color_symbols
;
3490 while (CONSP (color_symbols
))
3492 Lisp_Object sym
= XCAR (color_symbols
);
3494 || !STRINGP (XCAR (sym
))
3495 || !STRINGP (XCDR (sym
)))
3497 color_symbols
= XCDR (color_symbols
);
3500 return NILP (color_symbols
);
3504 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3507 xpm_image_p (object
)
3510 struct image_keyword fmt
[XPM_LAST
];
3511 bcopy (xpm_format
, fmt
, sizeof fmt
);
3512 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3513 /* Either `:file' or `:data' must be present. */
3514 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3515 /* Either no `:color-symbols' or it's a list of conses
3516 whose car and cdr are strings. */
3517 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3518 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3522 /* Load image IMG which will be displayed on frame F. Value is
3523 non-zero if successful. */
3531 XpmAttributes attrs
;
3532 Lisp_Object specified_file
, color_symbols
;
3535 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3536 #endif /* HAVE_NTGUI */
3538 /* Configure the XPM lib. Use the visual of frame F. Allocate
3539 close colors. Return colors allocated. */
3540 bzero (&attrs
, sizeof attrs
);
3543 attrs
.visual
= FRAME_X_VISUAL (f
);
3544 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3545 attrs
.valuemask
|= XpmVisual
;
3546 attrs
.valuemask
|= XpmColormap
;
3547 #endif /* HAVE_NTGUI */
3549 #ifdef ALLOC_XPM_COLORS
3550 /* Allocate colors with our own functions which handle
3551 failing color allocation more gracefully. */
3552 attrs
.color_closure
= f
;
3553 attrs
.alloc_color
= xpm_alloc_color
;
3554 attrs
.free_colors
= xpm_free_colors
;
3555 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3556 #else /* not ALLOC_XPM_COLORS */
3557 /* Let the XPM lib allocate colors. */
3558 attrs
.valuemask
|= XpmReturnAllocPixels
;
3559 #ifdef XpmAllocCloseColors
3560 attrs
.alloc_close_colors
= 1;
3561 attrs
.valuemask
|= XpmAllocCloseColors
;
3562 #else /* not XpmAllocCloseColors */
3563 attrs
.closeness
= 600;
3564 attrs
.valuemask
|= XpmCloseness
;
3565 #endif /* not XpmAllocCloseColors */
3566 #endif /* ALLOC_XPM_COLORS */
3568 /* If image specification contains symbolic color definitions, add
3569 these to `attrs'. */
3570 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3571 if (CONSP (color_symbols
))
3574 XpmColorSymbol
*xpm_syms
;
3577 attrs
.valuemask
|= XpmColorSymbols
;
3579 /* Count number of symbols. */
3580 attrs
.numsymbols
= 0;
3581 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3584 /* Allocate an XpmColorSymbol array. */
3585 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3586 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3587 bzero (xpm_syms
, size
);
3588 attrs
.colorsymbols
= xpm_syms
;
3590 /* Fill the color symbol array. */
3591 for (tail
= color_symbols
, i
= 0;
3593 ++i
, tail
= XCDR (tail
))
3595 Lisp_Object name
= XCAR (XCAR (tail
));
3596 Lisp_Object color
= XCDR (XCAR (tail
));
3597 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3598 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3599 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3600 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3604 /* Create a pixmap for the image, either from a file, or from a
3605 string buffer containing data in the same format as an XPM file. */
3606 #ifdef ALLOC_XPM_COLORS
3607 xpm_init_color_cache (f
, &attrs
);
3610 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3614 HDC frame_dc
= get_frame_dc (f
);
3615 hdc
= CreateCompatibleDC (frame_dc
);
3616 release_frame_dc (f
, frame_dc
);
3618 #endif /* HAVE_NTGUI */
3620 if (STRINGP (specified_file
))
3622 Lisp_Object file
= x_find_image_file (specified_file
);
3623 if (!STRINGP (file
))
3625 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3630 /* XpmReadFileToPixmap is not available in the Windows port of
3631 libxpm. But XpmReadFileToImage almost does what we want. */
3632 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3633 &xpm_image
, &xpm_mask
,
3636 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3637 SDATA (file
), &img
->pixmap
, &img
->mask
,
3639 #endif /* HAVE_NTGUI */
3643 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3645 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3646 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3647 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3648 &xpm_image
, &xpm_mask
,
3651 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3653 &img
->pixmap
, &img
->mask
,
3655 #endif /* HAVE_NTGUI */
3658 if (rc
== XpmSuccess
)
3660 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3661 img
->colors
= colors_in_color_table (&img
->ncolors
);
3662 #else /* not ALLOC_XPM_COLORS */
3666 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3667 plus some duplicate attributes. */
3668 if (xpm_image
&& xpm_image
->bitmap
)
3670 img
->pixmap
= xpm_image
->bitmap
;
3671 /* XImageFree in libXpm frees XImage struct without destroying
3672 the bitmap, which is what we want. */
3673 fn_XImageFree (xpm_image
);
3675 if (xpm_mask
&& xpm_mask
->bitmap
)
3677 /* The mask appears to be inverted compared with what we expect.
3678 TODO: invert our expectations. See other places where we
3679 have to invert bits because our idea of masks is backwards. */
3681 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3683 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3684 SelectObject (hdc
, old_obj
);
3686 img
->mask
= xpm_mask
->bitmap
;
3687 fn_XImageFree (xpm_mask
);
3692 #endif /* HAVE_NTGUI */
3694 /* Remember allocated colors. */
3695 img
->ncolors
= attrs
.nalloc_pixels
;
3696 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3697 * sizeof *img
->colors
);
3698 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3700 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3701 #ifdef DEBUG_X_COLORS
3702 register_color (img
->colors
[i
]);
3705 #endif /* not ALLOC_XPM_COLORS */
3707 img
->width
= attrs
.width
;
3708 img
->height
= attrs
.height
;
3709 xassert (img
->width
> 0 && img
->height
> 0);
3711 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3713 fn_XpmFreeAttributes (&attrs
);
3715 XpmFreeAttributes (&attrs
);
3716 #endif /* HAVE_NTGUI */
3722 #endif /* HAVE_NTGUI */
3727 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3730 case XpmFileInvalid
:
3731 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3735 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3738 case XpmColorFailed
:
3739 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3743 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3748 #ifdef ALLOC_XPM_COLORS
3749 xpm_free_color_cache ();
3751 return rc
== XpmSuccess
;
3754 #endif /* HAVE_XPM */
3757 /***********************************************************************
3759 ***********************************************************************/
3761 #ifdef COLOR_TABLE_SUPPORT
3763 /* An entry in the color table mapping an RGB color to a pixel color. */
3768 unsigned long pixel
;
3770 /* Next in color table collision list. */
3771 struct ct_color
*next
;
3774 /* The bucket vector size to use. Must be prime. */
3778 /* Value is a hash of the RGB color given by R, G, and B. */
3780 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
3782 /* The color hash table. */
3784 struct ct_color
**ct_table
;
3786 /* Number of entries in the color table. */
3788 int ct_colors_allocated
;
3790 /* Initialize the color table. */
3795 int size
= CT_SIZE
* sizeof (*ct_table
);
3796 ct_table
= (struct ct_color
**) xmalloc (size
);
3797 bzero (ct_table
, size
);
3798 ct_colors_allocated
= 0;
3802 /* Free memory associated with the color table. */
3808 struct ct_color
*p
, *next
;
3810 for (i
= 0; i
< CT_SIZE
; ++i
)
3811 for (p
= ct_table
[i
]; p
; p
= next
)
3822 /* Value is a pixel color for RGB color R, G, B on frame F. If an
3823 entry for that color already is in the color table, return the
3824 pixel color of that entry. Otherwise, allocate a new color for R,
3825 G, B, and make an entry in the color table. */
3827 static unsigned long
3828 lookup_rgb_color (f
, r
, g
, b
)
3832 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
3833 int i
= hash
% CT_SIZE
;
3835 Display_Info
*dpyinfo
;
3837 /* Handle TrueColor visuals specially, which improves performance by
3838 two orders of magnitude. Freeing colors on TrueColor visuals is
3839 a nop, and pixel colors specify RGB values directly. See also
3840 the Xlib spec, chapter 3.1. */
3841 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3842 if (dpyinfo
->red_bits
> 0)
3844 unsigned long pr
, pg
, pb
;
3846 /* Apply gamma-correction like normal color allocation does. */
3850 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
3851 gamma_correct (f
, &color
);
3852 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
3855 /* Scale down RGB values to the visual's bits per RGB, and shift
3856 them to the right position in the pixel color. Note that the
3857 original RGB values are 16-bit values, as usual in X. */
3858 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
3859 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
3860 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
3862 /* Assemble the pixel color. */
3863 return pr
| pg
| pb
;
3866 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3867 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
3873 #ifdef HAVE_X_WINDOWS
3882 cmap
= FRAME_X_COLORMAP (f
);
3883 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3886 ++ct_colors_allocated
;
3887 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3891 p
->pixel
= color
.pixel
;
3892 p
->next
= ct_table
[i
];
3896 return FRAME_FOREGROUND_PIXEL (f
);
3901 color
= PALETTERGB (r
, g
, b
);
3903 color
= RGB_TO_ULONG (r
, g
, b
);
3904 #endif /* HAVE_NTGUI */
3905 ++ct_colors_allocated
;
3906 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3911 p
->next
= ct_table
[i
];
3913 #endif /* HAVE_X_WINDOWS */
3921 /* Look up pixel color PIXEL which is used on frame F in the color
3922 table. If not already present, allocate it. Value is PIXEL. */
3924 static unsigned long
3925 lookup_pixel_color (f
, pixel
)
3927 unsigned long pixel
;
3929 int i
= pixel
% CT_SIZE
;
3932 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3933 if (p
->pixel
== pixel
)
3942 #ifdef HAVE_X_WINDOWS
3943 cmap
= FRAME_X_COLORMAP (f
);
3944 color
.pixel
= pixel
;
3945 x_query_color (f
, &color
);
3946 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3949 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
3950 color
.pixel
= pixel
;
3951 XQueryColor (NULL
, cmap
, &color
);
3952 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3954 #endif /* HAVE_X_WINDOWS */
3958 ++ct_colors_allocated
;
3960 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3965 p
->next
= ct_table
[i
];
3969 return FRAME_FOREGROUND_PIXEL (f
);
3975 /* Value is a vector of all pixel colors contained in the color table,
3976 allocated via xmalloc. Set *N to the number of colors. */
3978 static unsigned long *
3979 colors_in_color_table (n
)
3984 unsigned long *colors
;
3986 if (ct_colors_allocated
== 0)
3993 colors
= (unsigned long *) xmalloc (ct_colors_allocated
3995 *n
= ct_colors_allocated
;
3997 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
3998 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3999 colors
[j
++] = p
->pixel
;
4005 #else /* COLOR_TABLE_SUPPORT */
4007 static unsigned long
4008 lookup_rgb_color (f
, r
, g
, b
)
4012 unsigned long pixel
;
4015 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4016 gamma_correct (f
, &pixel
);
4020 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4021 #endif /* HAVE_NTGUI */
4030 #endif /* COLOR_TABLE_SUPPORT */
4033 /***********************************************************************
4035 ***********************************************************************/
4037 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4038 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4039 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4042 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4043 #endif /* HAVE_NTGUI */
4045 /* Non-zero means draw a cross on images having `:conversion
4048 int cross_disabled_images
;
4050 /* Edge detection matrices for different edge-detection
4053 static int emboss_matrix
[9] = {
4055 2, -1, 0, /* y - 1 */
4057 0, 1, -2 /* y + 1 */
4060 static int laplace_matrix
[9] = {
4062 1, 0, 0, /* y - 1 */
4064 0, 0, -1 /* y + 1 */
4067 /* Value is the intensity of the color whose red/green/blue values
4070 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4073 /* On frame F, return an array of XColor structures describing image
4074 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4075 non-zero means also fill the red/green/blue members of the XColor
4076 structures. Value is a pointer to the array of XColors structures,
4077 allocated with xmalloc; it must be freed by the caller. */
4080 x_to_xcolors (f
, img
, rgb_p
)
4087 XImagePtr_or_DC ximg
;
4091 #endif /* HAVE_NTGUI */
4093 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4096 /* Get the X image IMG->pixmap. */
4097 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4098 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4100 /* Load the image into a memory device context. */
4101 hdc
= get_frame_dc (f
);
4102 ximg
= CreateCompatibleDC (hdc
);
4103 release_frame_dc (f
, hdc
);
4104 prev
= SelectObject (ximg
, img
->pixmap
);
4105 #endif /* HAVE_NTGUI */
4107 /* Fill the `pixel' members of the XColor array. I wished there
4108 were an easy and portable way to circumvent XGetPixel. */
4110 for (y
= 0; y
< img
->height
; ++y
)
4114 #ifdef HAVE_X_WINDOWS
4115 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4116 p
->pixel
= XGetPixel (ximg
, x
, y
);
4118 x_query_colors (f
, row
, img
->width
);
4122 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4124 /* W32_TODO: palette support needed here? */
4125 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4129 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4130 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4131 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4134 p
->red
= 256 * GetRValue (p
->pixel
);
4135 p
->green
= 256 * GetGValue (p
->pixel
);
4136 p
->blue
= 256 * GetBValue (p
->pixel
);
4137 #endif /* HAVE_NTGUI */
4140 #endif /* HAVE_X_WINDOWS */
4143 Destroy_Image (ximg
, prev
);
4150 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4151 created with CreateDIBSection, with the pointer to the bit values
4152 stored in ximg->data. */
4154 static void XPutPixel (ximg
, x
, y
, color
)
4159 int width
= ximg
->info
.bmiHeader
.biWidth
;
4160 int height
= ximg
->info
.bmiHeader
.biHeight
;
4161 unsigned char * pixel
;
4163 /* True color images. */
4164 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4166 int rowbytes
= width
* 3;
4167 /* Ensure scanlines are aligned on 4 byte boundaries. */
4169 rowbytes
+= 4 - (rowbytes
% 4);
4171 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4172 /* Windows bitmaps are in BGR order. */
4173 *pixel
= GetBValue (color
);
4174 *(pixel
+ 1) = GetGValue (color
);
4175 *(pixel
+ 2) = GetRValue (color
);
4177 /* Monochrome images. */
4178 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4180 int rowbytes
= width
/ 8;
4181 /* Ensure scanlines are aligned on 4 byte boundaries. */
4183 rowbytes
+= 4 - (rowbytes
% 4);
4184 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4185 /* Filter out palette info. */
4186 if (color
& 0x00ffffff)
4187 *pixel
= *pixel
| (1 << x
% 8);
4189 *pixel
= *pixel
& ~(1 << x
% 8);
4192 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4195 #endif /* HAVE_NTGUI */
4197 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4198 RGB members are set. F is the frame on which this all happens.
4199 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4202 x_from_xcolors (f
, img
, colors
)
4212 init_color_table ();
4214 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4217 for (y
= 0; y
< img
->height
; ++y
)
4218 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4220 unsigned long pixel
;
4221 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4222 XPutPixel (oimg
, x
, y
, pixel
);
4226 x_clear_image_1 (f
, img
, 1, 0, 1);
4228 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4229 x_destroy_x_image (oimg
);
4230 img
->pixmap
= pixmap
;
4231 #ifdef COLOR_TABLE_SUPPORT
4232 img
->colors
= colors_in_color_table (&img
->ncolors
);
4233 free_color_table ();
4234 #endif /* COLOR_TABLE_SUPPORT */
4238 /* On frame F, perform edge-detection on image IMG.
4240 MATRIX is a nine-element array specifying the transformation
4241 matrix. See emboss_matrix for an example.
4243 COLOR_ADJUST is a color adjustment added to each pixel of the
4247 x_detect_edges (f
, img
, matrix
, color_adjust
)
4250 int matrix
[9], color_adjust
;
4252 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4256 for (i
= sum
= 0; i
< 9; ++i
)
4257 sum
+= abs (matrix
[i
]);
4259 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4261 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4263 for (y
= 0; y
< img
->height
; ++y
)
4265 p
= COLOR (new, 0, y
);
4266 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4267 p
= COLOR (new, img
->width
- 1, y
);
4268 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4271 for (x
= 1; x
< img
->width
- 1; ++x
)
4273 p
= COLOR (new, x
, 0);
4274 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4275 p
= COLOR (new, x
, img
->height
- 1);
4276 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4279 for (y
= 1; y
< img
->height
- 1; ++y
)
4281 p
= COLOR (new, 1, y
);
4283 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4285 int r
, g
, b
, y1
, x1
;
4288 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4289 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4292 XColor
*t
= COLOR (colors
, x1
, y1
);
4293 r
+= matrix
[i
] * t
->red
;
4294 g
+= matrix
[i
] * t
->green
;
4295 b
+= matrix
[i
] * t
->blue
;
4298 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4299 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4300 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4301 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4306 x_from_xcolors (f
, img
, new);
4312 /* Perform the pre-defined `emboss' edge-detection on image IMG
4320 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4324 /* Transform image IMG which is used on frame F with a Laplace
4325 edge-detection algorithm. The result is an image that can be used
4326 to draw disabled buttons, for example. */
4333 x_detect_edges (f
, img
, laplace_matrix
, 45000);
4337 /* Perform edge-detection on image IMG on frame F, with specified
4338 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4340 MATRIX must be either
4342 - a list of at least 9 numbers in row-major form
4343 - a vector of at least 9 numbers
4345 COLOR_ADJUST nil means use a default; otherwise it must be a
4349 x_edge_detection (f
, img
, matrix
, color_adjust
)
4352 Lisp_Object matrix
, color_adjust
;
4360 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
4361 ++i
, matrix
= XCDR (matrix
))
4362 trans
[i
] = XFLOATINT (XCAR (matrix
));
4364 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
4366 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
4367 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
4370 if (NILP (color_adjust
))
4371 color_adjust
= make_number (0xffff / 2);
4373 if (i
== 9 && NUMBERP (color_adjust
))
4374 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
4378 /* Transform image IMG on frame F so that it looks disabled. */
4381 x_disable_image (f
, img
)
4385 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4387 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
4389 int n_planes
= dpyinfo
->n_planes
;
4390 #endif /* HAVE_NTGUI */
4394 /* Color (or grayscale). Convert to gray, and equalize. Just
4395 drawing such images with a stipple can look very odd, so
4396 we're using this method instead. */
4397 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4399 const int h
= 15000;
4400 const int l
= 30000;
4402 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
4406 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
4407 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
4408 p
->red
= p
->green
= p
->blue
= i2
;
4411 x_from_xcolors (f
, img
, colors
);
4414 /* Draw a cross over the disabled image, if we must or if we
4416 if (n_planes
< 2 || cross_disabled_images
)
4419 Display
*dpy
= FRAME_X_DISPLAY (f
);
4423 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4424 #define MaskForeground(f) PIX_MASK_DRAW (f)
4426 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4427 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4430 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
4431 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
4432 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
4433 img
->width
- 1, img
->height
- 1);
4434 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
4440 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
4441 XSetForeground (dpy
, gc
, MaskForeground (f
));
4442 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
4443 img
->width
- 1, img
->height
- 1);
4444 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
4452 hdc
= get_frame_dc (f
);
4453 bmpdc
= CreateCompatibleDC (hdc
);
4454 release_frame_dc (f
, hdc
);
4456 prev
= SelectObject (bmpdc
, img
->pixmap
);
4458 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
4459 MoveToEx (bmpdc
, 0, 0, NULL
);
4460 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4461 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4462 LineTo (bmpdc
, img
->width
- 1, 0);
4466 SelectObject (bmpdc
, img
->mask
);
4467 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
4468 MoveToEx (bmpdc
, 0, 0, NULL
);
4469 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4470 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4471 LineTo (bmpdc
, img
->width
- 1, 0);
4473 SelectObject (bmpdc
, prev
);
4475 #endif /* HAVE_NTGUI */
4480 /* Build a mask for image IMG which is used on frame F. FILE is the
4481 name of an image file, for error messages. HOW determines how to
4482 determine the background color of IMG. If it is a list '(R G B)',
4483 with R, G, and B being integers >= 0, take that as the color of the
4484 background. Otherwise, determine the background color of IMG
4485 heuristically. Value is non-zero if successful. */
4488 x_build_heuristic_mask (f
, img
, how
)
4493 XImagePtr_or_DC ximg
;
4501 #endif /* HAVE_NTGUI */
4502 int x
, y
, rc
, use_img_background
;
4503 unsigned long bg
= 0;
4507 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4508 img
->mask
= NO_PIXMAP
;
4509 img
->background_transparent_valid
= 0;
4513 /* Create an image and pixmap serving as mask. */
4514 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
4515 &mask_img
, &img
->mask
);
4519 /* Get the X image of IMG->pixmap. */
4520 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
4521 img
->width
, img
->height
,
4524 /* Create the bit array serving as mask. */
4525 row_width
= (img
->width
+ 7) / 8;
4526 mask_img
= xmalloc (row_width
* img
->height
);
4527 bzero (mask_img
, row_width
* img
->height
);
4529 /* Create a memory device context for IMG->pixmap. */
4530 frame_dc
= get_frame_dc (f
);
4531 ximg
= CreateCompatibleDC (frame_dc
);
4532 release_frame_dc (f
, frame_dc
);
4533 prev
= SelectObject (ximg
, img
->pixmap
);
4534 #endif /* HAVE_NTGUI */
4536 /* Determine the background color of ximg. If HOW is `(R G B)'
4537 take that as color. Otherwise, use the image's background color. */
4538 use_img_background
= 1;
4544 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
4546 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
4550 if (i
== 3 && NILP (how
))
4552 char color_name
[30];
4553 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
4556 0x00ffffff & /* Filter out palette info. */
4557 #endif /* HAVE_NTGUI */
4558 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
4559 use_img_background
= 0;
4563 if (use_img_background
)
4564 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
4566 /* Set all bits in mask_img to 1 whose color in ximg is different
4567 from the background color bg. */
4569 for (y
= 0; y
< img
->height
; ++y
)
4570 for (x
= 0; x
< img
->width
; ++x
)
4571 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
4572 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
)));
4574 /* Fill in the background_transparent field while we have the mask handy. */
4575 image_background_transparent (img
, f
, mask_img
);
4577 /* Put mask_img into img->mask. */
4578 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
4579 x_destroy_x_image (mask_img
);
4582 for (y
= 0; y
< img
->height
; ++y
)
4583 for (x
= 0; x
< img
->width
; ++x
)
4585 COLORREF p
= GetPixel (ximg
, x
, y
);
4587 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
4590 /* Create the mask image. */
4591 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
4593 /* Fill in the background_transparent field while we have the mask handy. */
4594 SelectObject (ximg
, img
->mask
);
4595 image_background_transparent (img
, f
, ximg
);
4597 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
4599 #endif /* HAVE_NTGUI */
4601 Destroy_Image (ximg
, prev
);
4607 /***********************************************************************
4608 PBM (mono, gray, color)
4609 ***********************************************************************/
4611 static int pbm_image_p
P_ ((Lisp_Object object
));
4612 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
4613 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
4615 /* The symbol `pbm' identifying images of this type. */
4619 /* Indices of image specification fields in gs_format, below. */
4621 enum pbm_keyword_index
4637 /* Vector of image_keyword structures describing the format
4638 of valid user-defined image specifications. */
4640 static struct image_keyword pbm_format
[PBM_LAST
] =
4642 {":type", IMAGE_SYMBOL_VALUE
, 1},
4643 {":file", IMAGE_STRING_VALUE
, 0},
4644 {":data", IMAGE_STRING_VALUE
, 0},
4645 {":ascent", IMAGE_ASCENT_VALUE
, 0},
4646 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
4647 {":relief", IMAGE_INTEGER_VALUE
, 0},
4648 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4649 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4650 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4651 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
4652 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
4655 /* Structure describing the image type `pbm'. */
4657 static struct image_type pbm_type
=
4667 /* Return non-zero if OBJECT is a valid PBM image specification. */
4670 pbm_image_p (object
)
4673 struct image_keyword fmt
[PBM_LAST
];
4675 bcopy (pbm_format
, fmt
, sizeof fmt
);
4677 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
4680 /* Must specify either :data or :file. */
4681 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
4685 /* Scan a decimal number from *S and return it. Advance *S while
4686 reading the number. END is the end of the string. Value is -1 at
4690 pbm_scan_number (s
, end
)
4691 unsigned char **s
, *end
;
4693 int c
= 0, val
= -1;
4697 /* Skip white-space. */
4698 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4703 /* Skip comment to end of line. */
4704 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
4707 else if (isdigit (c
))
4709 /* Read decimal number. */
4711 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
4712 val
= 10 * val
+ c
- '0';
4724 #if 0 /* Unused. ++kfs */
4726 /* Read FILE into memory. Value is a pointer to a buffer allocated
4727 with xmalloc holding FILE's contents. Value is null if an error
4728 occurred. *SIZE is set to the size of the file. */
4731 pbm_read_file (file
, size
)
4739 if (stat (SDATA (file
), &st
) == 0
4740 && (fp
= fopen (SDATA (file
), "rb")) != NULL
4741 && (buf
= (char *) xmalloc (st
.st_size
),
4742 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
4761 #endif /* HAVE_NTGUI */
4763 /* Load PBM image IMG for use on frame F. */
4771 int width
, height
, max_color_idx
= 0;
4773 Lisp_Object file
, specified_file
;
4774 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
4775 struct gcpro gcpro1
;
4776 unsigned char *contents
= NULL
;
4777 unsigned char *end
, *p
;
4780 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4784 if (STRINGP (specified_file
))
4786 file
= x_find_image_file (specified_file
);
4787 if (!STRINGP (file
))
4789 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4794 contents
= slurp_file (SDATA (file
), &size
);
4795 if (contents
== NULL
)
4797 image_error ("Error reading `%s'", file
, Qnil
);
4803 end
= contents
+ size
;
4808 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4810 end
= p
+ SBYTES (data
);
4813 /* Check magic number. */
4814 if (end
- p
< 2 || *p
++ != 'P')
4816 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
4826 raw_p
= 0, type
= PBM_MONO
;
4830 raw_p
= 0, type
= PBM_GRAY
;
4834 raw_p
= 0, type
= PBM_COLOR
;
4838 raw_p
= 1, type
= PBM_MONO
;
4842 raw_p
= 1, type
= PBM_GRAY
;
4846 raw_p
= 1, type
= PBM_COLOR
;
4850 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
4854 /* Read width, height, maximum color-component. Characters
4855 starting with `#' up to the end of a line are ignored. */
4856 width
= pbm_scan_number (&p
, end
);
4857 height
= pbm_scan_number (&p
, end
);
4859 if (type
!= PBM_MONO
)
4861 max_color_idx
= pbm_scan_number (&p
, end
);
4862 if (raw_p
&& max_color_idx
> 255)
4863 max_color_idx
= 255;
4868 || (type
!= PBM_MONO
&& max_color_idx
< 0))
4871 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4872 &ximg
, &img
->pixmap
))
4875 /* Initialize the color hash table. */
4876 init_color_table ();
4878 if (type
== PBM_MONO
)
4881 struct image_keyword fmt
[PBM_LAST
];
4882 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
4883 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
4885 /* Parse the image specification. */
4886 bcopy (pbm_format
, fmt
, sizeof fmt
);
4887 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
4889 /* Get foreground and background colors, maybe allocate colors. */
4890 if (fmt
[PBM_FOREGROUND
].count
4891 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
4892 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
4893 if (fmt
[PBM_BACKGROUND
].count
4894 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
4896 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
4897 img
->background
= bg
;
4898 img
->background_valid
= 1;
4901 for (y
= 0; y
< height
; ++y
)
4902 for (x
= 0; x
< width
; ++x
)
4912 g
= pbm_scan_number (&p
, end
);
4914 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
4919 for (y
= 0; y
< height
; ++y
)
4920 for (x
= 0; x
< width
; ++x
)
4924 if (type
== PBM_GRAY
)
4925 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
4934 r
= pbm_scan_number (&p
, end
);
4935 g
= pbm_scan_number (&p
, end
);
4936 b
= pbm_scan_number (&p
, end
);
4939 if (r
< 0 || g
< 0 || b
< 0)
4941 x_destroy_x_image (ximg
);
4942 image_error ("Invalid pixel value in image `%s'",
4947 /* RGB values are now in the range 0..max_color_idx.
4948 Scale this to the range 0..0xffff supported by X. */
4949 r
= (double) r
* 65535 / max_color_idx
;
4950 g
= (double) g
* 65535 / max_color_idx
;
4951 b
= (double) b
* 65535 / max_color_idx
;
4952 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
4956 #ifdef COLOR_TABLE_SUPPORT
4957 /* Store in IMG->colors the colors allocated for the image, and
4958 free the color table. */
4959 img
->colors
= colors_in_color_table (&img
->ncolors
);
4960 free_color_table ();
4961 #endif /* COLOR_TABLE_SUPPORT */
4964 img
->height
= height
;
4966 /* Maybe fill in the background field while we have ximg handy. */
4968 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4969 IMAGE_BACKGROUND (img
, f
, ximg
);
4971 /* Put the image into a pixmap. */
4972 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4973 x_destroy_x_image (ximg
);
4975 /* X and W32 versions did it here, MAC version above. ++kfs
4977 img->height = height; */
4985 /***********************************************************************
4987 ***********************************************************************/
4989 #if defined (HAVE_PNG) || defined (MAC_OS)
4991 /* Function prototypes. */
4993 static int png_image_p
P_ ((Lisp_Object object
));
4994 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
4996 /* The symbol `png' identifying images of this type. */
5000 /* Indices of image specification fields in png_format, below. */
5002 enum png_keyword_index
5017 /* Vector of image_keyword structures describing the format
5018 of valid user-defined image specifications. */
5020 static struct image_keyword png_format
[PNG_LAST
] =
5022 {":type", IMAGE_SYMBOL_VALUE
, 1},
5023 {":data", IMAGE_STRING_VALUE
, 0},
5024 {":file", IMAGE_STRING_VALUE
, 0},
5025 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5026 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5027 {":relief", IMAGE_INTEGER_VALUE
, 0},
5028 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5029 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5030 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5031 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5034 /* Structure describing the image type `png'. */
5036 static struct image_type png_type
=
5045 /* Return non-zero if OBJECT is a valid PNG image specification. */
5048 png_image_p (object
)
5051 struct image_keyword fmt
[PNG_LAST
];
5052 bcopy (png_format
, fmt
, sizeof fmt
);
5054 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5057 /* Must specify either the :data or :file keyword. */
5058 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5061 #endif /* HAVE_PNG || MAC_OS */
5066 #if defined HAVE_LIBPNG_PNG_H
5067 # include <libpng/png.h>
5073 /* PNG library details. */
5075 DEF_IMGLIB_FN (png_get_io_ptr
);
5076 DEF_IMGLIB_FN (png_check_sig
);
5077 DEF_IMGLIB_FN (png_create_read_struct
);
5078 DEF_IMGLIB_FN (png_create_info_struct
);
5079 DEF_IMGLIB_FN (png_destroy_read_struct
);
5080 DEF_IMGLIB_FN (png_set_read_fn
);
5081 DEF_IMGLIB_FN (png_init_io
);
5082 DEF_IMGLIB_FN (png_set_sig_bytes
);
5083 DEF_IMGLIB_FN (png_read_info
);
5084 DEF_IMGLIB_FN (png_get_IHDR
);
5085 DEF_IMGLIB_FN (png_get_valid
);
5086 DEF_IMGLIB_FN (png_set_strip_16
);
5087 DEF_IMGLIB_FN (png_set_expand
);
5088 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5089 DEF_IMGLIB_FN (png_set_background
);
5090 DEF_IMGLIB_FN (png_get_bKGD
);
5091 DEF_IMGLIB_FN (png_read_update_info
);
5092 DEF_IMGLIB_FN (png_get_channels
);
5093 DEF_IMGLIB_FN (png_get_rowbytes
);
5094 DEF_IMGLIB_FN (png_read_image
);
5095 DEF_IMGLIB_FN (png_read_end
);
5096 DEF_IMGLIB_FN (png_error
);
5099 init_png_functions (void)
5103 /* Ensure zlib is loaded. Try debug version first. */
5104 if (!LoadLibrary ("zlibd.dll")
5105 && !LoadLibrary ("zlib.dll"))
5108 /* Try loading libpng under probable names. */
5109 if (!(library
= LoadLibrary ("libpng13d.dll"))
5110 && !(library
= LoadLibrary ("libpng13.dll"))
5111 && !(library
= LoadLibrary ("libpng12d.dll"))
5112 && !(library
= LoadLibrary ("libpng12.dll"))
5113 && !(library
= LoadLibrary ("libpng.dll")))
5116 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5117 LOAD_IMGLIB_FN (library
, png_check_sig
);
5118 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5119 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5120 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5121 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5122 LOAD_IMGLIB_FN (library
, png_init_io
);
5123 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5124 LOAD_IMGLIB_FN (library
, png_read_info
);
5125 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5126 LOAD_IMGLIB_FN (library
, png_get_valid
);
5127 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5128 LOAD_IMGLIB_FN (library
, png_set_expand
);
5129 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5130 LOAD_IMGLIB_FN (library
, png_set_background
);
5131 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5132 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5133 LOAD_IMGLIB_FN (library
, png_get_channels
);
5134 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5135 LOAD_IMGLIB_FN (library
, png_read_image
);
5136 LOAD_IMGLIB_FN (library
, png_read_end
);
5137 LOAD_IMGLIB_FN (library
, png_error
);
5142 #define fn_png_get_io_ptr png_get_io_ptr
5143 #define fn_png_check_sig png_check_sig
5144 #define fn_png_create_read_struct png_create_read_struct
5145 #define fn_png_create_info_struct png_create_info_struct
5146 #define fn_png_destroy_read_struct png_destroy_read_struct
5147 #define fn_png_set_read_fn png_set_read_fn
5148 #define fn_png_init_io png_init_io
5149 #define fn_png_set_sig_bytes png_set_sig_bytes
5150 #define fn_png_read_info png_read_info
5151 #define fn_png_get_IHDR png_get_IHDR
5152 #define fn_png_get_valid png_get_valid
5153 #define fn_png_set_strip_16 png_set_strip_16
5154 #define fn_png_set_expand png_set_expand
5155 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5156 #define fn_png_set_background png_set_background
5157 #define fn_png_get_bKGD png_get_bKGD
5158 #define fn_png_read_update_info png_read_update_info
5159 #define fn_png_get_channels png_get_channels
5160 #define fn_png_get_rowbytes png_get_rowbytes
5161 #define fn_png_read_image png_read_image
5162 #define fn_png_read_end png_read_end
5163 #define fn_png_error png_error
5165 #endif /* HAVE_NTGUI */
5167 /* Error and warning handlers installed when the PNG library
5171 my_png_error (png_ptr
, msg
)
5172 png_struct
*png_ptr
;
5175 xassert (png_ptr
!= NULL
);
5176 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5177 longjmp (png_ptr
->jmpbuf
, 1);
5182 my_png_warning (png_ptr
, msg
)
5183 png_struct
*png_ptr
;
5186 xassert (png_ptr
!= NULL
);
5187 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5190 /* Memory source for PNG decoding. */
5192 struct png_memory_storage
5194 unsigned char *bytes
; /* The data */
5195 size_t len
; /* How big is it? */
5196 int index
; /* Where are we? */
5200 /* Function set as reader function when reading PNG image from memory.
5201 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5202 bytes from the input to DATA. */
5205 png_read_from_memory (png_ptr
, data
, length
)
5206 png_structp png_ptr
;
5210 struct png_memory_storage
*tbr
5211 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5213 if (length
> tbr
->len
- tbr
->index
)
5214 fn_png_error (png_ptr
, "Read error");
5216 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5217 tbr
->index
= tbr
->index
+ length
;
5220 /* Load PNG image IMG for use on frame F. Value is non-zero if
5228 Lisp_Object file
, specified_file
;
5229 Lisp_Object specified_data
;
5231 XImagePtr ximg
, mask_img
= NULL
;
5232 struct gcpro gcpro1
;
5233 png_struct
*png_ptr
= NULL
;
5234 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5235 FILE *volatile fp
= NULL
;
5237 png_byte
* volatile pixels
= NULL
;
5238 png_byte
** volatile rows
= NULL
;
5239 png_uint_32 width
, height
;
5240 int bit_depth
, color_type
, interlace_type
;
5242 png_uint_32 row_bytes
;
5244 double screen_gamma
;
5245 struct png_memory_storage tbr
; /* Data to be read */
5247 /* Find out what file to load. */
5248 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5249 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5253 if (NILP (specified_data
))
5255 file
= x_find_image_file (specified_file
);
5256 if (!STRINGP (file
))
5258 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5263 /* Open the image file. */
5264 fp
= fopen (SDATA (file
), "rb");
5267 image_error ("Cannot open image file `%s'", file
, Qnil
);
5273 /* Check PNG signature. */
5274 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5275 || !fn_png_check_sig (sig
, sizeof sig
))
5277 image_error ("Not a PNG file: `%s'", file
, Qnil
);
5285 /* Read from memory. */
5286 tbr
.bytes
= SDATA (specified_data
);
5287 tbr
.len
= SBYTES (specified_data
);
5290 /* Check PNG signature. */
5291 if (tbr
.len
< sizeof sig
5292 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
5294 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
5299 /* Need to skip past the signature. */
5300 tbr
.bytes
+= sizeof (sig
);
5303 /* Initialize read and info structs for PNG lib. */
5304 png_ptr
= fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
5305 my_png_error
, my_png_warning
);
5308 if (fp
) fclose (fp
);
5313 info_ptr
= fn_png_create_info_struct (png_ptr
);
5316 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
5317 if (fp
) fclose (fp
);
5322 end_info
= fn_png_create_info_struct (png_ptr
);
5325 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
5326 if (fp
) fclose (fp
);
5331 /* Set error jump-back. We come back here when the PNG library
5332 detects an error. */
5333 if (setjmp (png_ptr
->jmpbuf
))
5337 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5340 if (fp
) fclose (fp
);
5345 /* Read image info. */
5346 if (!NILP (specified_data
))
5347 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
5349 fn_png_init_io (png_ptr
, fp
);
5351 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
5352 fn_png_read_info (png_ptr
, info_ptr
);
5353 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
5354 &interlace_type
, NULL
, NULL
);
5356 /* If image contains simply transparency data, we prefer to
5357 construct a clipping mask. */
5358 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
5363 /* This function is easier to write if we only have to handle
5364 one data format: RGB or RGBA with 8 bits per channel. Let's
5365 transform other formats into that format. */
5367 /* Strip more than 8 bits per channel. */
5368 if (bit_depth
== 16)
5369 fn_png_set_strip_16 (png_ptr
);
5371 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5373 fn_png_set_expand (png_ptr
);
5375 /* Convert grayscale images to RGB. */
5376 if (color_type
== PNG_COLOR_TYPE_GRAY
5377 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5378 fn_png_set_gray_to_rgb (png_ptr
);
5380 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
5382 #if 0 /* Avoid double gamma correction for PNG images. */
5383 { /* Tell the PNG lib to handle gamma correction for us. */
5386 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5387 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
5388 /* The libpng documentation says this is right in this case. */
5389 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5392 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
5393 /* Image contains gamma information. */
5394 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
5396 /* Use the standard default for the image gamma. */
5397 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5401 /* Handle alpha channel by combining the image with a background
5402 color. Do this only if a real alpha channel is supplied. For
5403 simple transparency, we prefer a clipping mask. */
5406 png_color_16
*image_bg
;
5407 Lisp_Object specified_bg
5408 = image_spec_value (img
->spec
, QCbackground
, NULL
);
5410 if (STRINGP (specified_bg
))
5411 /* The user specified `:background', use that. */
5413 /* W32 version incorrectly used COLORREF here!! ++kfs */
5415 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
5417 png_color_16 user_bg
;
5419 bzero (&user_bg
, sizeof user_bg
);
5420 user_bg
.red
= color
.red
>> 8;
5421 user_bg
.green
= color
.green
>> 8;
5422 user_bg
.blue
= color
.blue
>> 8;
5424 fn_png_set_background (png_ptr
, &user_bg
,
5425 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5428 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
5429 /* Image contains a background color with which to
5430 combine the image. */
5431 fn_png_set_background (png_ptr
, image_bg
,
5432 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
5435 /* Image does not contain a background color with which
5436 to combine the image data via an alpha channel. Use
5437 the frame's background instead. */
5438 #ifdef HAVE_X_WINDOWS
5440 png_color_16 frame_background
;
5442 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
5443 x_query_color (f
, &color
);
5445 bzero (&frame_background
, sizeof frame_background
);
5446 frame_background
.red
= color
.red
>> 8;
5447 frame_background
.green
= color
.green
>> 8;
5448 frame_background
.blue
= color
.blue
>> 8;
5449 #endif /* HAVE_X_WINDOWS */
5453 png_color_16 frame_background
;
5454 color
= FRAME_BACKGROUND_PIXEL (f
);
5455 #if 0 /* W32 TODO : Colormap support. */
5456 x_query_color (f
, &color
);
5458 bzero (&frame_background
, sizeof frame_background
);
5459 frame_background
.red
= GetRValue (color
);
5460 frame_background
.green
= GetGValue (color
);
5461 frame_background
.blue
= GetBValue (color
);
5462 #endif /* HAVE_NTGUI */
5465 unsigned long color
;
5466 png_color_16 frame_background
;
5467 color
= FRAME_BACKGROUND_PIXEL (f
);
5468 #if 0 /* MAC/W32 TODO : Colormap support. */
5469 x_query_color (f
, &color
);
5471 bzero (&frame_background
, sizeof frame_background
);
5472 frame_background
.red
= RED_FROM_ULONG (color
);
5473 frame_background
.green
= GREEN_FROM_ULONG (color
);
5474 frame_background
.blue
= BLUE_FROM_ULONG (color
);
5477 fn_png_set_background (png_ptr
, &frame_background
,
5478 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5482 /* Update info structure. */
5483 fn_png_read_update_info (png_ptr
, info_ptr
);
5485 /* Get number of channels. Valid values are 1 for grayscale images
5486 and images with a palette, 2 for grayscale images with transparency
5487 information (alpha channel), 3 for RGB images, and 4 for RGB
5488 images with alpha channel, i.e. RGBA. If conversions above were
5489 sufficient we should only have 3 or 4 channels here. */
5490 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
5491 xassert (channels
== 3 || channels
== 4);
5493 /* Number of bytes needed for one row of the image. */
5494 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
5496 /* Allocate memory for the image. */
5497 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
5498 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
5499 for (i
= 0; i
< height
; ++i
)
5500 rows
[i
] = pixels
+ i
* row_bytes
;
5502 /* Read the entire image. */
5503 fn_png_read_image (png_ptr
, rows
);
5504 fn_png_read_end (png_ptr
, info_ptr
);
5511 /* Create the X image and pixmap. */
5512 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
5516 /* Create an image and pixmap serving as mask if the PNG image
5517 contains an alpha channel. */
5520 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
5521 &mask_img
, &img
->mask
))
5523 x_destroy_x_image (ximg
);
5524 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5525 img
->pixmap
= NO_PIXMAP
;
5529 /* Fill the X image and mask from PNG data. */
5530 init_color_table ();
5532 for (y
= 0; y
< height
; ++y
)
5534 png_byte
*p
= rows
[y
];
5536 for (x
= 0; x
< width
; ++x
)
5543 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5544 /* An alpha channel, aka mask channel, associates variable
5545 transparency with an image. Where other image formats
5546 support binary transparency---fully transparent or fully
5547 opaque---PNG allows up to 254 levels of partial transparency.
5548 The PNG library implements partial transparency by combining
5549 the image with a specified background color.
5551 I'm not sure how to handle this here nicely: because the
5552 background on which the image is displayed may change, for
5553 real alpha channel support, it would be necessary to create
5554 a new image for each possible background.
5556 What I'm doing now is that a mask is created if we have
5557 boolean transparency information. Otherwise I'm using
5558 the frame's background color to combine the image with. */
5563 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
5569 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5570 /* Set IMG's background color from the PNG image, unless the user
5574 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
5576 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
5577 img
->background_valid
= 1;
5581 #ifdef COLOR_TABLE_SUPPORT
5582 /* Remember colors allocated for this image. */
5583 img
->colors
= colors_in_color_table (&img
->ncolors
);
5584 free_color_table ();
5585 #endif /* COLOR_TABLE_SUPPORT */
5588 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5593 img
->height
= height
;
5595 /* Maybe fill in the background field while we have ximg handy. */
5596 IMAGE_BACKGROUND (img
, f
, ximg
);
5598 /* Put the image into the pixmap, then free the X image and its buffer. */
5599 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5600 x_destroy_x_image (ximg
);
5602 /* Same for the mask. */
5605 /* Fill in the background_transparent field while we have the mask
5607 image_background_transparent (img
, f
, mask_img
);
5609 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5610 x_destroy_x_image (mask_img
);
5617 #else /* HAVE_PNG */
5626 if (MyCGImageCreateWithPNGDataProvider
)
5627 return image_load_quartz2d (f
, img
, 1);
5630 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
5634 #endif /* !HAVE_PNG */
5638 /***********************************************************************
5640 ***********************************************************************/
5642 #if defined (HAVE_JPEG) || defined (MAC_OS)
5644 static int jpeg_image_p
P_ ((Lisp_Object object
));
5645 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
5647 /* The symbol `jpeg' identifying images of this type. */
5651 /* Indices of image specification fields in gs_format, below. */
5653 enum jpeg_keyword_index
5662 JPEG_HEURISTIC_MASK
,
5668 /* Vector of image_keyword structures describing the format
5669 of valid user-defined image specifications. */
5671 static struct image_keyword jpeg_format
[JPEG_LAST
] =
5673 {":type", IMAGE_SYMBOL_VALUE
, 1},
5674 {":data", IMAGE_STRING_VALUE
, 0},
5675 {":file", IMAGE_STRING_VALUE
, 0},
5676 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5677 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5678 {":relief", IMAGE_INTEGER_VALUE
, 0},
5679 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5680 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5681 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5682 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5685 /* Structure describing the image type `jpeg'. */
5687 static struct image_type jpeg_type
=
5696 /* Return non-zero if OBJECT is a valid JPEG image specification. */
5699 jpeg_image_p (object
)
5702 struct image_keyword fmt
[JPEG_LAST
];
5704 bcopy (jpeg_format
, fmt
, sizeof fmt
);
5706 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
5709 /* Must specify either the :data or :file keyword. */
5710 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
5713 #endif /* HAVE_JPEG || MAC_OS */
5717 /* Work around a warning about HAVE_STDLIB_H being redefined in
5719 #ifdef HAVE_STDLIB_H
5720 #define HAVE_STDLIB_H_1
5721 #undef HAVE_STDLIB_H
5722 #endif /* HAVE_STLIB_H */
5724 #include <jpeglib.h>
5728 #ifdef HAVE_STLIB_H_1
5729 #define HAVE_STDLIB_H 1
5734 /* JPEG library details. */
5735 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
5736 DEF_IMGLIB_FN (jpeg_start_decompress
);
5737 DEF_IMGLIB_FN (jpeg_finish_decompress
);
5738 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
5739 DEF_IMGLIB_FN (jpeg_read_header
);
5740 DEF_IMGLIB_FN (jpeg_read_scanlines
);
5741 DEF_IMGLIB_FN (jpeg_stdio_src
);
5742 DEF_IMGLIB_FN (jpeg_std_error
);
5743 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
5746 init_jpeg_functions (void)
5750 if (!(library
= LoadLibrary ("libjpeg.dll"))
5751 && !(library
= LoadLibrary ("jpeg-62.dll"))
5752 && !(library
= LoadLibrary ("jpeg.dll")))
5755 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
5756 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
5757 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
5758 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
5759 LOAD_IMGLIB_FN (library
, jpeg_stdio_src
);
5760 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
5761 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
5762 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
5763 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
5767 /* Wrapper since we can't directly assign the function pointer
5768 to another function pointer that was declared more completely easily. */
5770 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
5771 j_decompress_ptr cinfo
;
5774 return fn_jpeg_resync_to_restart (cinfo
, desired
);
5779 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
5780 #define fn_jpeg_start_decompress jpeg_start_decompress
5781 #define fn_jpeg_finish_decompress jpeg_finish_decompress
5782 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
5783 #define fn_jpeg_read_header jpeg_read_header
5784 #define fn_jpeg_read_scanlines jpeg_read_scanlines
5785 #define fn_jpeg_stdio_src jpeg_stdio_src
5786 #define fn_jpeg_std_error jpeg_std_error
5787 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
5789 #endif /* HAVE_NTGUI */
5791 struct my_jpeg_error_mgr
5793 struct jpeg_error_mgr pub
;
5794 jmp_buf setjmp_buffer
;
5799 my_error_exit (cinfo
)
5802 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
5803 longjmp (mgr
->setjmp_buffer
, 1);
5807 /* Init source method for JPEG data source manager. Called by
5808 jpeg_read_header() before any data is actually read. See
5809 libjpeg.doc from the JPEG lib distribution. */
5812 our_init_source (cinfo
)
5813 j_decompress_ptr cinfo
;
5818 /* Fill input buffer method for JPEG data source manager. Called
5819 whenever more data is needed. We read the whole image in one step,
5820 so this only adds a fake end of input marker at the end. */
5823 our_fill_input_buffer (cinfo
)
5824 j_decompress_ptr cinfo
;
5826 /* Insert a fake EOI marker. */
5827 struct jpeg_source_mgr
*src
= cinfo
->src
;
5828 static JOCTET buffer
[2];
5830 buffer
[0] = (JOCTET
) 0xFF;
5831 buffer
[1] = (JOCTET
) JPEG_EOI
;
5833 src
->next_input_byte
= buffer
;
5834 src
->bytes_in_buffer
= 2;
5839 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
5840 is the JPEG data source manager. */
5843 our_skip_input_data (cinfo
, num_bytes
)
5844 j_decompress_ptr cinfo
;
5847 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5851 if (num_bytes
> src
->bytes_in_buffer
)
5852 ERREXIT (cinfo
, JERR_INPUT_EOF
);
5854 src
->bytes_in_buffer
-= num_bytes
;
5855 src
->next_input_byte
+= num_bytes
;
5860 /* Method to terminate data source. Called by
5861 jpeg_finish_decompress() after all data has been processed. */
5864 our_term_source (cinfo
)
5865 j_decompress_ptr cinfo
;
5870 /* Set up the JPEG lib for reading an image from DATA which contains
5871 LEN bytes. CINFO is the decompression info structure created for
5872 reading the image. */
5875 jpeg_memory_src (cinfo
, data
, len
)
5876 j_decompress_ptr cinfo
;
5880 struct jpeg_source_mgr
*src
;
5882 if (cinfo
->src
== NULL
)
5884 /* First time for this JPEG object? */
5885 cinfo
->src
= (struct jpeg_source_mgr
*)
5886 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
5887 sizeof (struct jpeg_source_mgr
));
5888 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5889 src
->next_input_byte
= data
;
5892 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5893 src
->init_source
= our_init_source
;
5894 src
->fill_input_buffer
= our_fill_input_buffer
;
5895 src
->skip_input_data
= our_skip_input_data
;
5896 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
5897 src
->term_source
= our_term_source
;
5898 src
->bytes_in_buffer
= len
;
5899 src
->next_input_byte
= data
;
5903 /* Load image IMG for use on frame F. Patterned after example.c
5904 from the JPEG lib. */
5911 struct jpeg_decompress_struct cinfo
;
5912 struct my_jpeg_error_mgr mgr
;
5913 Lisp_Object file
, specified_file
;
5914 Lisp_Object specified_data
;
5915 FILE * volatile fp
= NULL
;
5917 int row_stride
, x
, y
;
5918 XImagePtr ximg
= NULL
;
5920 unsigned long *colors
;
5922 struct gcpro gcpro1
;
5924 /* Open the JPEG file. */
5925 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5926 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5930 if (NILP (specified_data
))
5932 file
= x_find_image_file (specified_file
);
5933 if (!STRINGP (file
))
5935 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5940 fp
= fopen (SDATA (file
), "rb");
5943 image_error ("Cannot open `%s'", file
, Qnil
);
5949 /* Customize libjpeg's error handling to call my_error_exit when an
5950 error is detected. This function will perform a longjmp. */
5951 cinfo
.err
= fn_jpeg_std_error (&mgr
.pub
);
5952 mgr
.pub
.error_exit
= my_error_exit
;
5954 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
5958 /* Called from my_error_exit. Display a JPEG error. */
5959 char buffer
[JMSG_LENGTH_MAX
];
5960 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
5961 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
5962 build_string (buffer
));
5965 /* Close the input file and destroy the JPEG object. */
5967 fclose ((FILE *) fp
);
5968 fn_jpeg_destroy_decompress (&cinfo
);
5970 /* If we already have an XImage, free that. */
5971 x_destroy_x_image (ximg
);
5973 /* Free pixmap and colors. */
5974 x_clear_image (f
, img
);
5980 /* Create the JPEG decompression object. Let it read from fp.
5981 Read the JPEG image header. */
5982 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
5984 if (NILP (specified_data
))
5985 fn_jpeg_stdio_src (&cinfo
, (FILE *) fp
);
5987 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
5988 SBYTES (specified_data
));
5990 fn_jpeg_read_header (&cinfo
, TRUE
);
5992 /* Customize decompression so that color quantization will be used.
5993 Start decompression. */
5994 cinfo
.quantize_colors
= TRUE
;
5995 fn_jpeg_start_decompress (&cinfo
);
5996 width
= img
->width
= cinfo
.output_width
;
5997 height
= img
->height
= cinfo
.output_height
;
5999 /* Create X image and pixmap. */
6000 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6001 longjmp (mgr
.setjmp_buffer
, 2);
6003 /* Allocate colors. When color quantization is used,
6004 cinfo.actual_number_of_colors has been set with the number of
6005 colors generated, and cinfo.colormap is a two-dimensional array
6006 of color indices in the range 0..cinfo.actual_number_of_colors.
6007 No more than 255 colors will be generated. */
6011 if (cinfo
.out_color_components
> 2)
6012 ir
= 0, ig
= 1, ib
= 2;
6013 else if (cinfo
.out_color_components
> 1)
6014 ir
= 0, ig
= 1, ib
= 0;
6016 ir
= 0, ig
= 0, ib
= 0;
6018 /* Use the color table mechanism because it handles colors that
6019 cannot be allocated nicely. Such colors will be replaced with
6020 a default color, and we don't have to care about which colors
6021 can be freed safely, and which can't. */
6022 init_color_table ();
6023 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6026 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6028 /* Multiply RGB values with 255 because X expects RGB values
6029 in the range 0..0xffff. */
6030 int r
= cinfo
.colormap
[ir
][i
] << 8;
6031 int g
= cinfo
.colormap
[ig
][i
] << 8;
6032 int b
= cinfo
.colormap
[ib
][i
] << 8;
6033 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6036 #ifdef COLOR_TABLE_SUPPORT
6037 /* Remember those colors actually allocated. */
6038 img
->colors
= colors_in_color_table (&img
->ncolors
);
6039 free_color_table ();
6040 #endif /* COLOR_TABLE_SUPPORT */
6044 row_stride
= width
* cinfo
.output_components
;
6045 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6047 for (y
= 0; y
< height
; ++y
)
6049 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6050 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6051 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6055 fn_jpeg_finish_decompress (&cinfo
);
6056 fn_jpeg_destroy_decompress (&cinfo
);
6058 fclose ((FILE *) fp
);
6060 /* Maybe fill in the background field while we have ximg handy. */
6061 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6062 IMAGE_BACKGROUND (img
, f
, ximg
);
6064 /* Put the image into the pixmap. */
6065 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6066 x_destroy_x_image (ximg
);
6071 #else /* HAVE_JPEG */
6080 return image_load_quartz2d (f
, img
, 0);
6082 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
6087 #endif /* !HAVE_JPEG */
6091 /***********************************************************************
6093 ***********************************************************************/
6095 #if defined (HAVE_TIFF) || defined (MAC_OS)
6097 static int tiff_image_p
P_ ((Lisp_Object object
));
6098 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6100 /* The symbol `tiff' identifying images of this type. */
6104 /* Indices of image specification fields in tiff_format, below. */
6106 enum tiff_keyword_index
6115 TIFF_HEURISTIC_MASK
,
6121 /* Vector of image_keyword structures describing the format
6122 of valid user-defined image specifications. */
6124 static struct image_keyword tiff_format
[TIFF_LAST
] =
6126 {":type", IMAGE_SYMBOL_VALUE
, 1},
6127 {":data", IMAGE_STRING_VALUE
, 0},
6128 {":file", IMAGE_STRING_VALUE
, 0},
6129 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6130 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6131 {":relief", IMAGE_INTEGER_VALUE
, 0},
6132 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6133 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6134 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6135 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6138 /* Structure describing the image type `tiff'. */
6140 static struct image_type tiff_type
=
6149 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6152 tiff_image_p (object
)
6155 struct image_keyword fmt
[TIFF_LAST
];
6156 bcopy (tiff_format
, fmt
, sizeof fmt
);
6158 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6161 /* Must specify either the :data or :file keyword. */
6162 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6165 #endif /* HAVE_TIFF || MAC_OS */
6173 /* TIFF library details. */
6174 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6175 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6176 DEF_IMGLIB_FN (TIFFOpen
);
6177 DEF_IMGLIB_FN (TIFFClientOpen
);
6178 DEF_IMGLIB_FN (TIFFGetField
);
6179 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6180 DEF_IMGLIB_FN (TIFFClose
);
6183 init_tiff_functions (void)
6187 if (!(library
= LoadLibrary ("libtiff.dll")))
6190 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6191 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6192 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6193 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6194 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6195 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6196 LOAD_IMGLIB_FN (library
, TIFFClose
);
6202 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6203 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6204 #define fn_TIFFOpen TIFFOpen
6205 #define fn_TIFFClientOpen TIFFClientOpen
6206 #define fn_TIFFGetField TIFFGetField
6207 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6208 #define fn_TIFFClose TIFFClose
6210 #endif /* HAVE_NTGUI */
6213 /* Reading from a memory buffer for TIFF images Based on the PNG
6214 memory source, but we have to provide a lot of extra functions.
6217 We really only need to implement read and seek, but I am not
6218 convinced that the TIFF library is smart enough not to destroy
6219 itself if we only hand it the function pointers we need to
6224 unsigned char *bytes
;
6231 tiff_read_from_memory (data
, buf
, size
)
6236 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6238 if (size
> src
->len
- src
->index
)
6240 bcopy (src
->bytes
+ src
->index
, buf
, size
);
6246 tiff_write_from_memory (data
, buf
, size
)
6255 tiff_seek_in_memory (data
, off
, whence
)
6260 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6265 case SEEK_SET
: /* Go from beginning of source. */
6269 case SEEK_END
: /* Go from end of source. */
6270 idx
= src
->len
+ off
;
6273 case SEEK_CUR
: /* Go from current position. */
6274 idx
= src
->index
+ off
;
6277 default: /* Invalid `whence'. */
6281 if (idx
> src
->len
|| idx
< 0)
6289 tiff_close_memory (data
)
6297 tiff_mmap_memory (data
, pbase
, psize
)
6302 /* It is already _IN_ memory. */
6307 tiff_unmap_memory (data
, base
, size
)
6312 /* We don't need to do this. */
6316 tiff_size_of_memory (data
)
6319 return ((tiff_memory_source
*) data
)->len
;
6324 tiff_error_handler (title
, format
, ap
)
6325 const char *title
, *format
;
6331 len
= sprintf (buf
, "TIFF error: %s ", title
);
6332 vsprintf (buf
+ len
, format
, ap
);
6333 add_to_log (buf
, Qnil
, Qnil
);
6338 tiff_warning_handler (title
, format
, ap
)
6339 const char *title
, *format
;
6345 len
= sprintf (buf
, "TIFF warning: %s ", title
);
6346 vsprintf (buf
+ len
, format
, ap
);
6347 add_to_log (buf
, Qnil
, Qnil
);
6351 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6359 Lisp_Object file
, specified_file
;
6360 Lisp_Object specified_data
;
6362 int width
, height
, x
, y
;
6366 struct gcpro gcpro1
;
6367 tiff_memory_source memsrc
;
6369 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6370 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6374 fn_TIFFSetErrorHandler (tiff_error_handler
);
6375 fn_TIFFSetWarningHandler (tiff_warning_handler
);
6377 if (NILP (specified_data
))
6379 /* Read from a file */
6380 file
= x_find_image_file (specified_file
);
6381 if (!STRINGP (file
))
6383 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6388 /* Try to open the image file. */
6389 tiff
= fn_TIFFOpen (SDATA (file
), "r");
6392 image_error ("Cannot open `%s'", file
, Qnil
);
6399 /* Memory source! */
6400 memsrc
.bytes
= SDATA (specified_data
);
6401 memsrc
.len
= SBYTES (specified_data
);
6404 tiff
= fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
6405 (TIFFReadWriteProc
) tiff_read_from_memory
,
6406 (TIFFReadWriteProc
) tiff_write_from_memory
,
6407 tiff_seek_in_memory
,
6409 tiff_size_of_memory
,
6415 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
6421 /* Get width and height of the image, and allocate a raster buffer
6422 of width x height 32-bit values. */
6423 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
6424 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
6425 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
6427 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
6428 fn_TIFFClose (tiff
);
6431 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
6437 /* Create the X image and pixmap. */
6438 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6445 /* Initialize the color table. */
6446 init_color_table ();
6448 /* Process the pixel raster. Origin is in the lower-left corner. */
6449 for (y
= 0; y
< height
; ++y
)
6451 uint32
*row
= buf
+ y
* width
;
6453 for (x
= 0; x
< width
; ++x
)
6455 uint32 abgr
= row
[x
];
6456 int r
= TIFFGetR (abgr
) << 8;
6457 int g
= TIFFGetG (abgr
) << 8;
6458 int b
= TIFFGetB (abgr
) << 8;
6459 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
6463 #ifdef COLOR_TABLE_SUPPORT
6464 /* Remember the colors allocated for the image. Free the color table. */
6465 img
->colors
= colors_in_color_table (&img
->ncolors
);
6466 free_color_table ();
6467 #endif /* COLOR_TABLE_SUPPORT */
6470 img
->height
= height
;
6472 /* Maybe fill in the background field while we have ximg handy. */
6473 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6474 IMAGE_BACKGROUND (img
, f
, ximg
);
6476 /* Put the image into the pixmap, then free the X image and its buffer. */
6477 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6478 x_destroy_x_image (ximg
);
6485 #else /* HAVE_TIFF */
6493 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
6497 #endif /* !HAVE_TIFF */
6501 /***********************************************************************
6503 ***********************************************************************/
6505 #if defined (HAVE_GIF) || defined (MAC_OS)
6507 static int gif_image_p
P_ ((Lisp_Object object
));
6508 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
6510 /* The symbol `gif' identifying images of this type. */
6514 /* Indices of image specification fields in gif_format, below. */
6516 enum gif_keyword_index
6532 /* Vector of image_keyword structures describing the format
6533 of valid user-defined image specifications. */
6535 static struct image_keyword gif_format
[GIF_LAST
] =
6537 {":type", IMAGE_SYMBOL_VALUE
, 1},
6538 {":data", IMAGE_STRING_VALUE
, 0},
6539 {":file", IMAGE_STRING_VALUE
, 0},
6540 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6541 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6542 {":relief", IMAGE_INTEGER_VALUE
, 0},
6543 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6544 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6545 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6546 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6547 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6550 /* Structure describing the image type `gif'. */
6552 static struct image_type gif_type
=
6561 /* Return non-zero if OBJECT is a valid GIF image specification. */
6564 gif_image_p (object
)
6567 struct image_keyword fmt
[GIF_LAST
];
6568 bcopy (gif_format
, fmt
, sizeof fmt
);
6570 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
6573 /* Must specify either the :data or :file keyword. */
6574 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
6577 #endif /* HAVE_GIF || MAC_OS */
6581 #if defined (HAVE_NTGUI) || defined (MAC_OS)
6582 /* avoid conflict with QuickdrawText.h */
6583 #define DrawText gif_DrawText
6584 #include <gif_lib.h>
6587 #else /* HAVE_NTGUI || MAC_OS */
6589 #include <gif_lib.h>
6591 #endif /* HAVE_NTGUI || MAC_OS */
6596 /* GIF library details. */
6597 DEF_IMGLIB_FN (DGifCloseFile
);
6598 DEF_IMGLIB_FN (DGifSlurp
);
6599 DEF_IMGLIB_FN (DGifOpen
);
6600 DEF_IMGLIB_FN (DGifOpenFileName
);
6603 init_gif_functions (void)
6607 if (!(library
= LoadLibrary ("libungif.dll")))
6610 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
6611 LOAD_IMGLIB_FN (library
, DGifSlurp
);
6612 LOAD_IMGLIB_FN (library
, DGifOpen
);
6613 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
6619 #define fn_DGifCloseFile DGifCloseFile
6620 #define fn_DGifSlurp DGifSlurp
6621 #define fn_DGifOpen DGifOpen
6622 #define fn_DGifOpenFileName DGifOpenFileName
6624 #endif /* HAVE_NTGUI */
6626 /* Reading a GIF image from memory
6627 Based on the PNG memory stuff to a certain extent. */
6631 unsigned char *bytes
;
6637 /* Make the current memory source available to gif_read_from_memory.
6638 It's done this way because not all versions of libungif support
6639 a UserData field in the GifFileType structure. */
6640 static gif_memory_source
*current_gif_memory_src
;
6643 gif_read_from_memory (file
, buf
, len
)
6648 gif_memory_source
*src
= current_gif_memory_src
;
6650 if (len
> src
->len
- src
->index
)
6653 bcopy (src
->bytes
+ src
->index
, buf
, len
);
6659 /* Load GIF image IMG for use on frame F. Value is non-zero if
6667 Lisp_Object file
, specified_file
;
6668 Lisp_Object specified_data
;
6669 int rc
, width
, height
, x
, y
, i
;
6671 ColorMapObject
*gif_color_map
;
6672 unsigned long pixel_colors
[256];
6674 struct gcpro gcpro1
;
6676 int ino
, image_left
, image_top
, image_width
, image_height
;
6677 gif_memory_source memsrc
;
6678 unsigned char *raster
;
6680 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6681 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6685 if (NILP (specified_data
))
6687 file
= x_find_image_file (specified_file
);
6688 if (!STRINGP (file
))
6690 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6695 /* Open the GIF file. */
6696 gif
= fn_DGifOpenFileName (SDATA (file
));
6699 image_error ("Cannot open `%s'", file
, Qnil
);
6706 /* Read from memory! */
6707 current_gif_memory_src
= &memsrc
;
6708 memsrc
.bytes
= SDATA (specified_data
);
6709 memsrc
.len
= SBYTES (specified_data
);
6712 gif
= fn_DGifOpen(&memsrc
, gif_read_from_memory
);
6715 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
6721 /* Read entire contents. */
6722 rc
= fn_DGifSlurp (gif
);
6723 if (rc
== GIF_ERROR
)
6725 image_error ("Error reading `%s'", img
->spec
, Qnil
);
6726 fn_DGifCloseFile (gif
);
6731 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
6732 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
6733 if (ino
>= gif
->ImageCount
)
6735 image_error ("Invalid image number `%s' in image `%s'",
6737 fn_DGifCloseFile (gif
);
6742 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
6743 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
6745 /* Create the X image and pixmap. */
6746 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6748 fn_DGifCloseFile (gif
);
6753 /* Allocate colors. */
6754 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
6756 gif_color_map
= gif
->SColorMap
;
6757 init_color_table ();
6758 bzero (pixel_colors
, sizeof pixel_colors
);
6760 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
6762 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
6763 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
6764 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
6765 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6768 #ifdef COLOR_TABLE_SUPPORT
6769 img
->colors
= colors_in_color_table (&img
->ncolors
);
6770 free_color_table ();
6771 #endif /* COLOR_TABLE_SUPPORT */
6773 /* Clear the part of the screen image that are not covered by
6774 the image from the GIF file. Full animated GIF support
6775 requires more than can be done here (see the gif89 spec,
6776 disposal methods). Let's simply assume that the part
6777 not covered by a sub-image is in the frame's background color. */
6778 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
6779 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
6780 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
6781 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
6783 for (y
= 0; y
< image_top
; ++y
)
6784 for (x
= 0; x
< width
; ++x
)
6785 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6787 for (y
= image_top
+ image_height
; y
< height
; ++y
)
6788 for (x
= 0; x
< width
; ++x
)
6789 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6791 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
6793 for (x
= 0; x
< image_left
; ++x
)
6794 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6795 for (x
= image_left
+ image_width
; x
< width
; ++x
)
6796 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6799 /* Read the GIF image into the X image. We use a local variable
6800 `raster' here because RasterBits below is a char *, and invites
6801 problems with bytes >= 0x80. */
6802 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
6804 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
6806 static int interlace_start
[] = {0, 4, 2, 1};
6807 static int interlace_increment
[] = {8, 8, 4, 2};
6809 int row
= interlace_start
[0];
6813 for (y
= 0; y
< image_height
; y
++)
6815 if (row
>= image_height
)
6817 row
= interlace_start
[++pass
];
6818 while (row
>= image_height
)
6819 row
= interlace_start
[++pass
];
6822 for (x
= 0; x
< image_width
; x
++)
6824 int i
= raster
[(y
* image_width
) + x
];
6825 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
6829 row
+= interlace_increment
[pass
];
6834 for (y
= 0; y
< image_height
; ++y
)
6835 for (x
= 0; x
< image_width
; ++x
)
6837 int i
= raster
[y
* image_width
+ x
];
6838 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
6842 fn_DGifCloseFile (gif
);
6844 /* Maybe fill in the background field while we have ximg handy. */
6845 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6846 IMAGE_BACKGROUND (img
, f
, ximg
);
6848 /* Put the image into the pixmap, then free the X image and its buffer. */
6849 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6850 x_destroy_x_image (ximg
);
6864 Lisp_Object specified_file
, file
;
6865 Lisp_Object specified_data
;
6867 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
6875 Lisp_Object specified_bg
;
6881 struct gcpro gcpro1
;
6884 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6885 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6887 if (NILP (specified_data
))
6889 /* Read from a file */
6893 err
= find_image_fsspec (specified_file
, &file
, &fss
);
6897 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6902 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
6903 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
6907 if (!graphic_p
&& !movie_p
)
6909 if (prefer_graphic_p
)
6910 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
6911 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
6914 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
6915 CloseMovieFile (refnum
);
6918 image_error ("Error reading `%s'", file
, Qnil
);
6924 /* Memory source! */
6926 long file_type_atom
[3];
6928 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
6931 image_error ("Cannot allocate data handle for `%s'",
6936 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
6937 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
6938 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
6939 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
6942 err
= PtrAndHand ("\p", dref
, 1);
6944 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
6947 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
6950 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
6951 &movie_p
, &prefer_graphic_p
, 0);
6955 if (!graphic_p
&& !movie_p
)
6957 if (prefer_graphic_p
)
6961 DisposeHandle (dref
);
6962 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
6966 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
6967 HandleDataHandlerSubType
);
6968 DisposeHandle (dref
);
6973 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
6974 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
6975 track
= GetMovieIndTrack (movie
, 1);
6976 media
= GetTrackMedia (track
);
6977 nsamples
= GetMediaSampleCount (media
);
6978 if (ino
>= nsamples
)
6980 image_error ("Invalid image number `%s' in image `%s'",
6985 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6986 if (!STRINGP (specified_bg
) ||
6987 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6989 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6990 color
.red
= RED16_FROM_ULONG (color
.pixel
);
6991 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
6992 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
6994 GetMovieBox (movie
, &rect
);
6995 width
= img
->width
= rect
.right
- rect
.left
;
6996 height
= img
->height
= rect
.bottom
- rect
.top
;
6997 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7000 SetGWorld (ximg
, NULL
);
7001 bg_color
.red
= color
.red
;
7002 bg_color
.green
= color
.green
;
7003 bg_color
.blue
= color
.blue
;
7004 RGBBackColor (&bg_color
);
7005 SetMovieActive (movie
, TRUE
);
7006 SetMovieGWorld (movie
, ximg
, NULL
);
7007 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7008 SetMovieTimeValue (movie
, time
);
7009 MoviesTask (movie
, 0L);
7010 DisposeTrackMedia (media
);
7011 DisposeMovieTrack (track
);
7012 DisposeMovie (movie
);
7015 /* Maybe fill in the background field while we have ximg handy. */
7016 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7017 IMAGE_BACKGROUND (img
, f
, ximg
);
7019 /* Put the image into the pixmap. */
7020 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7021 x_destroy_x_image (ximg
);
7025 image_error ("Cannot open `%s'", file
, Qnil
);
7028 DisposeTrackMedia (media
);
7030 DisposeMovieTrack (track
);
7032 DisposeMovie (movie
);
7039 #endif /* HAVE_GIF */
7043 /***********************************************************************
7045 ***********************************************************************/
7047 #ifdef HAVE_X_WINDOWS
7048 #define HAVE_GHOSTSCRIPT 1
7049 #endif /* HAVE_X_WINDOWS */
7051 /* The symbol `postscript' identifying images of this type. */
7053 Lisp_Object Qpostscript
;
7055 #ifdef HAVE_GHOSTSCRIPT
7057 static int gs_image_p
P_ ((Lisp_Object object
));
7058 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
7059 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7061 /* Keyword symbols. */
7063 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
7065 /* Indices of image specification fields in gs_format, below. */
7067 enum gs_keyword_index
7085 /* Vector of image_keyword structures describing the format
7086 of valid user-defined image specifications. */
7088 static struct image_keyword gs_format
[GS_LAST
] =
7090 {":type", IMAGE_SYMBOL_VALUE
, 1},
7091 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7092 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7093 {":file", IMAGE_STRING_VALUE
, 1},
7094 {":loader", IMAGE_FUNCTION_VALUE
, 0},
7095 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
7096 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7097 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7098 {":relief", IMAGE_INTEGER_VALUE
, 0},
7099 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7100 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7101 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7102 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7105 /* Structure describing the image type `ghostscript'. */
7107 static struct image_type gs_type
=
7117 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7120 gs_clear_image (f
, img
)
7124 /* IMG->data.ptr_val may contain a recorded colormap. */
7125 xfree (img
->data
.ptr_val
);
7126 x_clear_image (f
, img
);
7130 /* Return non-zero if OBJECT is a valid Ghostscript image
7137 struct image_keyword fmt
[GS_LAST
];
7141 bcopy (gs_format
, fmt
, sizeof fmt
);
7143 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
7146 /* Bounding box must be a list or vector containing 4 integers. */
7147 tem
= fmt
[GS_BOUNDING_BOX
].value
;
7150 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
7151 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
7156 else if (VECTORP (tem
))
7158 if (XVECTOR (tem
)->size
!= 4)
7160 for (i
= 0; i
< 4; ++i
)
7161 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
7171 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7180 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
7181 struct gcpro gcpro1
, gcpro2
;
7183 double in_width
, in_height
;
7184 Lisp_Object pixel_colors
= Qnil
;
7186 /* Compute pixel size of pixmap needed from the given size in the
7187 image specification. Sizes in the specification are in pt. 1 pt
7188 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7190 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
7191 in_width
= XFASTINT (pt_width
) / 72.0;
7192 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
7193 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
7194 in_height
= XFASTINT (pt_height
) / 72.0;
7195 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
7197 /* Create the pixmap. */
7198 xassert (img
->pixmap
== NO_PIXMAP
);
7200 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7202 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7203 img
->width
, img
->height
,
7204 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
7209 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
7213 /* Call the loader to fill the pixmap. It returns a process object
7214 if successful. We do not record_unwind_protect here because
7215 other places in redisplay like calling window scroll functions
7216 don't either. Let the Lisp loader use `unwind-protect' instead. */
7217 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
7219 sprintf (buffer
, "%lu %lu",
7220 (unsigned long) FRAME_X_WINDOW (f
),
7221 (unsigned long) img
->pixmap
);
7222 window_and_pixmap_id
= build_string (buffer
);
7224 sprintf (buffer
, "%lu %lu",
7225 FRAME_FOREGROUND_PIXEL (f
),
7226 FRAME_BACKGROUND_PIXEL (f
));
7227 pixel_colors
= build_string (buffer
);
7229 XSETFRAME (frame
, f
);
7230 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
7232 loader
= intern ("gs-load-image");
7234 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
7235 make_number (img
->width
),
7236 make_number (img
->height
),
7237 window_and_pixmap_id
,
7240 return PROCESSP (img
->data
.lisp_val
);
7244 /* Kill the Ghostscript process that was started to fill PIXMAP on
7245 frame F. Called from XTread_socket when receiving an event
7246 telling Emacs that Ghostscript has finished drawing. */
7249 x_kill_gs_process (pixmap
, f
)
7253 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7257 /* Find the image containing PIXMAP. */
7258 for (i
= 0; i
< c
->used
; ++i
)
7259 if (c
->images
[i
]->pixmap
== pixmap
)
7262 /* Should someone in between have cleared the image cache, for
7263 instance, give up. */
7267 /* Kill the GS process. We should have found PIXMAP in the image
7268 cache and its image should contain a process object. */
7270 xassert (PROCESSP (img
->data
.lisp_val
));
7271 Fkill_process (img
->data
.lisp_val
, Qnil
);
7272 img
->data
.lisp_val
= Qnil
;
7274 #if defined (HAVE_X_WINDOWS)
7276 /* On displays with a mutable colormap, figure out the colors
7277 allocated for the image by looking at the pixels of an XImage for
7279 class = FRAME_X_VISUAL (f
)->class;
7280 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
7286 /* Try to get an XImage for img->pixmep. */
7287 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7288 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7293 /* Initialize the color table. */
7294 init_color_table ();
7296 /* For each pixel of the image, look its color up in the
7297 color table. After having done so, the color table will
7298 contain an entry for each color used by the image. */
7299 for (y
= 0; y
< img
->height
; ++y
)
7300 for (x
= 0; x
< img
->width
; ++x
)
7302 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
7303 lookup_pixel_color (f
, pixel
);
7306 /* Record colors in the image. Free color table and XImage. */
7307 #ifdef COLOR_TABLE_SUPPORT
7308 img
->colors
= colors_in_color_table (&img
->ncolors
);
7309 free_color_table ();
7311 XDestroyImage (ximg
);
7313 #if 0 /* This doesn't seem to be the case. If we free the colors
7314 here, we get a BadAccess later in x_clear_image when
7315 freeing the colors. */
7316 /* We have allocated colors once, but Ghostscript has also
7317 allocated colors on behalf of us. So, to get the
7318 reference counts right, free them once. */
7320 x_free_colors (f
, img
->colors
, img
->ncolors
);
7324 image_error ("Cannot get X image of `%s'; colors will not be freed",
7329 #endif /* HAVE_X_WINDOWS */
7331 /* Now that we have the pixmap, compute mask and transform the
7332 image if requested. */
7334 postprocess_image (f
, img
);
7338 #endif /* HAVE_GHOSTSCRIPT */
7341 /***********************************************************************
7343 ***********************************************************************/
7347 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
7348 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
7352 return valid_image_p (spec
) ? Qt
: Qnil
;
7356 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
7362 if (valid_image_p (spec
))
7363 id
= lookup_image (SELECTED_FRAME (), spec
);
7366 return make_number (id
);
7369 #endif /* GLYPH_DEBUG != 0 */
7372 /***********************************************************************
7374 ***********************************************************************/
7379 QCascent
= intern (":ascent");
7380 staticpro (&QCascent
);
7381 QCmargin
= intern (":margin");
7382 staticpro (&QCmargin
);
7383 QCrelief
= intern (":relief");
7384 staticpro (&QCrelief
);
7385 QCconversion
= intern (":conversion");
7386 staticpro (&QCconversion
);
7387 QCcolor_symbols
= intern (":color-symbols");
7388 staticpro (&QCcolor_symbols
);
7389 QCheuristic_mask
= intern (":heuristic-mask");
7390 staticpro (&QCheuristic_mask
);
7391 QCindex
= intern (":index");
7392 staticpro (&QCindex
);
7393 QCmatrix
= intern (":matrix");
7394 staticpro (&QCmatrix
);
7395 QCcolor_adjustment
= intern (":color-adjustment");
7396 staticpro (&QCcolor_adjustment
);
7397 QCmask
= intern (":mask");
7398 staticpro (&QCmask
);
7400 Qlaplace
= intern ("laplace");
7401 staticpro (&Qlaplace
);
7402 Qemboss
= intern ("emboss");
7403 staticpro (&Qemboss
);
7404 Qedge_detection
= intern ("edge-detection");
7405 staticpro (&Qedge_detection
);
7406 Qheuristic
= intern ("heuristic");
7407 staticpro (&Qheuristic
);
7409 Qpostscript
= intern ("postscript");
7410 staticpro (&Qpostscript
);
7411 #ifdef HAVE_GHOSTSCRIPT
7412 QCloader
= intern (":loader");
7413 staticpro (&QCloader
);
7414 QCbounding_box
= intern (":bounding-box");
7415 staticpro (&QCbounding_box
);
7416 QCpt_width
= intern (":pt-width");
7417 staticpro (&QCpt_width
);
7418 QCpt_height
= intern (":pt-height");
7419 staticpro (&QCpt_height
);
7420 #endif /* HAVE_GHOSTSCRIPT */
7422 Qpbm
= intern ("pbm");
7425 Qxbm
= intern ("xbm");
7429 Qxpm
= intern ("xpm");
7433 #if defined (HAVE_JPEG) || defined (MAC_OS)
7434 Qjpeg
= intern ("jpeg");
7438 #if defined (HAVE_TIFF) || defined (MAC_OS)
7439 Qtiff
= intern ("tiff");
7443 #if defined (HAVE_GIF) || defined (MAC_OS)
7444 Qgif
= intern ("gif");
7448 #if defined (HAVE_PNG) || defined (MAC_OS)
7449 Qpng
= intern ("png");
7453 defsubr (&Sclear_image_cache
);
7454 defsubr (&Simage_size
);
7455 defsubr (&Simage_mask_p
);
7459 defsubr (&Slookup_image
);
7462 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
7463 doc
: /* Non-nil means always draw a cross over disabled images.
7464 Disabled images are those having an `:conversion disabled' property.
7465 A cross is always drawn on black & white displays. */);
7466 cross_disabled_images
= 0;
7468 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
7469 doc
: /* List of directories to search for window system bitmap files. */);
7470 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
7472 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
7473 doc
: /* Time after which cached images are removed from the cache.
7474 When an image has not been displayed this many seconds, remove it
7475 from the image cache. Value must be an integer or nil with nil
7476 meaning don't clear the cache. */);
7477 Vimage_cache_eviction_delay
= make_number (30 * 60);
7482 /* Image types that rely on external libraries are loaded dynamically
7483 if the library is available. */
7484 #define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn())
7486 #define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */
7487 #endif /* HAVE_NTGUI */
7493 Vimage_types
= Qnil
;
7495 define_image_type (&xbm_type
);
7496 define_image_type (&pbm_type
);
7499 IF_LIB_AVAILABLE(init_xpm_functions
)
7500 define_image_type (&xpm_type
);
7503 #if defined (HAVE_JPEG) || defined (MAC_OS)
7504 IF_LIB_AVAILABLE(init_jpeg_functions
)
7505 define_image_type (&jpeg_type
);
7508 #if defined (HAVE_TIFF) || defined (MAC_OS)
7509 IF_LIB_AVAILABLE(init_tiff_functions
)
7510 define_image_type (&tiff_type
);
7513 #if defined (HAVE_GIF) || defined (MAC_OS)
7514 IF_LIB_AVAILABLE(init_gif_functions
)
7515 define_image_type (&gif_type
);
7518 #if defined (HAVE_PNG) || defined (MAC_OS)
7519 IF_LIB_AVAILABLE(init_png_functions
)
7520 define_image_type (&png_type
);
7523 #ifdef HAVE_GHOSTSCRIPT
7524 define_image_type (&gs_type
);
7528 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7531 init_image_func_pointer ();
7536 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
7537 (do not change this comment) */