1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
30 /* This makes the fields of a Display accessible, in Xlib header files. */
32 #define XLIB_ILLEGAL_ACCESS
37 #include "dispextern.h"
38 #include "blockinput.h"
41 #include "character.h"
43 #include "termhooks.h"
48 #include <sys/types.h>
51 #define COLOR_TABLE_SUPPORT 1
53 typedef struct x_bitmap_record Bitmap_Record
;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
57 #define RGB_PIXEL_COLOR unsigned long
59 #define PIX_MASK_RETAIN 0
60 #define PIX_MASK_DRAW 1
61 #endif /* HAVE_X_WINDOWS */
67 /* W32_TODO : Color tables on W32. */
68 #undef COLOR_TABLE_SUPPORT
70 typedef struct w32_bitmap_record Bitmap_Record
;
71 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
83 /* Functions from w32term.c that depend on XColor (so can't go in w32term.h
84 without modifying lots of files). */
85 extern void x_query_colors (struct frame
*f
, XColor
*colors
, int ncolors
);
86 extern void x_query_color (struct frame
*f
, XColor
*color
);
87 #endif /* HAVE_NTGUI */
91 #include <sys/types.h>
94 #undef COLOR_TABLE_SUPPORT
96 typedef struct ns_bitmap_record Bitmap_Record
;
98 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
101 #define RGB_PIXEL_COLOR unsigned long
104 #define PIX_MASK_RETAIN 0
105 #define PIX_MASK_DRAW 1
107 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
108 #define x_defined_color(f, name, color_def, alloc) \
109 ns_defined_color (f, name, color_def, alloc, 0)
110 #define FRAME_X_SCREEN(f) 0
111 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
115 /* Search path for bitmap files. */
117 Lisp_Object Vx_bitmap_file_path
;
120 static void x_disable_image
P_ ((struct frame
*, struct image
*));
121 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
124 static void init_color_table
P_ ((void));
125 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
126 #ifdef COLOR_TABLE_SUPPORT
127 static void free_color_table
P_ ((void));
128 static unsigned long *colors_in_color_table
P_ ((int *n
));
129 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
132 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
133 id, which is just an int that this section returns. Bitmaps are
134 reference counted so they can be shared among frames.
136 Bitmap indices are guaranteed to be > 0, so a negative number can
137 be used to indicate no bitmap.
139 If you use x_create_bitmap_from_data, then you must keep track of
140 the bitmaps yourself. That is, creating a bitmap from the same
141 data more than once will not be caught. */
146 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
147 Display
*display
; /* not used */
149 int x
, y
; /* not used */
150 unsigned int width
, height
; /* not used */
151 unsigned long plane_mask
; /* not used */
152 int format
; /* not used */
154 #if !USE_MAC_IMAGE_IO
156 xassert (x
== 0 && y
== 0);
159 SetRect (&ri
, 0, 0, width
, height
);
160 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
162 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
165 LockPixels (GetGWorldPixMap (pixmap
));
172 XPutPixel (ximage
, x
, y
, pixel
)
178 if (ximage
->bits_per_pixel
== 32)
179 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
181 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
183 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
184 short depth
= GetPixDepth (pixmap
);
186 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
189 char *base_addr
= GetPixBaseAddr (pixmap
);
190 short row_bytes
= GetPixRowBytes (pixmap
);
192 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
198 char *base_addr
= GetPixBaseAddr (pixmap
);
199 short row_bytes
= GetPixRowBytes (pixmap
);
201 if (pixel
== PIX_MASK_DRAW
)
202 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
204 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
212 GetGWorld (&old_port
, &old_gdh
);
213 SetGWorld (ximage
, NULL
);
215 color
.red
= RED16_FROM_ULONG (pixel
);
216 color
.green
= GREEN16_FROM_ULONG (pixel
);
217 color
.blue
= BLUE16_FROM_ULONG (pixel
);
219 SetCPixel (x
, y
, &color
);
221 SetGWorld (old_port
, old_gdh
);
227 XGetPixel (ximage
, x
, y
)
232 if (ximage
->bits_per_pixel
== 32)
233 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
235 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
237 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
238 short depth
= GetPixDepth (pixmap
);
240 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
243 char *base_addr
= GetPixBaseAddr (pixmap
);
244 short row_bytes
= GetPixRowBytes (pixmap
);
246 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
252 char *base_addr
= GetPixBaseAddr (pixmap
);
253 short row_bytes
= GetPixRowBytes (pixmap
);
255 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
256 return PIX_MASK_DRAW
;
258 return PIX_MASK_RETAIN
;
266 GetGWorld (&old_port
, &old_gdh
);
267 SetGWorld (ximage
, NULL
);
269 GetCPixel (x
, y
, &color
);
271 SetGWorld (old_port
, old_gdh
);
272 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
281 #if !USE_MAC_IMAGE_IO
282 UnlockPixels (GetGWorldPixMap (ximg
));
289 mac_data_provider_release_data (info
, data
, size
)
294 xfree ((void *)data
);
299 mac_create_cg_image_from_image (f
, img
)
304 XImagePtr ximg
= img
->pixmap
;
305 CGDataProviderRef provider
;
311 unsigned long color
, alpha
;
313 for (y
= 0; y
< ximg
->height
; y
++)
314 for (x
= 0; x
< ximg
->width
; x
++)
316 color
= XGetPixel (ximg
, x
, y
);
317 alpha
= XGetPixel (img
->mask
, x
, y
);
318 XPutPixel (ximg
, x
, y
,
319 ARGB_TO_ULONG (alpha
,
320 RED_FROM_ULONG (color
)
321 * alpha
/ PIX_MASK_DRAW
,
322 GREEN_FROM_ULONG (color
)
323 * alpha
/ PIX_MASK_DRAW
,
324 BLUE_FROM_ULONG (color
)
325 * alpha
/ PIX_MASK_DRAW
));
327 xfree (img
->mask
->data
);
328 img
->mask
->data
= NULL
;
331 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
332 ximg
->bytes_per_line
* ximg
->height
,
333 mac_data_provider_release_data
);
335 result
= CGImageCreate (ximg
->width
, ximg
->height
, 8, 32,
336 ximg
->bytes_per_line
, mac_cg_color_space_rgb
,
337 ((img
->mask
? kCGImageAlphaPremultipliedFirst
338 : kCGImageAlphaNoneSkipFirst
)
339 | kCGBitmapByteOrder32Host
),
340 provider
, NULL
, 0, kCGRenderingIntentDefault
);
341 CGDataProviderRelease (provider
);
347 CGImageRef result
= NULL
;
354 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
355 img
->width
, img
->height
, 1);
362 GetGWorld (&old_port
, &old_gdh
);
363 SetGWorld (mask
, NULL
);
364 BackColor (blackColor
); /* Don't mask. */
365 SetRect (&r
, 0, 0, img
->width
, img
->height
);
367 SetGWorld (old_port
, old_gdh
);
372 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
373 GetGWorldPixMap (mask
), &result
);
374 if (mask
!= img
->mask
)
375 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
382 #endif /* USE_CG_DRAWING */
387 XGetImage (Display
*display
, Pixmap pixmap
, int x
, int y
,
388 unsigned int width
, unsigned int height
,
389 unsigned long plane_mask
, int format
)
391 /* TODO: not sure what this function is supposed to do.. */
392 ns_retain_object(pixmap
);
396 /* use with imgs created by ns_image_for_XPM */
398 XGetPixel (XImagePtr ximage
, int x
, int y
)
400 return ns_get_pixel(ximage
, x
, y
);
403 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
404 pixel is assumed to be in form RGB */
406 XPutPixel (XImagePtr ximage
, int x
, int y
, unsigned long pixel
)
408 ns_put_pixel(ximage
, x
, y
, pixel
);
413 /* Functions to access the contents of a bitmap, given an id. */
416 x_bitmap_height (f
, id
)
420 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
424 x_bitmap_width (f
, id
)
428 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
431 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
433 x_bitmap_pixmap (f
, id
)
437 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
441 #ifdef HAVE_X_WINDOWS
443 x_bitmap_mask (f
, id
)
447 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
451 /* Allocate a new bitmap record. Returns index of new record. */
454 x_allocate_bitmap_record (f
)
457 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
460 if (dpyinfo
->bitmaps
== NULL
)
462 dpyinfo
->bitmaps_size
= 10;
464 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
465 dpyinfo
->bitmaps_last
= 1;
469 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
470 return ++dpyinfo
->bitmaps_last
;
472 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
473 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
476 dpyinfo
->bitmaps_size
*= 2;
478 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
479 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
480 return ++dpyinfo
->bitmaps_last
;
483 /* Add one reference to the reference count of the bitmap with id ID. */
486 x_reference_bitmap (f
, id
)
490 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
493 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
496 x_create_bitmap_from_data (f
, bits
, width
, height
)
499 unsigned int width
, height
;
501 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
504 #ifdef HAVE_X_WINDOWS
506 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
507 bits
, width
, height
);
510 #endif /* HAVE_X_WINDOWS */
514 bitmap
= CreateBitmap (width
, height
,
515 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
516 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
520 #endif /* HAVE_NTGUI */
523 void *bitmap
= ns_image_from_XBM(bits
, width
, height
);
528 id
= x_allocate_bitmap_record (f
);
531 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
532 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
535 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
536 dpyinfo
->bitmaps
[id
- 1].height
= height
;
537 dpyinfo
->bitmaps
[id
- 1].width
= width
;
538 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
540 #ifdef HAVE_X_WINDOWS
541 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
542 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
543 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
544 #endif /* HAVE_X_WINDOWS */
547 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
548 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
549 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
550 #endif /* HAVE_NTGUI */
555 /* Create bitmap from file FILE for frame F. */
558 x_create_bitmap_from_file (f
, file
)
562 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
565 return -1; /* W32_TODO : bitmap support */
566 #endif /* HAVE_NTGUI */
570 void *bitmap
= ns_image_from_file(file
);
576 id
= x_allocate_bitmap_record (f
);
577 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
578 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
579 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
580 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
581 dpyinfo
->bitmaps
[id
- 1].height
= ns_image_width(bitmap
);
582 dpyinfo
->bitmaps
[id
- 1].width
= ns_image_height(bitmap
);
583 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
587 #ifdef HAVE_X_WINDOWS
588 unsigned int width
, height
;
590 int xhot
, yhot
, result
, id
;
595 /* Look for an existing bitmap with the same name. */
596 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
598 if (dpyinfo
->bitmaps
[id
].refcount
599 && dpyinfo
->bitmaps
[id
].file
600 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
602 ++dpyinfo
->bitmaps
[id
].refcount
;
607 /* Search bitmap-file-path for the file, if appropriate. */
608 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
613 filename
= (char *) SDATA (found
);
615 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
616 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
617 if (result
!= BitmapSuccess
)
620 id
= x_allocate_bitmap_record (f
);
621 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
622 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
623 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
624 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
625 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
626 dpyinfo
->bitmaps
[id
- 1].height
= height
;
627 dpyinfo
->bitmaps
[id
- 1].width
= width
;
628 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
631 #endif /* HAVE_X_WINDOWS */
637 free_bitmap_record (dpyinfo
, bm
)
638 Display_Info
*dpyinfo
;
641 #ifdef HAVE_X_WINDOWS
642 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
644 XFreePixmap (dpyinfo
->display
, bm
->mask
);
645 #endif /* HAVE_X_WINDOWS */
648 DeleteObject (bm
->pixmap
);
649 #endif /* HAVE_NTGUI */
652 ns_release_object(bm
->img
);
662 /* Remove reference to bitmap with id number ID. */
665 x_destroy_bitmap (f
, id
)
669 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
673 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
675 if (--bm
->refcount
== 0)
678 free_bitmap_record (dpyinfo
, bm
);
684 /* Free all the bitmaps for the display specified by DPYINFO. */
687 x_destroy_all_bitmaps (dpyinfo
)
688 Display_Info
*dpyinfo
;
691 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
693 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
694 if (bm
->refcount
> 0)
695 free_bitmap_record (dpyinfo
, bm
);
697 dpyinfo
->bitmaps_last
= 0;
701 #ifdef HAVE_X_WINDOWS
703 /* Useful functions defined in the section
704 `Image type independent image structures' below. */
706 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
709 unsigned long height
));
711 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
712 int depth
, XImagePtr
*ximg
,
715 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
718 /* Create a mask of a bitmap. Note is this not a perfect mask.
719 It's nicer with some borders in this context */
722 x_create_bitmap_mask (f
, id
)
727 XImagePtr ximg
, mask_img
;
728 unsigned long width
, height
;
731 unsigned long x
, y
, xp
, xm
, yp
, ym
;
734 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
739 pixmap
= x_bitmap_pixmap (f
, id
);
740 width
= x_bitmap_width (f
, id
);
741 height
= x_bitmap_height (f
, id
);
744 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
753 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
758 XDestroyImage (ximg
);
762 bg
= four_corners_best (ximg
, NULL
, width
, height
);
764 for (y
= 0; y
< ximg
->height
; ++y
)
766 for (x
= 0; x
< ximg
->width
; ++x
)
768 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
769 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
770 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
771 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
772 if (XGetPixel (ximg
, x
, y
) == bg
773 && XGetPixel (ximg
, x
, yp
) == bg
774 && XGetPixel (ximg
, x
, ym
) == bg
775 && XGetPixel (ximg
, xp
, y
) == bg
776 && XGetPixel (ximg
, xp
, yp
) == bg
777 && XGetPixel (ximg
, xp
, ym
) == bg
778 && XGetPixel (ximg
, xm
, y
) == bg
779 && XGetPixel (ximg
, xm
, yp
) == bg
780 && XGetPixel (ximg
, xm
, ym
) == bg
)
781 XPutPixel (mask_img
, x
, y
, 0);
783 XPutPixel (mask_img
, x
, y
, 1);
787 xassert (interrupt_input_blocked
);
788 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
789 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
791 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
793 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
794 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
796 XDestroyImage (ximg
);
797 x_destroy_x_image (mask_img
);
802 #endif /* HAVE_X_WINDOWS */
805 /***********************************************************************
807 ***********************************************************************/
809 /* Value is the number of elements of vector VECTOR. */
811 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
813 /* List of supported image types. Use define_image_type to add new
814 types. Use lookup_image_type to find a type for a given symbol. */
816 static struct image_type
*image_types
;
818 /* A list of symbols, one for each supported image type. */
820 Lisp_Object Vimage_types
;
822 /* An alist of image types and libraries that implement the type. */
824 Lisp_Object Vimage_library_alist
;
826 /* Cache for delayed-loading image types. */
828 static Lisp_Object Vimage_type_cache
;
830 /* The symbol `xbm' which is used as the type symbol for XBM images. */
836 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
837 extern Lisp_Object QCdata
, QCtype
;
838 extern Lisp_Object Qcenter
;
839 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
840 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
841 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
845 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
847 /* Time in seconds after which images should be removed from the cache
850 Lisp_Object Vimage_cache_eviction_delay
;
852 /* Function prototypes. */
854 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
855 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
856 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
857 static void x_laplace
P_ ((struct frame
*, struct image
*));
858 static void x_emboss
P_ ((struct frame
*, struct image
*));
859 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
862 #define CACHE_IMAGE_TYPE(type, status) \
863 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
865 #define ADD_IMAGE_TYPE(type) \
866 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
868 /* Define a new image type from TYPE. This adds a copy of TYPE to
869 image_types and caches the loading status of TYPE. */
872 define_image_type (type
, loaded
)
873 struct image_type
*type
;
882 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
883 The initialized data segment is read-only. */
884 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
885 bcopy (type
, p
, sizeof *p
);
886 p
->next
= image_types
;
891 CACHE_IMAGE_TYPE (*type
->type
, success
);
896 /* Look up image type SYMBOL, and return a pointer to its image_type
897 structure. Value is null if SYMBOL is not a known image type. */
899 static INLINE
struct image_type
*
900 lookup_image_type (symbol
)
903 struct image_type
*type
;
905 /* We must initialize the image-type if it hasn't been already. */
906 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
907 return 0; /* unimplemented */
909 for (type
= image_types
; type
; type
= type
->next
)
910 if (EQ (symbol
, *type
->type
))
917 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
918 valid image specification is a list whose car is the symbol
919 `image', and whose rest is a property list. The property list must
920 contain a value for key `:type'. That value must be the name of a
921 supported image type. The rest of the property list depends on the
925 valid_image_p (object
)
934 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
935 if (EQ (XCAR (tem
), QCtype
))
938 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
940 struct image_type
*type
;
941 type
= lookup_image_type (XCAR (tem
));
943 valid_p
= type
->valid_p (object
);
954 /* Log error message with format string FORMAT and argument ARG.
955 Signaling an error, e.g. when an image cannot be loaded, is not a
956 good idea because this would interrupt redisplay, and the error
957 message display would lead to another redisplay. This function
958 therefore simply displays a message. */
961 image_error (format
, arg1
, arg2
)
963 Lisp_Object arg1
, arg2
;
965 add_to_log (format
, arg1
, arg2
);
970 /***********************************************************************
972 ***********************************************************************/
974 enum image_value_type
976 IMAGE_DONT_CHECK_VALUE_TYPE
,
978 IMAGE_STRING_OR_NIL_VALUE
,
980 IMAGE_POSITIVE_INTEGER_VALUE
,
981 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
982 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
985 IMAGE_FUNCTION_VALUE
,
990 /* Structure used when parsing image specifications. */
994 /* Name of keyword. */
997 /* The type of value allowed. */
998 enum image_value_type type
;
1000 /* Non-zero means key must be present. */
1003 /* Used to recognize duplicate keywords in a property list. */
1006 /* The value that was found. */
1011 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
1013 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
1016 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
1017 has the format (image KEYWORD VALUE ...). One of the keyword/
1018 value pairs must be `:type TYPE'. KEYWORDS is a vector of
1019 image_keywords structures of size NKEYWORDS describing other
1020 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1023 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1025 struct image_keyword
*keywords
;
1035 plist
= XCDR (spec
);
1036 while (CONSP (plist
))
1038 Lisp_Object key
, value
;
1040 /* First element of a pair must be a symbol. */
1042 plist
= XCDR (plist
);
1046 /* There must follow a value. */
1049 value
= XCAR (plist
);
1050 plist
= XCDR (plist
);
1052 /* Find key in KEYWORDS. Error if not found. */
1053 for (i
= 0; i
< nkeywords
; ++i
)
1054 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1060 /* Record that we recognized the keyword. If a keywords
1061 was found more than once, it's an error. */
1062 keywords
[i
].value
= value
;
1063 ++keywords
[i
].count
;
1065 if (keywords
[i
].count
> 1)
1068 /* Check type of value against allowed type. */
1069 switch (keywords
[i
].type
)
1071 case IMAGE_STRING_VALUE
:
1072 if (!STRINGP (value
))
1076 case IMAGE_STRING_OR_NIL_VALUE
:
1077 if (!STRINGP (value
) && !NILP (value
))
1081 case IMAGE_SYMBOL_VALUE
:
1082 if (!SYMBOLP (value
))
1086 case IMAGE_POSITIVE_INTEGER_VALUE
:
1087 if (!INTEGERP (value
) || XINT (value
) <= 0)
1091 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1092 if (INTEGERP (value
) && XINT (value
) >= 0)
1095 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1096 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1100 case IMAGE_ASCENT_VALUE
:
1101 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1103 else if (INTEGERP (value
)
1104 && XINT (value
) >= 0
1105 && XINT (value
) <= 100)
1109 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1110 if (!INTEGERP (value
) || XINT (value
) < 0)
1114 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1117 case IMAGE_FUNCTION_VALUE
:
1118 value
= indirect_function (value
);
1120 || COMPILEDP (value
)
1121 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1125 case IMAGE_NUMBER_VALUE
:
1126 if (!INTEGERP (value
) && !FLOATP (value
))
1130 case IMAGE_INTEGER_VALUE
:
1131 if (!INTEGERP (value
))
1135 case IMAGE_BOOL_VALUE
:
1136 if (!NILP (value
) && !EQ (value
, Qt
))
1145 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1149 /* Check that all mandatory fields are present. */
1150 for (i
= 0; i
< nkeywords
; ++i
)
1151 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1154 return NILP (plist
);
1158 /* Return the value of KEY in image specification SPEC. Value is nil
1159 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1160 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1163 image_spec_value (spec
, key
, found
)
1164 Lisp_Object spec
, key
;
1169 xassert (valid_image_p (spec
));
1171 for (tail
= XCDR (spec
);
1172 CONSP (tail
) && CONSP (XCDR (tail
));
1173 tail
= XCDR (XCDR (tail
)))
1175 if (EQ (XCAR (tail
), key
))
1179 return XCAR (XCDR (tail
));
1189 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1190 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1191 PIXELS non-nil means return the size in pixels, otherwise return the
1192 size in canonical character units.
1193 FRAME is the frame on which the image will be displayed. FRAME nil
1194 or omitted means use the selected frame. */)
1195 (spec
, pixels
, frame
)
1196 Lisp_Object spec
, pixels
, frame
;
1201 if (valid_image_p (spec
))
1203 struct frame
*f
= check_x_frame (frame
);
1204 int id
= lookup_image (f
, spec
);
1205 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1206 int width
= img
->width
+ 2 * img
->hmargin
;
1207 int height
= img
->height
+ 2 * img
->vmargin
;
1210 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1211 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1213 size
= Fcons (make_number (width
), make_number (height
));
1216 error ("Invalid image specification");
1222 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1223 doc
: /* Return t if image SPEC has a mask bitmap.
1224 FRAME is the frame on which the image will be displayed. FRAME nil
1225 or omitted means use the selected frame. */)
1227 Lisp_Object spec
, frame
;
1232 if (valid_image_p (spec
))
1234 struct frame
*f
= check_x_frame (frame
);
1235 int id
= lookup_image (f
, spec
);
1236 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1241 error ("Invalid image specification");
1246 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1247 doc
: /* Return extension data for image SPEC.
1248 FRAME is the frame on which the image will be displayed. FRAME nil
1249 or omitted means use the selected frame. */)
1251 Lisp_Object spec
, frame
;
1256 if (valid_image_p (spec
))
1258 struct frame
*f
= check_x_frame (frame
);
1259 int id
= lookup_image (f
, spec
);
1260 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1261 ext
= img
->data
.lisp_val
;
1268 /***********************************************************************
1269 Image type independent image structures
1270 ***********************************************************************/
1272 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1273 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1274 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1276 #define MAX_IMAGE_SIZE 6.0
1277 Lisp_Object Vmax_image_size
;
1279 /* Allocate and return a new image structure for image specification
1280 SPEC. SPEC has a hash value of HASH. */
1282 static struct image
*
1283 make_image (spec
, hash
)
1287 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1288 Lisp_Object file
= image_spec_value (spec
, QCfile
, NULL
);
1290 xassert (valid_image_p (spec
));
1291 bzero (img
, sizeof *img
);
1292 img
->dependencies
= NILP (file
) ? Qnil
: list1 (file
);
1293 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1294 xassert (img
->type
!= NULL
);
1296 img
->data
.lisp_val
= Qnil
;
1297 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1299 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1304 /* Free image IMG which was used on frame F, including its resources. */
1313 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1315 /* Remove IMG from the hash table of its cache. */
1317 img
->prev
->next
= img
->next
;
1319 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1322 img
->next
->prev
= img
->prev
;
1324 c
->images
[img
->id
] = NULL
;
1326 /* Free resources, then free IMG. */
1327 img
->type
->free (f
, img
);
1332 /* Return 1 if the given widths and heights are valid for display;
1333 otherwise, return 0. */
1336 check_image_size (f
, width
, height
)
1343 if (width
<= 0 || height
<= 0)
1346 if (INTEGERP (Vmax_image_size
))
1347 w
= h
= XINT (Vmax_image_size
);
1348 else if (FLOATP (Vmax_image_size
))
1352 w
= FRAME_PIXEL_WIDTH (f
);
1353 h
= FRAME_PIXEL_HEIGHT (f
);
1356 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1357 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1358 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1363 return (width
<= w
&& height
<= h
);
1366 /* Prepare image IMG for display on frame F. Must be called before
1367 drawing an image. */
1370 prepare_image_for_display (f
, img
)
1376 /* We're about to display IMG, so set its timestamp to `now'. */
1378 img
->timestamp
= EMACS_SECS (t
);
1380 /* If IMG doesn't have a pixmap yet, load it now, using the image
1381 type dependent loader function. */
1382 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1383 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1388 /* Value is the number of pixels for the ascent of image IMG when
1389 drawn in face FACE. */
1392 image_ascent (img
, face
, slice
)
1395 struct glyph_slice
*slice
;
1400 if (slice
->height
== img
->height
)
1401 height
= img
->height
+ img
->vmargin
;
1402 else if (slice
->y
== 0)
1403 height
= slice
->height
+ img
->vmargin
;
1405 height
= slice
->height
;
1407 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1412 /* W32 specific version. Why?. ++kfs */
1413 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1414 - FONT_BASE (face
->font
)) / 2;
1416 /* This expression is arranged so that if the image can't be
1417 exactly centered, it will be moved slightly up. This is
1418 because a typical font is `top-heavy' (due to the presence
1419 uppercase letters), so the image placement should err towards
1420 being top-heavy too. It also just generally looks better. */
1421 ascent
= (height
+ FONT_BASE(face
->font
)
1422 - FONT_DESCENT(face
->font
) + 1) / 2;
1423 #endif /* HAVE_NTGUI */
1426 ascent
= height
/ 2;
1429 ascent
= (int) (height
* img
->ascent
/ 100.0);
1435 /* Image background colors. */
1437 /* Find the "best" corner color of a bitmap.
1438 On W32, XIMG is assumed to a device context with the bitmap selected. */
1440 static RGB_PIXEL_COLOR
1441 four_corners_best (ximg
, corners
, width
, height
)
1442 XImagePtr_or_DC ximg
;
1444 unsigned long width
, height
;
1446 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1449 if (corners
&& corners
[BOT_CORNER
] >= 0)
1451 /* Get the colors at the corner_pixels of ximg. */
1452 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1453 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1454 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1455 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1459 /* Get the colors at the corner_pixels of ximg. */
1460 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1461 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1462 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1463 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1465 /* Choose the most frequently found color as background. */
1466 for (i
= best_count
= 0; i
< 4; ++i
)
1470 for (j
= n
= 0; j
< 4; ++j
)
1471 if (corner_pixels
[i
] == corner_pixels
[j
])
1475 best
= corner_pixels
[i
], best_count
= n
;
1481 /* Portability macros */
1485 #define Destroy_Image(img_dc, prev) \
1486 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1488 #define Free_Pixmap(display, pixmap) \
1489 DeleteObject (pixmap)
1491 #elif defined (HAVE_NS)
1493 #define Destroy_Image(ximg, dummy) \
1494 ns_release_object(ximg)
1496 #define Free_Pixmap(display, pixmap) \
1497 ns_release_object(pixmap)
1501 #define Destroy_Image(ximg, dummy) \
1502 XDestroyImage (ximg)
1504 #define Free_Pixmap(display, pixmap) \
1505 XFreePixmap (display, pixmap)
1507 #endif /* !HAVE_NTGUI && !HAVE_NS */
1510 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1511 it is guessed heuristically. If non-zero, XIMG is an existing
1512 XImage object (or device context with the image selected on W32) to
1513 use for the heuristic. */
1516 image_background (img
, f
, ximg
)
1519 XImagePtr_or_DC ximg
;
1521 if (! img
->background_valid
)
1522 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1524 int free_ximg
= !ximg
;
1527 #endif /* HAVE_NTGUI */
1532 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1533 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1535 HDC frame_dc
= get_frame_dc (f
);
1536 ximg
= CreateCompatibleDC (frame_dc
);
1537 release_frame_dc (f
, frame_dc
);
1538 prev
= SelectObject (ximg
, img
->pixmap
);
1539 #endif /* !HAVE_NTGUI */
1542 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1545 Destroy_Image (ximg
, prev
);
1547 img
->background_valid
= 1;
1550 return img
->background
;
1553 /* Return the `background_transparent' field of IMG. If IMG doesn't
1554 have one yet, it is guessed heuristically. If non-zero, MASK is an
1555 existing XImage object to use for the heuristic. */
1558 image_background_transparent (img
, f
, mask
)
1561 XImagePtr_or_DC mask
;
1563 if (! img
->background_transparent_valid
)
1564 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1568 int free_mask
= !mask
;
1571 #endif /* HAVE_NTGUI */
1576 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1577 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1579 HDC frame_dc
= get_frame_dc (f
);
1580 mask
= CreateCompatibleDC (frame_dc
);
1581 release_frame_dc (f
, frame_dc
);
1582 prev
= SelectObject (mask
, img
->mask
);
1583 #endif /* HAVE_NTGUI */
1586 img
->background_transparent
1587 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1590 Destroy_Image (mask
, prev
);
1593 img
->background_transparent
= 0;
1595 img
->background_transparent_valid
= 1;
1598 return img
->background_transparent
;
1602 /***********************************************************************
1603 Helper functions for X image types
1604 ***********************************************************************/
1606 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1608 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1609 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1611 Lisp_Object color_name
,
1612 unsigned long dflt
));
1615 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1616 free the pixmap if any. MASK_P non-zero means clear the mask
1617 pixmap if any. COLORS_P non-zero means free colors allocated for
1618 the image, if any. */
1621 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1624 int pixmap_p
, mask_p
, colors_p
;
1626 if (pixmap_p
&& img
->pixmap
)
1628 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1629 img
->pixmap
= NO_PIXMAP
;
1630 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1631 img
->background_valid
= 0;
1634 if (mask_p
&& img
->mask
)
1636 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1637 img
->mask
= NO_PIXMAP
;
1638 img
->background_transparent_valid
= 0;
1641 if (colors_p
&& img
->ncolors
)
1643 /* W32_TODO: color table support. */
1644 #ifdef HAVE_X_WINDOWS
1645 x_free_colors (f
, img
->colors
, img
->ncolors
);
1646 #endif /* HAVE_X_WINDOWS */
1647 xfree (img
->colors
);
1654 /* Free X resources of image IMG which is used on frame F. */
1657 x_clear_image (f
, img
)
1662 x_clear_image_1 (f
, img
, 1, 1, 1);
1667 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1668 cannot be allocated, use DFLT. Add a newly allocated color to
1669 IMG->colors, so that it can be freed again. Value is the pixel
1672 static unsigned long
1673 x_alloc_image_color (f
, img
, color_name
, dflt
)
1676 Lisp_Object color_name
;
1680 unsigned long result
;
1682 xassert (STRINGP (color_name
));
1684 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1686 /* This isn't called frequently so we get away with simply
1687 reallocating the color vector to the needed size, here. */
1690 (unsigned long *) xrealloc (img
->colors
,
1691 img
->ncolors
* sizeof *img
->colors
);
1692 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1693 result
= color
.pixel
;
1703 /***********************************************************************
1705 ***********************************************************************/
1707 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1708 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1709 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1711 /* Return a new, initialized image cache that is allocated from the
1712 heap. Call free_image_cache to free an image cache. */
1714 struct image_cache
*
1717 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1720 bzero (c
, sizeof *c
);
1722 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1723 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1724 c
->buckets
= (struct image
**) xmalloc (size
);
1725 bzero (c
->buckets
, size
);
1730 /* Find an image matching SPEC in the cache, and return it. If no
1731 image is found, return NULL. */
1732 static struct image
*
1733 search_image_cache (f
, spec
, hash
)
1739 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1740 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1742 if (!c
) return NULL
;
1744 /* If the image spec does not specify a background color, the cached
1745 image must have the same background color as the current frame.
1746 The foreground color must also match, for the sake of monochrome
1749 In fact, we could ignore the foreground color matching condition
1750 for color images, or if the image spec specifies :foreground;
1751 similarly we could ignore the background color matching condition
1752 for formats that don't use transparency (such as jpeg), or if the
1753 image spec specifies :background. However, the extra memory
1754 usage is probably negligible in practice, so we don't bother. */
1756 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1757 if (img
->hash
== hash
1758 && !NILP (Fequal (img
->spec
, spec
))
1759 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1760 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1766 /* Search frame F for an image with spec SPEC, and free it. */
1769 uncache_image (f
, spec
)
1773 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1775 free_image (f
, img
);
1779 /* Free image cache of frame F. Be aware that X frames share images
1783 free_image_cache (f
)
1786 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1791 /* Cache should not be referenced by any frame when freed. */
1792 xassert (c
->refcount
== 0);
1794 for (i
= 0; i
< c
->used
; ++i
)
1795 free_image (f
, c
->images
[i
]);
1799 FRAME_IMAGE_CACHE (f
) = NULL
;
1804 /* Clear image cache of frame F. FILTER=t means free all images.
1805 FILTER=nil means clear only images that haven't been
1806 displayed for some time.
1807 Else, only free the images which have FILTER in their `dependencies'.
1808 Should be called from time to time to reduce the number of loaded images.
1809 If image-cache-eviction-delay is non-nil, this frees images in the cache
1810 which weren't displayed for at least that many seconds. */
1813 clear_image_cache (struct frame
*f
, Lisp_Object filter
)
1815 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1817 if (c
&& (!NILP (filter
) || INTEGERP (Vimage_cache_eviction_delay
)))
1824 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1826 /* Block input so that we won't be interrupted by a SIGIO
1827 while being in an inconsistent state. */
1830 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1832 struct image
*img
= c
->images
[i
];
1834 && (NILP (filter
) ? img
->timestamp
< old
1836 || !NILP (Fmember (filter
, img
->dependencies
)))))
1838 free_image (f
, img
);
1843 /* We may be clearing the image cache because, for example,
1844 Emacs was iconified for a longer period of time. In that
1845 case, current matrices may still contain references to
1846 images freed above. So, clear these matrices. */
1849 Lisp_Object tail
, frame
;
1851 FOR_EACH_FRAME (tail
, frame
)
1853 struct frame
*f
= XFRAME (frame
);
1854 if (FRAME_IMAGE_CACHE (f
) == c
)
1855 clear_current_matrices (f
);
1858 ++windows_or_buffers_changed
;
1866 clear_image_caches (Lisp_Object filter
)
1868 /* FIXME: We want to do
1869 * struct terminal *t;
1870 * for (t = terminal_list; t; t = t->next_terminal)
1871 * clear_image_cache (t, filter); */
1872 Lisp_Object tail
, frame
;
1873 FOR_EACH_FRAME (tail
, frame
)
1874 if (FRAME_WINDOW_P (XFRAME (frame
)))
1875 clear_image_cache (XFRAME (frame
), filter
);
1878 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1880 doc
: /* Clear the image cache.
1881 FILTER nil or a frame means clear all images in the selected frame.
1882 FILTER t means clear the image caches of all frames.
1883 Anything else, means only clear those images which refer to FILTER,
1884 which is then usually a filename. */)
1888 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1889 clear_image_caches (filter
);
1891 clear_image_cache (check_x_frame (filter
), Qt
);
1897 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1899 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1900 If SPEC specifies an image file, the displayed image is updated with
1901 the current contents of that file.
1902 FRAME nil or omitted means use the selected frame.
1903 FRAME t means refresh the image on all frames. */)
1905 Lisp_Object spec
, frame
;
1907 if (!valid_image_p (spec
))
1908 error ("Invalid image specification");
1913 FOR_EACH_FRAME (tail
, frame
)
1915 struct frame
*f
= XFRAME (frame
);
1916 if (FRAME_WINDOW_P (f
))
1917 uncache_image (f
, spec
);
1921 uncache_image (check_x_frame (frame
), spec
);
1927 /* Compute masks and transform image IMG on frame F, as specified
1928 by the image's specification, */
1931 postprocess_image (f
, img
)
1935 /* Manipulation of the image's mask. */
1938 Lisp_Object conversion
, spec
;
1943 /* `:heuristic-mask t'
1945 means build a mask heuristically.
1946 `:heuristic-mask (R G B)'
1947 `:mask (heuristic (R G B))'
1948 means build a mask from color (R G B) in the
1951 means remove a mask, if any. */
1953 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1955 x_build_heuristic_mask (f
, img
, mask
);
1960 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1962 if (EQ (mask
, Qheuristic
))
1963 x_build_heuristic_mask (f
, img
, Qt
);
1964 else if (CONSP (mask
)
1965 && EQ (XCAR (mask
), Qheuristic
))
1967 if (CONSP (XCDR (mask
)))
1968 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1970 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1972 else if (NILP (mask
) && found_p
&& img
->mask
)
1974 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1975 img
->mask
= NO_PIXMAP
;
1980 /* Should we apply an image transformation algorithm? */
1981 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1982 if (EQ (conversion
, Qdisabled
))
1983 x_disable_image (f
, img
);
1984 else if (EQ (conversion
, Qlaplace
))
1986 else if (EQ (conversion
, Qemboss
))
1988 else if (CONSP (conversion
)
1989 && EQ (XCAR (conversion
), Qedge_detection
))
1992 tem
= XCDR (conversion
);
1994 x_edge_detection (f
, img
,
1995 Fplist_get (tem
, QCmatrix
),
1996 Fplist_get (tem
, QCcolor_adjustment
));
2002 /* Return the id of image with Lisp specification SPEC on frame F.
2003 SPEC must be a valid Lisp image specification (see valid_image_p). */
2006 lookup_image (f
, spec
)
2010 struct image_cache
*c
;
2013 struct gcpro gcpro1
;
2016 /* F must be a window-system frame, and SPEC must be a valid image
2018 xassert (FRAME_WINDOW_P (f
));
2019 xassert (valid_image_p (spec
));
2021 c
= FRAME_IMAGE_CACHE (f
);
2025 /* Look up SPEC in the hash table of the image cache. */
2026 hash
= sxhash (spec
, 0);
2027 img
= search_image_cache (f
, spec
, hash
);
2028 if (img
&& img
->load_failed_p
)
2030 free_image (f
, img
);
2034 /* If not found, create a new image and cache it. */
2037 extern Lisp_Object Qpostscript
;
2040 img
= make_image (spec
, hash
);
2041 cache_image (f
, img
);
2042 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2043 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2044 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2046 /* If we can't load the image, and we don't have a width and
2047 height, use some arbitrary width and height so that we can
2048 draw a rectangle for it. */
2049 if (img
->load_failed_p
)
2053 value
= image_spec_value (spec
, QCwidth
, NULL
);
2054 img
->width
= (INTEGERP (value
)
2055 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2056 value
= image_spec_value (spec
, QCheight
, NULL
);
2057 img
->height
= (INTEGERP (value
)
2058 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2062 /* Handle image type independent image attributes
2063 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2064 `:background COLOR'. */
2065 Lisp_Object ascent
, margin
, relief
, bg
;
2067 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2068 if (INTEGERP (ascent
))
2069 img
->ascent
= XFASTINT (ascent
);
2070 else if (EQ (ascent
, Qcenter
))
2071 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2073 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2074 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2075 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2076 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2077 && INTEGERP (XCDR (margin
)))
2079 if (XINT (XCAR (margin
)) > 0)
2080 img
->hmargin
= XFASTINT (XCAR (margin
));
2081 if (XINT (XCDR (margin
)) > 0)
2082 img
->vmargin
= XFASTINT (XCDR (margin
));
2085 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2086 if (INTEGERP (relief
))
2088 img
->relief
= XINT (relief
);
2089 img
->hmargin
+= eabs (img
->relief
);
2090 img
->vmargin
+= eabs (img
->relief
);
2093 if (! img
->background_valid
)
2095 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2099 = x_alloc_image_color (f
, img
, bg
,
2100 FRAME_BACKGROUND_PIXEL (f
));
2101 img
->background_valid
= 1;
2105 /* Do image transformations and compute masks, unless we
2106 don't have the image yet. */
2107 if (!EQ (*img
->type
->type
, Qpostscript
))
2108 postprocess_image (f
, img
);
2114 /* We're using IMG, so set its timestamp to `now'. */
2115 EMACS_GET_TIME (now
);
2116 img
->timestamp
= EMACS_SECS (now
);
2120 /* Value is the image id. */
2125 /* Cache image IMG in the image cache of frame F. */
2128 cache_image (f
, img
)
2132 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2135 /* Find a free slot in c->images. */
2136 for (i
= 0; i
< c
->used
; ++i
)
2137 if (c
->images
[i
] == NULL
)
2140 /* If no free slot found, maybe enlarge c->images. */
2141 if (i
== c
->used
&& c
->used
== c
->size
)
2144 c
->images
= (struct image
**) xrealloc (c
->images
,
2145 c
->size
* sizeof *c
->images
);
2148 /* Add IMG to c->images, and assign IMG an id. */
2154 /* Add IMG to the cache's hash table. */
2155 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2156 img
->next
= c
->buckets
[i
];
2158 img
->next
->prev
= img
;
2160 c
->buckets
[i
] = img
;
2164 /* Call FN on every image in the image cache of frame F. Used to mark
2165 Lisp Objects in the image cache. */
2167 /* Mark Lisp objects in image IMG. */
2173 mark_object (img
->spec
);
2174 mark_object (img
->dependencies
);
2176 if (!NILP (img
->data
.lisp_val
))
2177 mark_object (img
->data
.lisp_val
);
2182 mark_image_cache (struct image_cache
*c
)
2187 for (i
= 0; i
< c
->used
; ++i
)
2189 mark_image (c
->images
[i
]);
2195 /***********************************************************************
2196 X / NS / W32 support code
2197 ***********************************************************************/
2201 /* Macro for defining functions that will be loaded from image DLLs. */
2202 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2204 /* Macro for loading those image functions from the library. */
2205 #define LOAD_IMGLIB_FN(lib,func) { \
2206 fn_##func = (void *) GetProcAddress (lib, #func); \
2207 if (!fn_##func) return 0; \
2210 /* Load a DLL implementing an image type.
2211 The `image-library-alist' variable associates a symbol,
2212 identifying an image type, to a list of possible filenames.
2213 The function returns NULL if no library could be loaded for
2214 the given image type, or if the library was previously loaded;
2215 else the handle of the DLL. */
2217 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2219 HMODULE library
= NULL
;
2221 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2223 Lisp_Object dlls
= Fassq (type
, libraries
);
2226 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2228 CHECK_STRING_CAR (dlls
);
2229 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2237 #endif /* HAVE_NTGUI */
2239 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2240 XImagePtr
*, Pixmap
*));
2241 static void x_destroy_x_image
P_ ((XImagePtr
));
2242 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2245 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2246 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2247 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2248 via xmalloc. Print error messages via image_error if an error
2249 occurs. Value is non-zero if successful.
2251 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2252 should indicate the bit depth of the image. */
2255 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2257 int width
, height
, depth
;
2261 #ifdef HAVE_X_WINDOWS
2262 Display
*display
= FRAME_X_DISPLAY (f
);
2263 Window window
= FRAME_X_WINDOW (f
);
2264 Screen
*screen
= FRAME_X_SCREEN (f
);
2266 xassert (interrupt_input_blocked
);
2269 depth
= DefaultDepthOfScreen (screen
);
2270 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2271 depth
, ZPixmap
, 0, NULL
, width
, height
,
2272 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2275 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2279 /* Allocate image raster. */
2280 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2282 /* Allocate a pixmap of the same size. */
2283 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2284 if (*pixmap
== NO_PIXMAP
)
2286 x_destroy_x_image (*ximg
);
2288 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2293 #endif /* HAVE_X_WINDOWS */
2297 BITMAPINFOHEADER
*header
;
2299 int scanline_width_bits
;
2301 int palette_colors
= 0;
2306 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2307 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2309 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2313 scanline_width_bits
= width
* depth
;
2314 remainder
= scanline_width_bits
% 32;
2317 scanline_width_bits
+= 32 - remainder
;
2319 /* Bitmaps with a depth less than 16 need a palette. */
2320 /* BITMAPINFO structure already contains the first RGBQUAD. */
2322 palette_colors
= 1 << depth
- 1;
2324 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2327 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2331 header
= &((*ximg
)->info
.bmiHeader
);
2332 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2333 header
->biSize
= sizeof (*header
);
2334 header
->biWidth
= width
;
2335 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2336 header
->biPlanes
= 1;
2337 header
->biBitCount
= depth
;
2338 header
->biCompression
= BI_RGB
;
2339 header
->biClrUsed
= palette_colors
;
2341 /* TODO: fill in palette. */
2344 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2345 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2346 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2347 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2348 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2349 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2350 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2351 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2354 hdc
= get_frame_dc (f
);
2356 /* Create a DIBSection and raster array for the bitmap,
2357 and store its handle in *pixmap. */
2358 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2359 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2360 /* casting avoids a GCC warning */
2361 (void **)&((*ximg
)->data
), NULL
, 0);
2363 /* Realize display palette and garbage all frames. */
2364 release_frame_dc (f
, hdc
);
2366 if (*pixmap
== NULL
)
2368 DWORD err
= GetLastError ();
2369 Lisp_Object errcode
;
2370 /* All system errors are < 10000, so the following is safe. */
2371 XSETINT (errcode
, (int) err
);
2372 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2373 x_destroy_x_image (*ximg
);
2379 #endif /* HAVE_NTGUI */
2382 *pixmap
= ns_image_for_XPM(width
, height
, depth
);
2386 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil
, Qnil
);
2395 /* Destroy XImage XIMG. Free XIMG->data. */
2398 x_destroy_x_image (ximg
)
2401 xassert (interrupt_input_blocked
);
2404 #ifdef HAVE_X_WINDOWS
2407 XDestroyImage (ximg
);
2408 #endif /* HAVE_X_WINDOWS */
2410 /* Data will be freed by DestroyObject. */
2413 #endif /* HAVE_NTGUI */
2415 ns_release_object(ximg
);
2416 #endif /* HAVE_NS */
2421 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2422 are width and height of both the image and pixmap. */
2425 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2431 #ifdef HAVE_X_WINDOWS
2434 xassert (interrupt_input_blocked
);
2435 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2436 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2437 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2438 #endif /* HAVE_X_WINDOWS */
2441 #if 0 /* I don't think this is necessary looking at where it is used. */
2442 HDC hdc
= get_frame_dc (f
);
2443 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2444 release_frame_dc (f
, hdc
);
2446 #endif /* HAVE_NTGUI */
2449 xassert (ximg
== pixmap
);
2450 ns_retain_object(ximg
);
2455 /***********************************************************************
2457 ***********************************************************************/
2459 static unsigned char *slurp_file
P_ ((char *, int *));
2462 /* Find image file FILE. Look in data-directory/images, then
2463 x-bitmap-file-path. Value is the encoded full name of the file
2464 found, or nil if not found. */
2467 x_find_image_file (file
)
2470 Lisp_Object file_found
, search_path
;
2471 struct gcpro gcpro1
, gcpro2
;
2475 /* TODO I think this should use something like image-load-path
2476 instead. Unfortunately, that can contain non-string elements. */
2477 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2479 Vx_bitmap_file_path
);
2480 GCPRO2 (file_found
, search_path
);
2482 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2483 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2489 file_found
= ENCODE_FILE (file_found
);
2498 /* Read FILE into memory. Value is a pointer to a buffer allocated
2499 with xmalloc holding FILE's contents. Value is null if an error
2500 occurred. *SIZE is set to the size of the file. */
2502 static unsigned char *
2503 slurp_file (file
, size
)
2508 unsigned char *buf
= NULL
;
2511 if (stat (file
, &st
) == 0
2512 && (fp
= fopen (file
, "rb")) != NULL
2513 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2514 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2535 /***********************************************************************
2537 ***********************************************************************/
2539 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2540 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2541 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2542 unsigned char *, unsigned char *));
2543 static int xbm_image_p
P_ ((Lisp_Object object
));
2544 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2545 unsigned char *, unsigned char *,
2546 int *, int *, unsigned char **));
2547 static int xbm_file_p
P_ ((Lisp_Object
));
2550 /* Indices of image specification fields in xbm_format, below. */
2552 enum xbm_keyword_index
2570 /* Vector of image_keyword structures describing the format
2571 of valid XBM image specifications. */
2573 static struct image_keyword xbm_format
[XBM_LAST
] =
2575 {":type", IMAGE_SYMBOL_VALUE
, 1},
2576 {":file", IMAGE_STRING_VALUE
, 0},
2577 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2578 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2579 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2580 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2581 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2582 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2583 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2584 {":relief", IMAGE_INTEGER_VALUE
, 0},
2585 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2586 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2587 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2590 /* Structure describing the image type XBM. */
2592 static struct image_type xbm_type
=
2601 /* Tokens returned from xbm_scan. */
2610 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2611 A valid specification is a list starting with the symbol `image'
2612 The rest of the list is a property list which must contain an
2615 If the specification specifies a file to load, it must contain
2616 an entry `:file FILENAME' where FILENAME is a string.
2618 If the specification is for a bitmap loaded from memory it must
2619 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2620 WIDTH and HEIGHT are integers > 0. DATA may be:
2622 1. a string large enough to hold the bitmap data, i.e. it must
2623 have a size >= (WIDTH + 7) / 8 * HEIGHT
2625 2. a bool-vector of size >= WIDTH * HEIGHT
2627 3. a vector of strings or bool-vectors, one for each line of the
2630 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2631 may not be specified in this case because they are defined in the
2634 Both the file and data forms may contain the additional entries
2635 `:background COLOR' and `:foreground COLOR'. If not present,
2636 foreground and background of the frame on which the image is
2637 displayed is used. */
2640 xbm_image_p (object
)
2643 struct image_keyword kw
[XBM_LAST
];
2645 bcopy (xbm_format
, kw
, sizeof kw
);
2646 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2649 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2651 if (kw
[XBM_FILE
].count
)
2653 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2656 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2658 /* In-memory XBM file. */
2659 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2667 /* Entries for `:width', `:height' and `:data' must be present. */
2668 if (!kw
[XBM_WIDTH
].count
2669 || !kw
[XBM_HEIGHT
].count
2670 || !kw
[XBM_DATA
].count
)
2673 data
= kw
[XBM_DATA
].value
;
2674 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2675 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2677 /* Check type of data, and width and height against contents of
2683 /* Number of elements of the vector must be >= height. */
2684 if (XVECTOR (data
)->size
< height
)
2687 /* Each string or bool-vector in data must be large enough
2688 for one line of the image. */
2689 for (i
= 0; i
< height
; ++i
)
2691 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2696 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2699 else if (BOOL_VECTOR_P (elt
))
2701 if (XBOOL_VECTOR (elt
)->size
< width
)
2708 else if (STRINGP (data
))
2711 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2714 else if (BOOL_VECTOR_P (data
))
2716 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2727 /* Scan a bitmap file. FP is the stream to read from. Value is
2728 either an enumerator from enum xbm_token, or a character for a
2729 single-character token, or 0 at end of file. If scanning an
2730 identifier, store the lexeme of the identifier in SVAL. If
2731 scanning a number, store its value in *IVAL. */
2734 xbm_scan (s
, end
, sval
, ival
)
2735 unsigned char **s
, *end
;
2743 /* Skip white space. */
2744 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2749 else if (isdigit (c
))
2751 int value
= 0, digit
;
2753 if (c
== '0' && *s
< end
)
2756 if (c
== 'x' || c
== 'X')
2763 else if (c
>= 'a' && c
<= 'f')
2764 digit
= c
- 'a' + 10;
2765 else if (c
>= 'A' && c
<= 'F')
2766 digit
= c
- 'A' + 10;
2769 value
= 16 * value
+ digit
;
2772 else if (isdigit (c
))
2776 && (c
= *(*s
)++, isdigit (c
)))
2777 value
= 8 * value
+ c
- '0';
2784 && (c
= *(*s
)++, isdigit (c
)))
2785 value
= 10 * value
+ c
- '0';
2793 else if (isalpha (c
) || c
== '_')
2797 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2804 else if (c
== '/' && **s
== '*')
2806 /* C-style comment. */
2808 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2822 /* Create a Windows bitmap from X bitmap data. */
2824 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2826 static unsigned char swap_nibble
[16]
2827 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2828 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2829 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2830 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2832 unsigned char *bits
, *p
;
2835 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2836 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2837 bits
= (unsigned char *) alloca (height
* w2
);
2838 bzero (bits
, height
* w2
);
2839 for (i
= 0; i
< height
; i
++)
2842 for (j
= 0; j
< w1
; j
++)
2844 /* Bitswap XBM bytes to match how Windows does things. */
2845 unsigned char c
= *data
++;
2846 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2847 | (swap_nibble
[(c
>>4) & 0xf]));
2850 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2856 convert_mono_to_color_image (f
, img
, foreground
, background
)
2859 COLORREF foreground
, background
;
2861 HDC hdc
, old_img_dc
, new_img_dc
;
2862 HGDIOBJ old_prev
, new_prev
;
2865 hdc
= get_frame_dc (f
);
2866 old_img_dc
= CreateCompatibleDC (hdc
);
2867 new_img_dc
= CreateCompatibleDC (hdc
);
2868 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2869 release_frame_dc (f
, hdc
);
2870 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2871 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2872 /* Windows convention for mono bitmaps is black = background,
2873 white = foreground. */
2874 SetTextColor (new_img_dc
, background
);
2875 SetBkColor (new_img_dc
, foreground
);
2877 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2880 SelectObject (old_img_dc
, old_prev
);
2881 SelectObject (new_img_dc
, new_prev
);
2882 DeleteDC (old_img_dc
);
2883 DeleteDC (new_img_dc
);
2884 DeleteObject (img
->pixmap
);
2885 if (new_pixmap
== 0)
2886 fprintf (stderr
, "Failed to convert image to color.\n");
2888 img
->pixmap
= new_pixmap
;
2891 #define XBM_BIT_SHUFFLE(b) (~(b))
2895 #define XBM_BIT_SHUFFLE(b) (b)
2897 #endif /* HAVE_NTGUI */
2901 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
2905 RGB_PIXEL_COLOR fg
, bg
;
2906 int non_default_colors
;
2910 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2912 /* If colors were specified, transfer the bitmap to a color one. */
2913 if (non_default_colors
)
2914 convert_mono_to_color_image (f
, img
, fg
, bg
);
2916 #elif defined (HAVE_NS)
2917 img
->pixmap
= ns_image_from_XBM(data
, img
->width
, img
->height
);
2921 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2924 img
->width
, img
->height
,
2926 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2927 #endif /* !HAVE_NTGUI && !HAVE_NS */
2932 /* Replacement for XReadBitmapFileData which isn't available under old
2933 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2934 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2935 the image. Return in *DATA the bitmap data allocated with xmalloc.
2936 Value is non-zero if successful. DATA null means just test if
2937 CONTENTS looks like an in-memory XBM file. */
2940 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
2942 unsigned char *contents
, *end
;
2943 int *width
, *height
;
2944 unsigned char **data
;
2946 unsigned char *s
= contents
;
2947 char buffer
[BUFSIZ
];
2950 int bytes_per_line
, i
, nbytes
;
2956 LA1 = xbm_scan (&s, end, buffer, &value)
2958 #define expect(TOKEN) \
2959 if (LA1 != (TOKEN)) \
2964 #define expect_ident(IDENT) \
2965 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2970 *width
= *height
= -1;
2973 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2975 /* Parse defines for width, height and hot-spots. */
2979 expect_ident ("define");
2980 expect (XBM_TK_IDENT
);
2982 if (LA1
== XBM_TK_NUMBER
)
2984 char *p
= strrchr (buffer
, '_');
2985 p
= p
? p
+ 1 : buffer
;
2986 if (strcmp (p
, "width") == 0)
2988 else if (strcmp (p
, "height") == 0)
2991 expect (XBM_TK_NUMBER
);
2994 if (!check_image_size (f
, *width
, *height
))
2996 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
2999 else if (data
== NULL
)
3002 /* Parse bits. Must start with `static'. */
3003 expect_ident ("static");
3004 if (LA1
== XBM_TK_IDENT
)
3006 if (strcmp (buffer
, "unsigned") == 0)
3009 expect_ident ("char");
3011 else if (strcmp (buffer
, "short") == 0)
3015 if (*width
% 16 && *width
% 16 < 9)
3018 else if (strcmp (buffer
, "char") == 0)
3026 expect (XBM_TK_IDENT
);
3032 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3033 nbytes
= bytes_per_line
* *height
;
3034 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3038 for (i
= 0; i
< nbytes
; i
+= 2)
3041 expect (XBM_TK_NUMBER
);
3043 *p
++ = XBM_BIT_SHUFFLE (val
);
3044 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3045 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3047 if (LA1
== ',' || LA1
== '}')
3055 for (i
= 0; i
< nbytes
; ++i
)
3058 expect (XBM_TK_NUMBER
);
3060 *p
++ = XBM_BIT_SHUFFLE (val
);
3062 if (LA1
== ',' || LA1
== '}')
3087 /* Load XBM image IMG which will be displayed on frame F from buffer
3088 CONTENTS. END is the end of the buffer. Value is non-zero if
3092 xbm_load_image (f
, img
, contents
, end
)
3095 unsigned char *contents
, *end
;
3098 unsigned char *data
;
3101 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3104 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3105 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3106 int non_default_colors
= 0;
3109 xassert (img
->width
> 0 && img
->height
> 0);
3111 /* Get foreground and background colors, maybe allocate colors. */
3112 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3115 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3116 non_default_colors
= 1;
3118 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3121 background
= x_alloc_image_color (f
, img
, value
, background
);
3122 img
->background
= background
;
3123 img
->background_valid
= 1;
3124 non_default_colors
= 1;
3127 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3128 foreground
, background
,
3129 non_default_colors
);
3132 if (img
->pixmap
== NO_PIXMAP
)
3134 x_clear_image (f
, img
);
3135 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3141 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3147 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3154 return (STRINGP (data
)
3155 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3162 /* Fill image IMG which is used on frame F with pixmap data. Value is
3163 non-zero if successful. */
3171 Lisp_Object file_name
;
3173 xassert (xbm_image_p (img
->spec
));
3175 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3176 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3177 if (STRINGP (file_name
))
3180 unsigned char *contents
;
3182 struct gcpro gcpro1
;
3184 file
= x_find_image_file (file_name
);
3186 if (!STRINGP (file
))
3188 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3193 contents
= slurp_file (SDATA (file
), &size
);
3194 if (contents
== NULL
)
3196 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3201 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3206 struct image_keyword fmt
[XBM_LAST
];
3208 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3209 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3210 int non_default_colors
= 0;
3213 int in_memory_file_p
= 0;
3215 /* See if data looks like an in-memory XBM file. */
3216 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3217 in_memory_file_p
= xbm_file_p (data
);
3219 /* Parse the image specification. */
3220 bcopy (xbm_format
, fmt
, sizeof fmt
);
3221 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3224 /* Get specified width, and height. */
3225 if (!in_memory_file_p
)
3227 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3228 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3229 xassert (img
->width
> 0 && img
->height
> 0);
3232 /* Get foreground and background colors, maybe allocate colors. */
3233 if (fmt
[XBM_FOREGROUND
].count
3234 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3236 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3238 non_default_colors
= 1;
3241 if (fmt
[XBM_BACKGROUND
].count
3242 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3244 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3246 non_default_colors
= 1;
3249 if (in_memory_file_p
)
3250 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3259 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3261 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3262 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3264 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3266 bcopy (SDATA (line
), p
, nbytes
);
3268 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3271 else if (STRINGP (data
))
3272 bits
= SDATA (data
);
3274 bits
= XBOOL_VECTOR (data
)->data
;
3280 /* Windows mono bitmaps are reversed compared with X. */
3281 invertedBits
= bits
;
3282 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3284 bits
= (char *) alloca(nbytes
);
3285 for (i
= 0; i
< nbytes
; i
++)
3286 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3289 /* Create the pixmap. */
3291 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3292 foreground
, background
,
3293 non_default_colors
);
3298 image_error ("Unable to create pixmap for XBM image `%s'",
3300 x_clear_image (f
, img
);
3310 /***********************************************************************
3312 ***********************************************************************/
3314 #if defined (HAVE_XPM) || defined (HAVE_NS)
3316 static int xpm_image_p
P_ ((Lisp_Object object
));
3317 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3318 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3320 #endif /* HAVE_XPM || HAVE_NS */
3324 /* Indicate to xpm.h that we don't have Xlib. */
3326 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3327 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3328 #define XColor xpm_XColor
3329 #define XImage xpm_XImage
3330 #define Display xpm_Display
3331 #define PIXEL_ALREADY_TYPEDEFED
3332 #include "X11/xpm.h"
3337 #undef PIXEL_ALREADY_TYPEDEFED
3339 #include "X11/xpm.h"
3340 #endif /* HAVE_NTGUI */
3341 #endif /* HAVE_XPM */
3343 #if defined (HAVE_XPM) || defined (HAVE_NS)
3344 /* The symbol `xpm' identifying XPM-format images. */
3348 /* Indices of image specification fields in xpm_format, below. */
3350 enum xpm_keyword_index
3366 /* Vector of image_keyword structures describing the format
3367 of valid XPM image specifications. */
3369 static struct image_keyword xpm_format
[XPM_LAST
] =
3371 {":type", IMAGE_SYMBOL_VALUE
, 1},
3372 {":file", IMAGE_STRING_VALUE
, 0},
3373 {":data", IMAGE_STRING_VALUE
, 0},
3374 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3375 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3376 {":relief", IMAGE_INTEGER_VALUE
, 0},
3377 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3378 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3379 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3380 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3381 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3384 /* Structure describing the image type XPM. */
3386 static struct image_type xpm_type
=
3395 #ifdef HAVE_X_WINDOWS
3397 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3398 functions for allocating image colors. Our own functions handle
3399 color allocation failures more gracefully than the ones on the XPM
3402 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3403 #define ALLOC_XPM_COLORS
3405 #endif /* HAVE_X_WINDOWS */
3407 #ifdef ALLOC_XPM_COLORS
3409 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3410 static void xpm_free_color_cache
P_ ((void));
3411 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3412 static int xpm_color_bucket
P_ ((char *));
3413 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3416 /* An entry in a hash table used to cache color definitions of named
3417 colors. This cache is necessary to speed up XPM image loading in
3418 case we do color allocations ourselves. Without it, we would need
3419 a call to XParseColor per pixel in the image. */
3421 struct xpm_cached_color
3423 /* Next in collision chain. */
3424 struct xpm_cached_color
*next
;
3426 /* Color definition (RGB and pixel color). */
3433 /* The hash table used for the color cache, and its bucket vector
3436 #define XPM_COLOR_CACHE_BUCKETS 1001
3437 struct xpm_cached_color
**xpm_color_cache
;
3439 /* Initialize the color cache. */
3442 xpm_init_color_cache (f
, attrs
)
3444 XpmAttributes
*attrs
;
3446 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3447 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3448 memset (xpm_color_cache
, 0, nbytes
);
3449 init_color_table ();
3451 if (attrs
->valuemask
& XpmColorSymbols
)
3456 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3457 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3458 attrs
->colorsymbols
[i
].value
, &color
))
3460 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3462 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3467 /* Free the color cache. */
3470 xpm_free_color_cache ()
3472 struct xpm_cached_color
*p
, *next
;
3475 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3476 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3482 xfree (xpm_color_cache
);
3483 xpm_color_cache
= NULL
;
3484 free_color_table ();
3487 /* Return the bucket index for color named COLOR_NAME in the color
3491 xpm_color_bucket (color_name
)
3497 for (s
= color_name
; *s
; ++s
)
3499 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3503 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3504 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3507 static struct xpm_cached_color
*
3508 xpm_cache_color (f
, color_name
, color
, bucket
)
3515 struct xpm_cached_color
*p
;
3518 bucket
= xpm_color_bucket (color_name
);
3520 nbytes
= sizeof *p
+ strlen (color_name
);
3521 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3522 strcpy (p
->name
, color_name
);
3524 p
->next
= xpm_color_cache
[bucket
];
3525 xpm_color_cache
[bucket
] = p
;
3529 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3530 return the cached definition in *COLOR. Otherwise, make a new
3531 entry in the cache and allocate the color. Value is zero if color
3532 allocation failed. */
3535 xpm_lookup_color (f
, color_name
, color
)
3540 struct xpm_cached_color
*p
;
3541 int h
= xpm_color_bucket (color_name
);
3543 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3544 if (strcmp (p
->name
, color_name
) == 0)
3549 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3552 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3554 p
= xpm_cache_color (f
, color_name
, color
, h
);
3556 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3557 with transparency, and it's useful. */
3558 else if (strcmp ("opaque", color_name
) == 0)
3560 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3561 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3562 p
= xpm_cache_color (f
, color_name
, color
, h
);
3569 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3570 CLOSURE is a pointer to the frame on which we allocate the
3571 color. Return in *COLOR the allocated color. Value is non-zero
3575 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3582 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3586 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3587 is a pointer to the frame on which we allocate the color. Value is
3588 non-zero if successful. */
3591 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3601 #endif /* ALLOC_XPM_COLORS */
3606 /* XPM library details. */
3608 DEF_IMGLIB_FN (XpmFreeAttributes
);
3609 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3610 DEF_IMGLIB_FN (XpmReadFileToImage
);
3611 DEF_IMGLIB_FN (XImageFree
);
3614 init_xpm_functions (Lisp_Object libraries
)
3618 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3621 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3622 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3623 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3624 LOAD_IMGLIB_FN (library
, XImageFree
);
3628 #endif /* HAVE_NTGUI */
3631 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3632 for XPM images. Such a list must consist of conses whose car and
3636 xpm_valid_color_symbols_p (color_symbols
)
3637 Lisp_Object color_symbols
;
3639 while (CONSP (color_symbols
))
3641 Lisp_Object sym
= XCAR (color_symbols
);
3643 || !STRINGP (XCAR (sym
))
3644 || !STRINGP (XCDR (sym
)))
3646 color_symbols
= XCDR (color_symbols
);
3649 return NILP (color_symbols
);
3653 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3656 xpm_image_p (object
)
3659 struct image_keyword fmt
[XPM_LAST
];
3660 bcopy (xpm_format
, fmt
, sizeof fmt
);
3661 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3662 /* Either `:file' or `:data' must be present. */
3663 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3664 /* Either no `:color-symbols' or it's a list of conses
3665 whose car and cdr are strings. */
3666 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3667 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3670 #endif /* HAVE_XPM || HAVE_NS */
3672 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3674 x_create_bitmap_from_xpm_data (f
, bits
)
3678 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3680 XpmAttributes attrs
;
3681 Pixmap bitmap
, mask
;
3683 bzero (&attrs
, sizeof attrs
);
3685 attrs
.visual
= FRAME_X_VISUAL (f
);
3686 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3687 attrs
.valuemask
|= XpmVisual
;
3688 attrs
.valuemask
|= XpmColormap
;
3690 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3691 bits
, &bitmap
, &mask
, &attrs
);
3692 if (rc
!= XpmSuccess
)
3694 XpmFreeAttributes (&attrs
);
3698 id
= x_allocate_bitmap_record (f
);
3699 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3700 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3701 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3702 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3703 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3704 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3705 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3706 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3708 XpmFreeAttributes (&attrs
);
3711 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3713 /* Load image IMG which will be displayed on frame F. Value is
3714 non-zero if successful. */
3724 XpmAttributes attrs
;
3725 Lisp_Object specified_file
, color_symbols
;
3728 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3729 #endif /* HAVE_NTGUI */
3731 /* Configure the XPM lib. Use the visual of frame F. Allocate
3732 close colors. Return colors allocated. */
3733 bzero (&attrs
, sizeof attrs
);
3736 attrs
.visual
= FRAME_X_VISUAL (f
);
3737 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3738 attrs
.valuemask
|= XpmVisual
;
3739 attrs
.valuemask
|= XpmColormap
;
3740 #endif /* HAVE_NTGUI */
3742 #ifdef ALLOC_XPM_COLORS
3743 /* Allocate colors with our own functions which handle
3744 failing color allocation more gracefully. */
3745 attrs
.color_closure
= f
;
3746 attrs
.alloc_color
= xpm_alloc_color
;
3747 attrs
.free_colors
= xpm_free_colors
;
3748 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3749 #else /* not ALLOC_XPM_COLORS */
3750 /* Let the XPM lib allocate colors. */
3751 attrs
.valuemask
|= XpmReturnAllocPixels
;
3752 #ifdef XpmAllocCloseColors
3753 attrs
.alloc_close_colors
= 1;
3754 attrs
.valuemask
|= XpmAllocCloseColors
;
3755 #else /* not XpmAllocCloseColors */
3756 attrs
.closeness
= 600;
3757 attrs
.valuemask
|= XpmCloseness
;
3758 #endif /* not XpmAllocCloseColors */
3759 #endif /* ALLOC_XPM_COLORS */
3761 /* If image specification contains symbolic color definitions, add
3762 these to `attrs'. */
3763 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3764 if (CONSP (color_symbols
))
3767 XpmColorSymbol
*xpm_syms
;
3770 attrs
.valuemask
|= XpmColorSymbols
;
3772 /* Count number of symbols. */
3773 attrs
.numsymbols
= 0;
3774 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3777 /* Allocate an XpmColorSymbol array. */
3778 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3779 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3780 bzero (xpm_syms
, size
);
3781 attrs
.colorsymbols
= xpm_syms
;
3783 /* Fill the color symbol array. */
3784 for (tail
= color_symbols
, i
= 0;
3786 ++i
, tail
= XCDR (tail
))
3788 Lisp_Object name
= XCAR (XCAR (tail
));
3789 Lisp_Object color
= XCDR (XCAR (tail
));
3790 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3791 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3792 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3793 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3797 /* Create a pixmap for the image, either from a file, or from a
3798 string buffer containing data in the same format as an XPM file. */
3799 #ifdef ALLOC_XPM_COLORS
3800 xpm_init_color_cache (f
, &attrs
);
3803 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3807 HDC frame_dc
= get_frame_dc (f
);
3808 hdc
= CreateCompatibleDC (frame_dc
);
3809 release_frame_dc (f
, frame_dc
);
3811 #endif /* HAVE_NTGUI */
3813 if (STRINGP (specified_file
))
3815 Lisp_Object file
= x_find_image_file (specified_file
);
3816 if (!STRINGP (file
))
3818 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3823 /* XpmReadFileToPixmap is not available in the Windows port of
3824 libxpm. But XpmReadFileToImage almost does what we want. */
3825 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3826 &xpm_image
, &xpm_mask
,
3829 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3830 SDATA (file
), &img
->pixmap
, &img
->mask
,
3832 #endif /* HAVE_NTGUI */
3836 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3838 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3839 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3840 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3841 &xpm_image
, &xpm_mask
,
3844 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3846 &img
->pixmap
, &img
->mask
,
3848 #endif /* HAVE_NTGUI */
3851 if (rc
== XpmSuccess
)
3853 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3854 img
->colors
= colors_in_color_table (&img
->ncolors
);
3855 #else /* not ALLOC_XPM_COLORS */
3859 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3860 plus some duplicate attributes. */
3861 if (xpm_image
&& xpm_image
->bitmap
)
3863 img
->pixmap
= xpm_image
->bitmap
;
3864 /* XImageFree in libXpm frees XImage struct without destroying
3865 the bitmap, which is what we want. */
3866 fn_XImageFree (xpm_image
);
3868 if (xpm_mask
&& xpm_mask
->bitmap
)
3870 /* The mask appears to be inverted compared with what we expect.
3871 TODO: invert our expectations. See other places where we
3872 have to invert bits because our idea of masks is backwards. */
3874 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3876 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3877 SelectObject (hdc
, old_obj
);
3879 img
->mask
= xpm_mask
->bitmap
;
3880 fn_XImageFree (xpm_mask
);
3885 #endif /* HAVE_NTGUI */
3887 /* Remember allocated colors. */
3888 img
->ncolors
= attrs
.nalloc_pixels
;
3889 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3890 * sizeof *img
->colors
);
3891 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3893 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3894 #ifdef DEBUG_X_COLORS
3895 register_color (img
->colors
[i
]);
3898 #endif /* not ALLOC_XPM_COLORS */
3900 img
->width
= attrs
.width
;
3901 img
->height
= attrs
.height
;
3902 xassert (img
->width
> 0 && img
->height
> 0);
3904 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3906 fn_XpmFreeAttributes (&attrs
);
3908 XpmFreeAttributes (&attrs
);
3909 #endif /* HAVE_NTGUI */
3915 #endif /* HAVE_NTGUI */
3920 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3923 case XpmFileInvalid
:
3924 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3928 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3931 case XpmColorFailed
:
3932 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3936 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3941 #ifdef ALLOC_XPM_COLORS
3942 xpm_free_color_cache ();
3944 return rc
== XpmSuccess
;
3947 #endif /* HAVE_XPM */
3949 #if defined (HAVE_NS) && !defined (HAVE_XPM)
3951 /* XPM support functions for NS where libxpm is not available.
3952 Only XPM version 3 (without any extensions) is supported. */
3954 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
3955 const unsigned char **, int *));
3956 static Lisp_Object xpm_make_color_table_v
3957 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3958 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3959 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
3961 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3962 const unsigned char *, int));
3963 static Lisp_Object xpm_make_color_table_h
3964 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3965 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3966 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
3968 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3969 const unsigned char *, int));
3970 static int xpm_str_to_color_key
P_ ((const char *));
3971 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3972 const unsigned char *, const unsigned char *));
3974 /* Tokens returned from xpm_scan. */
3983 /* Scan an XPM data and return a character (< 256) or a token defined
3984 by enum xpm_token above. *S and END are the start (inclusive) and
3985 the end (exclusive) addresses of the data, respectively. Advance
3986 *S while scanning. If token is either XPM_TK_IDENT or
3987 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3988 length of the corresponding token, respectively. */
3991 xpm_scan (s
, end
, beg
, len
)
3992 const unsigned char **s
, *end
, **beg
;
3999 /* Skip white-space. */
4000 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4003 /* gnus-pointer.xpm uses '-' in its identifier.
4004 sb-dir-plus.xpm uses '+' in its identifier. */
4005 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4009 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4012 return XPM_TK_IDENT
;
4017 while (*s
< end
&& **s
!= '"')
4022 return XPM_TK_STRING
;
4026 if (*s
< end
&& **s
== '*')
4028 /* C-style comment. */
4032 while (*s
< end
&& *(*s
)++ != '*')
4035 while (*s
< end
&& **s
!= '/');
4049 /* Functions for color table lookup in XPM data. A key is a string
4050 specifying the color of each pixel in XPM data. A value is either
4051 an integer that specifies a pixel color, Qt that specifies
4052 transparency, or Qnil for the unspecified color. If the length of
4053 the key string is one, a vector is used as a table. Otherwise, a
4054 hash table is used. */
4057 xpm_make_color_table_v (put_func
, get_func
)
4058 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4059 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4061 *put_func
= xpm_put_color_table_v
;
4062 *get_func
= xpm_get_color_table_v
;
4063 return Fmake_vector (make_number (256), Qnil
);
4067 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4068 Lisp_Object color_table
;
4069 const unsigned char *chars_start
;
4073 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4077 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4078 Lisp_Object color_table
;
4079 const unsigned char *chars_start
;
4082 return XVECTOR (color_table
)->contents
[*chars_start
];
4086 xpm_make_color_table_h (put_func
, get_func
)
4087 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4088 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4090 *put_func
= xpm_put_color_table_h
;
4091 *get_func
= xpm_get_color_table_h
;
4092 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4093 make_float (DEFAULT_REHASH_SIZE
),
4094 make_float (DEFAULT_REHASH_THRESHOLD
),
4099 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4100 Lisp_Object color_table
;
4101 const unsigned char *chars_start
;
4105 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4107 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4109 hash_lookup (table
, chars
, &hash_code
);
4110 hash_put (table
, chars
, color
, hash_code
);
4114 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4115 Lisp_Object color_table
;
4116 const unsigned char *chars_start
;
4119 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4120 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4123 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4126 enum xpm_color_key
{
4134 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4137 xpm_str_to_color_key (s
)
4143 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4145 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4151 xpm_load_image (f
, img
, contents
, end
)
4154 const unsigned char *contents
, *end
;
4156 const unsigned char *s
= contents
, *beg
, *str
;
4157 unsigned char buffer
[BUFSIZ
];
4158 int width
, height
, x
, y
;
4159 int num_colors
, chars_per_pixel
;
4161 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4162 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4163 Lisp_Object frame
, color_symbols
, color_table
;
4164 int best_key
, have_mask
= 0;
4165 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4168 LA1 = xpm_scan (&s, end, &beg, &len)
4170 #define expect(TOKEN) \
4171 if (LA1 != (TOKEN)) \
4176 #define expect_ident(IDENT) \
4177 if (LA1 == XPM_TK_IDENT \
4178 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4183 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4187 expect_ident ("static");
4188 expect_ident ("char");
4190 expect (XPM_TK_IDENT
);
4195 expect (XPM_TK_STRING
);
4198 memcpy (buffer
, beg
, len
);
4200 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4201 &num_colors
, &chars_per_pixel
) != 4
4202 || width
<= 0 || height
<= 0
4203 || num_colors
<= 0 || chars_per_pixel
<= 0)
4206 if (!check_image_size (f
, width
, height
))
4208 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
4214 XSETFRAME (frame
, f
);
4215 if (!NILP (Fxw_display_color_p (frame
)))
4216 best_key
= XPM_COLOR_KEY_C
;
4217 else if (!NILP (Fx_display_grayscale_p (frame
)))
4218 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4219 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4221 best_key
= XPM_COLOR_KEY_M
;
4223 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4224 if (chars_per_pixel
== 1)
4225 color_table
= xpm_make_color_table_v (&put_color_table
,
4228 color_table
= xpm_make_color_table_h (&put_color_table
,
4231 while (num_colors
-- > 0)
4233 unsigned char *color
, *max_color
;
4234 int key
, next_key
, max_key
= 0;
4235 Lisp_Object symbol_color
= Qnil
, color_val
;
4238 expect (XPM_TK_STRING
);
4239 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4241 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4242 buffer
[len
- chars_per_pixel
] = '\0';
4244 str
= strtok (buffer
, " \t");
4247 key
= xpm_str_to_color_key (str
);
4252 color
= strtok (NULL
, " \t");
4256 while ((str
= strtok (NULL
, " \t")) != NULL
)
4258 next_key
= xpm_str_to_color_key (str
);
4261 color
[strlen (color
)] = ' ';
4264 if (key
== XPM_COLOR_KEY_S
)
4266 if (NILP (symbol_color
))
4267 symbol_color
= build_string (color
);
4269 else if (max_key
< key
&& key
<= best_key
)
4279 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4281 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4283 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4285 if (xstrcasecmp (SDATA (XCDR (specified_color
)), "None") == 0)
4287 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4289 color_val
= make_number (cdef
.pixel
);
4292 if (NILP (color_val
) && max_key
> 0)
4294 if (xstrcasecmp (max_color
, "None") == 0)
4296 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4297 color_val
= make_number (cdef
.pixel
);
4299 if (!NILP (color_val
))
4300 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4305 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4306 &ximg
, &img
->pixmap
)
4308 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4309 &mask_img
, &img
->mask
)
4313 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4317 for (y
= 0; y
< height
; y
++)
4319 expect (XPM_TK_STRING
);
4321 if (len
< width
* chars_per_pixel
)
4323 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4325 Lisp_Object color_val
=
4326 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4328 XPutPixel (ximg
, x
, y
,
4329 (INTEGERP (color_val
) ? XINT (color_val
)
4330 : FRAME_FOREGROUND_PIXEL (f
)));
4332 XPutPixel (mask_img
, x
, y
,
4333 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4334 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4336 if (EQ(color_val
, Qt
))
4337 ns_set_alpha(ximg
, x
, y
, 0);
4345 img
->height
= height
;
4347 /* Maybe fill in the background field while we have ximg handy. */
4348 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4349 IMAGE_BACKGROUND (img
, f
, ximg
);
4351 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4352 x_destroy_x_image (ximg
);
4356 /* Fill in the background_transparent field while we have the
4358 image_background_transparent (img
, f
, mask_img
);
4360 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4361 x_destroy_x_image (mask_img
);
4365 x_destroy_x_image (mask_img
);
4366 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4367 img
->mask
= NO_PIXMAP
;
4373 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4375 x_destroy_x_image (ximg
);
4376 x_destroy_x_image (mask_img
);
4377 x_clear_image (f
, img
);
4391 Lisp_Object file_name
;
4393 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4394 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4395 if (STRINGP (file_name
))
4398 unsigned char *contents
;
4400 struct gcpro gcpro1
;
4402 file
= x_find_image_file (file_name
);
4404 if (!STRINGP (file
))
4406 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4411 contents
= slurp_file (SDATA (file
), &size
);
4412 if (contents
== NULL
)
4414 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4419 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4427 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4428 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4429 SDATA (data
) + SBYTES (data
));
4435 #endif /* HAVE_NS && !HAVE_XPM */
4439 /***********************************************************************
4441 ***********************************************************************/
4443 #ifdef COLOR_TABLE_SUPPORT
4445 /* An entry in the color table mapping an RGB color to a pixel color. */
4450 unsigned long pixel
;
4452 /* Next in color table collision list. */
4453 struct ct_color
*next
;
4456 /* The bucket vector size to use. Must be prime. */
4460 /* Value is a hash of the RGB color given by R, G, and B. */
4462 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4464 /* The color hash table. */
4466 struct ct_color
**ct_table
;
4468 /* Number of entries in the color table. */
4470 int ct_colors_allocated
;
4472 /* Initialize the color table. */
4477 int size
= CT_SIZE
* sizeof (*ct_table
);
4478 ct_table
= (struct ct_color
**) xmalloc (size
);
4479 bzero (ct_table
, size
);
4480 ct_colors_allocated
= 0;
4484 /* Free memory associated with the color table. */
4490 struct ct_color
*p
, *next
;
4492 for (i
= 0; i
< CT_SIZE
; ++i
)
4493 for (p
= ct_table
[i
]; p
; p
= next
)
4504 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4505 entry for that color already is in the color table, return the
4506 pixel color of that entry. Otherwise, allocate a new color for R,
4507 G, B, and make an entry in the color table. */
4509 static unsigned long
4510 lookup_rgb_color (f
, r
, g
, b
)
4514 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4515 int i
= hash
% CT_SIZE
;
4517 Display_Info
*dpyinfo
;
4519 /* Handle TrueColor visuals specially, which improves performance by
4520 two orders of magnitude. Freeing colors on TrueColor visuals is
4521 a nop, and pixel colors specify RGB values directly. See also
4522 the Xlib spec, chapter 3.1. */
4523 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4524 if (dpyinfo
->red_bits
> 0)
4526 unsigned long pr
, pg
, pb
;
4528 /* Apply gamma-correction like normal color allocation does. */
4532 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4533 gamma_correct (f
, &color
);
4534 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4537 /* Scale down RGB values to the visual's bits per RGB, and shift
4538 them to the right position in the pixel color. Note that the
4539 original RGB values are 16-bit values, as usual in X. */
4540 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4541 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4542 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4544 /* Assemble the pixel color. */
4545 return pr
| pg
| pb
;
4548 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4549 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4555 #ifdef HAVE_X_WINDOWS
4564 cmap
= FRAME_X_COLORMAP (f
);
4565 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4568 ++ct_colors_allocated
;
4569 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4573 p
->pixel
= color
.pixel
;
4574 p
->next
= ct_table
[i
];
4578 return FRAME_FOREGROUND_PIXEL (f
);
4583 color
= PALETTERGB (r
, g
, b
);
4585 color
= RGB_TO_ULONG (r
, g
, b
);
4586 #endif /* HAVE_NTGUI */
4587 ++ct_colors_allocated
;
4588 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4593 p
->next
= ct_table
[i
];
4595 #endif /* HAVE_X_WINDOWS */
4603 /* Look up pixel color PIXEL which is used on frame F in the color
4604 table. If not already present, allocate it. Value is PIXEL. */
4606 static unsigned long
4607 lookup_pixel_color (f
, pixel
)
4609 unsigned long pixel
;
4611 int i
= pixel
% CT_SIZE
;
4614 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4615 if (p
->pixel
== pixel
)
4624 #ifdef HAVE_X_WINDOWS
4625 cmap
= FRAME_X_COLORMAP (f
);
4626 color
.pixel
= pixel
;
4627 x_query_color (f
, &color
);
4628 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4631 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4632 color
.pixel
= pixel
;
4633 XQueryColor (NULL
, cmap
, &color
);
4634 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4636 #endif /* HAVE_X_WINDOWS */
4640 ++ct_colors_allocated
;
4642 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4647 p
->next
= ct_table
[i
];
4651 return FRAME_FOREGROUND_PIXEL (f
);
4657 /* Value is a vector of all pixel colors contained in the color table,
4658 allocated via xmalloc. Set *N to the number of colors. */
4660 static unsigned long *
4661 colors_in_color_table (n
)
4666 unsigned long *colors
;
4668 if (ct_colors_allocated
== 0)
4675 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4677 *n
= ct_colors_allocated
;
4679 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4680 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4681 colors
[j
++] = p
->pixel
;
4687 #else /* COLOR_TABLE_SUPPORT */
4689 static unsigned long
4690 lookup_rgb_color (f
, r
, g
, b
)
4694 unsigned long pixel
;
4697 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4698 #endif /* HAVE_NTGUI */
4701 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4702 #endif /* HAVE_NS */
4710 #endif /* COLOR_TABLE_SUPPORT */
4713 /***********************************************************************
4715 ***********************************************************************/
4717 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4718 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4719 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4722 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4723 #endif /* HAVE_NTGUI */
4725 /* Non-zero means draw a cross on images having `:conversion
4728 int cross_disabled_images
;
4730 /* Edge detection matrices for different edge-detection
4733 static int emboss_matrix
[9] = {
4735 2, -1, 0, /* y - 1 */
4737 0, 1, -2 /* y + 1 */
4740 static int laplace_matrix
[9] = {
4742 1, 0, 0, /* y - 1 */
4744 0, 0, -1 /* y + 1 */
4747 /* Value is the intensity of the color whose red/green/blue values
4750 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4753 /* On frame F, return an array of XColor structures describing image
4754 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4755 non-zero means also fill the red/green/blue members of the XColor
4756 structures. Value is a pointer to the array of XColors structures,
4757 allocated with xmalloc; it must be freed by the caller. */
4760 x_to_xcolors (f
, img
, rgb_p
)
4767 XImagePtr_or_DC ximg
;
4771 #endif /* HAVE_NTGUI */
4773 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4776 /* Get the X image IMG->pixmap. */
4777 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4778 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4780 /* Load the image into a memory device context. */
4781 hdc
= get_frame_dc (f
);
4782 ximg
= CreateCompatibleDC (hdc
);
4783 release_frame_dc (f
, hdc
);
4784 prev
= SelectObject (ximg
, img
->pixmap
);
4785 #endif /* HAVE_NTGUI */
4787 /* Fill the `pixel' members of the XColor array. I wished there
4788 were an easy and portable way to circumvent XGetPixel. */
4790 for (y
= 0; y
< img
->height
; ++y
)
4794 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4795 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4796 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4798 x_query_colors (f
, row
, img
->width
);
4802 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4804 /* W32_TODO: palette support needed here? */
4805 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4808 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4809 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4810 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4813 #endif /* HAVE_X_WINDOWS */
4816 Destroy_Image (ximg
, prev
);
4823 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4824 created with CreateDIBSection, with the pointer to the bit values
4825 stored in ximg->data. */
4828 XPutPixel (ximg
, x
, y
, color
)
4833 int width
= ximg
->info
.bmiHeader
.biWidth
;
4834 int height
= ximg
->info
.bmiHeader
.biHeight
;
4835 unsigned char * pixel
;
4837 /* True color images. */
4838 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4840 int rowbytes
= width
* 3;
4841 /* Ensure scanlines are aligned on 4 byte boundaries. */
4843 rowbytes
+= 4 - (rowbytes
% 4);
4845 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4846 /* Windows bitmaps are in BGR order. */
4847 *pixel
= GetBValue (color
);
4848 *(pixel
+ 1) = GetGValue (color
);
4849 *(pixel
+ 2) = GetRValue (color
);
4851 /* Monochrome images. */
4852 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4854 int rowbytes
= width
/ 8;
4855 /* Ensure scanlines are aligned on 4 byte boundaries. */
4857 rowbytes
+= 4 - (rowbytes
% 4);
4858 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4859 /* Filter out palette info. */
4860 if (color
& 0x00ffffff)
4861 *pixel
= *pixel
| (1 << x
% 8);
4863 *pixel
= *pixel
& ~(1 << x
% 8);
4866 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4869 #endif /* HAVE_NTGUI */
4871 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4872 RGB members are set. F is the frame on which this all happens.
4873 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4876 x_from_xcolors (f
, img
, colors
)
4882 XImagePtr oimg
= NULL
;
4886 init_color_table ();
4888 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4891 for (y
= 0; y
< img
->height
; ++y
)
4892 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4894 unsigned long pixel
;
4895 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4896 XPutPixel (oimg
, x
, y
, pixel
);
4900 x_clear_image_1 (f
, img
, 1, 0, 1);
4902 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4903 x_destroy_x_image (oimg
);
4904 img
->pixmap
= pixmap
;
4905 #ifdef COLOR_TABLE_SUPPORT
4906 img
->colors
= colors_in_color_table (&img
->ncolors
);
4907 free_color_table ();
4908 #endif /* COLOR_TABLE_SUPPORT */
4912 /* On frame F, perform edge-detection on image IMG.
4914 MATRIX is a nine-element array specifying the transformation
4915 matrix. See emboss_matrix for an example.
4917 COLOR_ADJUST is a color adjustment added to each pixel of the
4921 x_detect_edges (f
, img
, matrix
, color_adjust
)
4924 int matrix
[9], color_adjust
;
4926 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4930 for (i
= sum
= 0; i
< 9; ++i
)
4931 sum
+= eabs (matrix
[i
]);
4933 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4935 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4937 for (y
= 0; y
< img
->height
; ++y
)
4939 p
= COLOR (new, 0, y
);
4940 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4941 p
= COLOR (new, img
->width
- 1, y
);
4942 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4945 for (x
= 1; x
< img
->width
- 1; ++x
)
4947 p
= COLOR (new, x
, 0);
4948 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4949 p
= COLOR (new, x
, img
->height
- 1);
4950 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4953 for (y
= 1; y
< img
->height
- 1; ++y
)
4955 p
= COLOR (new, 1, y
);
4957 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4959 int r
, g
, b
, y1
, x1
;
4962 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4963 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4966 XColor
*t
= COLOR (colors
, x1
, y1
);
4967 r
+= matrix
[i
] * t
->red
;
4968 g
+= matrix
[i
] * t
->green
;
4969 b
+= matrix
[i
] * t
->blue
;
4972 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4973 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4974 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4975 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4980 x_from_xcolors (f
, img
, new);
4986 /* Perform the pre-defined `emboss' edge-detection on image IMG
4994 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4998 /* Transform image IMG which is used on frame F with a Laplace
4999 edge-detection algorithm. The result is an image that can be used
5000 to draw disabled buttons, for example. */
5007 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5011 /* Perform edge-detection on image IMG on frame F, with specified
5012 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5014 MATRIX must be either
5016 - a list of at least 9 numbers in row-major form
5017 - a vector of at least 9 numbers
5019 COLOR_ADJUST nil means use a default; otherwise it must be a
5023 x_edge_detection (f
, img
, matrix
, color_adjust
)
5026 Lisp_Object matrix
, color_adjust
;
5034 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5035 ++i
, matrix
= XCDR (matrix
))
5036 trans
[i
] = XFLOATINT (XCAR (matrix
));
5038 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5040 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5041 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5044 if (NILP (color_adjust
))
5045 color_adjust
= make_number (0xffff / 2);
5047 if (i
== 9 && NUMBERP (color_adjust
))
5048 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5052 /* Transform image IMG on frame F so that it looks disabled. */
5055 x_disable_image (f
, img
)
5059 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5061 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5063 int n_planes
= dpyinfo
->n_planes
;
5064 #endif /* HAVE_NTGUI */
5068 /* Color (or grayscale). Convert to gray, and equalize. Just
5069 drawing such images with a stipple can look very odd, so
5070 we're using this method instead. */
5071 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5073 const int h
= 15000;
5074 const int l
= 30000;
5076 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5080 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5081 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5082 p
->red
= p
->green
= p
->blue
= i2
;
5085 x_from_xcolors (f
, img
, colors
);
5088 /* Draw a cross over the disabled image, if we must or if we
5090 if (n_planes
< 2 || cross_disabled_images
)
5093 Display
*dpy
= FRAME_X_DISPLAY (f
);
5096 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5098 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5100 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5101 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5102 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5103 img
->width
- 1, img
->height
- 1);
5104 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5110 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5111 XSetForeground (dpy
, gc
, MaskForeground (f
));
5112 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5113 img
->width
- 1, img
->height
- 1);
5114 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5118 #endif /* !HAVE_NS */
5123 hdc
= get_frame_dc (f
);
5124 bmpdc
= CreateCompatibleDC (hdc
);
5125 release_frame_dc (f
, hdc
);
5127 prev
= SelectObject (bmpdc
, img
->pixmap
);
5129 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5130 MoveToEx (bmpdc
, 0, 0, NULL
);
5131 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5132 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5133 LineTo (bmpdc
, img
->width
- 1, 0);
5137 SelectObject (bmpdc
, img
->mask
);
5138 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5139 MoveToEx (bmpdc
, 0, 0, NULL
);
5140 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5141 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5142 LineTo (bmpdc
, img
->width
- 1, 0);
5144 SelectObject (bmpdc
, prev
);
5146 #endif /* HAVE_NTGUI */
5151 /* Build a mask for image IMG which is used on frame F. FILE is the
5152 name of an image file, for error messages. HOW determines how to
5153 determine the background color of IMG. If it is a list '(R G B)',
5154 with R, G, and B being integers >= 0, take that as the color of the
5155 background. Otherwise, determine the background color of IMG
5156 heuristically. Value is non-zero if successful. */
5159 x_build_heuristic_mask (f
, img
, how
)
5164 XImagePtr_or_DC ximg
;
5172 #endif /* HAVE_NTGUI */
5173 int x
, y
, rc
, use_img_background
;
5174 unsigned long bg
= 0;
5178 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5179 img
->mask
= NO_PIXMAP
;
5180 img
->background_transparent_valid
= 0;
5185 /* Create an image and pixmap serving as mask. */
5186 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5187 &mask_img
, &img
->mask
);
5190 #endif /* !HAVE_NS */
5192 /* Get the X image of IMG->pixmap. */
5193 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5194 img
->width
, img
->height
,
5197 /* Create the bit array serving as mask. */
5198 row_width
= (img
->width
+ 7) / 8;
5199 mask_img
= xmalloc (row_width
* img
->height
);
5200 bzero (mask_img
, row_width
* img
->height
);
5202 /* Create a memory device context for IMG->pixmap. */
5203 frame_dc
= get_frame_dc (f
);
5204 ximg
= CreateCompatibleDC (frame_dc
);
5205 release_frame_dc (f
, frame_dc
);
5206 prev
= SelectObject (ximg
, img
->pixmap
);
5207 #endif /* HAVE_NTGUI */
5209 /* Determine the background color of ximg. If HOW is `(R G B)'
5210 take that as color. Otherwise, use the image's background color. */
5211 use_img_background
= 1;
5217 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5219 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5223 if (i
== 3 && NILP (how
))
5225 char color_name
[30];
5226 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5229 0x00ffffff & /* Filter out palette info. */
5230 #endif /* HAVE_NTGUI */
5231 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5232 use_img_background
= 0;
5236 if (use_img_background
)
5237 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5239 /* Set all bits in mask_img to 1 whose color in ximg is different
5240 from the background color bg. */
5242 for (y
= 0; y
< img
->height
; ++y
)
5243 for (x
= 0; x
< img
->width
; ++x
)
5245 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5246 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5248 if (XGetPixel (ximg
, x
, y
) == bg
)
5249 ns_set_alpha(ximg
, x
, y
, 0);
5250 #endif /* HAVE_NS */
5252 /* Fill in the background_transparent field while we have the mask handy. */
5253 image_background_transparent (img
, f
, mask_img
);
5255 /* Put mask_img into img->mask. */
5256 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5257 x_destroy_x_image (mask_img
);
5258 #endif /* !HAVE_NS */
5260 for (y
= 0; y
< img
->height
; ++y
)
5261 for (x
= 0; x
< img
->width
; ++x
)
5263 COLORREF p
= GetPixel (ximg
, x
, y
);
5265 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5268 /* Create the mask image. */
5269 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5271 /* Fill in the background_transparent field while we have the mask handy. */
5272 SelectObject (ximg
, img
->mask
);
5273 image_background_transparent (img
, f
, ximg
);
5275 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5277 #endif /* HAVE_NTGUI */
5279 Destroy_Image (ximg
, prev
);
5285 /***********************************************************************
5286 PBM (mono, gray, color)
5287 ***********************************************************************/
5289 static int pbm_image_p
P_ ((Lisp_Object object
));
5290 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5291 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5293 /* The symbol `pbm' identifying images of this type. */
5297 /* Indices of image specification fields in gs_format, below. */
5299 enum pbm_keyword_index
5315 /* Vector of image_keyword structures describing the format
5316 of valid user-defined image specifications. */
5318 static struct image_keyword pbm_format
[PBM_LAST
] =
5320 {":type", IMAGE_SYMBOL_VALUE
, 1},
5321 {":file", IMAGE_STRING_VALUE
, 0},
5322 {":data", IMAGE_STRING_VALUE
, 0},
5323 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5324 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5325 {":relief", IMAGE_INTEGER_VALUE
, 0},
5326 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5327 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5328 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5329 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5330 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5333 /* Structure describing the image type `pbm'. */
5335 static struct image_type pbm_type
=
5345 /* Return non-zero if OBJECT is a valid PBM image specification. */
5348 pbm_image_p (object
)
5351 struct image_keyword fmt
[PBM_LAST
];
5353 bcopy (pbm_format
, fmt
, sizeof fmt
);
5355 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5358 /* Must specify either :data or :file. */
5359 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5363 /* Scan a decimal number from *S and return it. Advance *S while
5364 reading the number. END is the end of the string. Value is -1 at
5368 pbm_scan_number (s
, end
)
5369 unsigned char **s
, *end
;
5371 int c
= 0, val
= -1;
5375 /* Skip white-space. */
5376 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5381 /* Skip comment to end of line. */
5382 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5385 else if (isdigit (c
))
5387 /* Read decimal number. */
5389 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5390 val
= 10 * val
+ c
- '0';
5402 #if 0 /* Unused. ++kfs */
5404 /* Read FILE into memory. Value is a pointer to a buffer allocated
5405 with xmalloc holding FILE's contents. Value is null if an error
5406 occurred. *SIZE is set to the size of the file. */
5409 pbm_read_file (file
, size
)
5417 if (stat (SDATA (file
), &st
) == 0
5418 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5419 && (buf
= (char *) xmalloc (st
.st_size
),
5420 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5439 #endif /* HAVE_NTGUI */
5441 /* Load PBM image IMG for use on frame F. */
5449 int width
, height
, max_color_idx
= 0;
5451 Lisp_Object file
, specified_file
;
5452 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5453 struct gcpro gcpro1
;
5454 unsigned char *contents
= NULL
;
5455 unsigned char *end
, *p
;
5458 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5462 if (STRINGP (specified_file
))
5464 file
= x_find_image_file (specified_file
);
5465 if (!STRINGP (file
))
5467 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5472 contents
= slurp_file (SDATA (file
), &size
);
5473 if (contents
== NULL
)
5475 image_error ("Error reading `%s'", file
, Qnil
);
5481 end
= contents
+ size
;
5486 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5488 end
= p
+ SBYTES (data
);
5491 /* Check magic number. */
5492 if (end
- p
< 2 || *p
++ != 'P')
5494 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5504 raw_p
= 0, type
= PBM_MONO
;
5508 raw_p
= 0, type
= PBM_GRAY
;
5512 raw_p
= 0, type
= PBM_COLOR
;
5516 raw_p
= 1, type
= PBM_MONO
;
5520 raw_p
= 1, type
= PBM_GRAY
;
5524 raw_p
= 1, type
= PBM_COLOR
;
5528 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5532 /* Read width, height, maximum color-component. Characters
5533 starting with `#' up to the end of a line are ignored. */
5534 width
= pbm_scan_number (&p
, end
);
5535 height
= pbm_scan_number (&p
, end
);
5537 if (type
!= PBM_MONO
)
5539 max_color_idx
= pbm_scan_number (&p
, end
);
5540 if (max_color_idx
> 65535 || max_color_idx
< 0)
5542 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
5547 if (!check_image_size (f
, width
, height
))
5549 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
5553 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5554 &ximg
, &img
->pixmap
))
5557 /* Initialize the color hash table. */
5558 init_color_table ();
5560 if (type
== PBM_MONO
)
5563 struct image_keyword fmt
[PBM_LAST
];
5564 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5565 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5567 /* Parse the image specification. */
5568 bcopy (pbm_format
, fmt
, sizeof fmt
);
5569 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5571 /* Get foreground and background colors, maybe allocate colors. */
5572 if (fmt
[PBM_FOREGROUND
].count
5573 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5574 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5575 if (fmt
[PBM_BACKGROUND
].count
5576 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5578 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5579 img
->background
= bg
;
5580 img
->background_valid
= 1;
5583 for (y
= 0; y
< height
; ++y
)
5584 for (x
= 0; x
< width
; ++x
)
5592 x_destroy_x_image (ximg
);
5593 x_clear_image (f
, img
);
5594 image_error ("Invalid image size in image `%s'",
5604 g
= pbm_scan_number (&p
, end
);
5606 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5611 int expected_size
= height
* width
;
5612 if (max_color_idx
> 255)
5614 if (type
== PBM_COLOR
)
5617 if (raw_p
&& p
+ expected_size
> end
)
5619 x_destroy_x_image (ximg
);
5620 x_clear_image (f
, img
);
5621 image_error ("Invalid image size in image `%s'",
5626 for (y
= 0; y
< height
; ++y
)
5627 for (x
= 0; x
< width
; ++x
)
5631 if (type
== PBM_GRAY
&& raw_p
)
5634 if (max_color_idx
> 255)
5635 r
= g
= b
= r
* 256 + *p
++;
5637 else if (type
== PBM_GRAY
)
5638 r
= g
= b
= pbm_scan_number (&p
, end
);
5642 if (max_color_idx
> 255)
5645 if (max_color_idx
> 255)
5648 if (max_color_idx
> 255)
5653 r
= pbm_scan_number (&p
, end
);
5654 g
= pbm_scan_number (&p
, end
);
5655 b
= pbm_scan_number (&p
, end
);
5658 if (r
< 0 || g
< 0 || b
< 0)
5660 x_destroy_x_image (ximg
);
5661 image_error ("Invalid pixel value in image `%s'",
5666 /* RGB values are now in the range 0..max_color_idx.
5667 Scale this to the range 0..0xffff supported by X. */
5668 r
= (double) r
* 65535 / max_color_idx
;
5669 g
= (double) g
* 65535 / max_color_idx
;
5670 b
= (double) b
* 65535 / max_color_idx
;
5671 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5675 #ifdef COLOR_TABLE_SUPPORT
5676 /* Store in IMG->colors the colors allocated for the image, and
5677 free the color table. */
5678 img
->colors
= colors_in_color_table (&img
->ncolors
);
5679 free_color_table ();
5680 #endif /* COLOR_TABLE_SUPPORT */
5683 img
->height
= height
;
5685 /* Maybe fill in the background field while we have ximg handy. */
5687 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5688 /* Casting avoids a GCC warning. */
5689 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5691 /* Put the image into a pixmap. */
5692 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5693 x_destroy_x_image (ximg
);
5695 /* X and W32 versions did it here, MAC version above. ++kfs
5697 img->height = height; */
5705 /***********************************************************************
5707 ***********************************************************************/
5709 #if defined (HAVE_PNG) || defined (HAVE_NS)
5711 /* Function prototypes. */
5713 static int png_image_p
P_ ((Lisp_Object object
));
5714 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5716 /* The symbol `png' identifying images of this type. */
5720 /* Indices of image specification fields in png_format, below. */
5722 enum png_keyword_index
5737 /* Vector of image_keyword structures describing the format
5738 of valid user-defined image specifications. */
5740 static struct image_keyword png_format
[PNG_LAST
] =
5742 {":type", IMAGE_SYMBOL_VALUE
, 1},
5743 {":data", IMAGE_STRING_VALUE
, 0},
5744 {":file", IMAGE_STRING_VALUE
, 0},
5745 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5746 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5747 {":relief", IMAGE_INTEGER_VALUE
, 0},
5748 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5749 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5750 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5751 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5754 /* Structure describing the image type `png'. */
5756 static struct image_type png_type
=
5765 /* Return non-zero if OBJECT is a valid PNG image specification. */
5768 png_image_p (object
)
5771 struct image_keyword fmt
[PNG_LAST
];
5772 bcopy (png_format
, fmt
, sizeof fmt
);
5774 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5777 /* Must specify either the :data or :file keyword. */
5778 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5781 #endif /* HAVE_PNG || HAVE_NS */
5786 #if defined HAVE_LIBPNG_PNG_H
5787 # include <libpng/png.h>
5793 /* PNG library details. */
5795 DEF_IMGLIB_FN (png_get_io_ptr
);
5796 DEF_IMGLIB_FN (png_check_sig
);
5797 DEF_IMGLIB_FN (png_create_read_struct
);
5798 DEF_IMGLIB_FN (png_create_info_struct
);
5799 DEF_IMGLIB_FN (png_destroy_read_struct
);
5800 DEF_IMGLIB_FN (png_set_read_fn
);
5801 DEF_IMGLIB_FN (png_set_sig_bytes
);
5802 DEF_IMGLIB_FN (png_read_info
);
5803 DEF_IMGLIB_FN (png_get_IHDR
);
5804 DEF_IMGLIB_FN (png_get_valid
);
5805 DEF_IMGLIB_FN (png_set_strip_16
);
5806 DEF_IMGLIB_FN (png_set_expand
);
5807 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5808 DEF_IMGLIB_FN (png_set_background
);
5809 DEF_IMGLIB_FN (png_get_bKGD
);
5810 DEF_IMGLIB_FN (png_read_update_info
);
5811 DEF_IMGLIB_FN (png_get_channels
);
5812 DEF_IMGLIB_FN (png_get_rowbytes
);
5813 DEF_IMGLIB_FN (png_read_image
);
5814 DEF_IMGLIB_FN (png_read_end
);
5815 DEF_IMGLIB_FN (png_error
);
5818 init_png_functions (Lisp_Object libraries
)
5822 /* Try loading libpng under probable names. */
5823 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5826 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5827 LOAD_IMGLIB_FN (library
, png_check_sig
);
5828 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5829 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5830 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5831 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5832 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5833 LOAD_IMGLIB_FN (library
, png_read_info
);
5834 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5835 LOAD_IMGLIB_FN (library
, png_get_valid
);
5836 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5837 LOAD_IMGLIB_FN (library
, png_set_expand
);
5838 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5839 LOAD_IMGLIB_FN (library
, png_set_background
);
5840 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5841 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5842 LOAD_IMGLIB_FN (library
, png_get_channels
);
5843 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5844 LOAD_IMGLIB_FN (library
, png_read_image
);
5845 LOAD_IMGLIB_FN (library
, png_read_end
);
5846 LOAD_IMGLIB_FN (library
, png_error
);
5851 #define fn_png_get_io_ptr png_get_io_ptr
5852 #define fn_png_check_sig png_check_sig
5853 #define fn_png_create_read_struct png_create_read_struct
5854 #define fn_png_create_info_struct png_create_info_struct
5855 #define fn_png_destroy_read_struct png_destroy_read_struct
5856 #define fn_png_set_read_fn png_set_read_fn
5857 #define fn_png_set_sig_bytes png_set_sig_bytes
5858 #define fn_png_read_info png_read_info
5859 #define fn_png_get_IHDR png_get_IHDR
5860 #define fn_png_get_valid png_get_valid
5861 #define fn_png_set_strip_16 png_set_strip_16
5862 #define fn_png_set_expand png_set_expand
5863 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5864 #define fn_png_set_background png_set_background
5865 #define fn_png_get_bKGD png_get_bKGD
5866 #define fn_png_read_update_info png_read_update_info
5867 #define fn_png_get_channels png_get_channels
5868 #define fn_png_get_rowbytes png_get_rowbytes
5869 #define fn_png_read_image png_read_image
5870 #define fn_png_read_end png_read_end
5871 #define fn_png_error png_error
5873 #endif /* HAVE_NTGUI */
5875 /* Error and warning handlers installed when the PNG library
5879 my_png_error (png_ptr
, msg
)
5880 png_struct
*png_ptr
;
5883 xassert (png_ptr
!= NULL
);
5884 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5885 longjmp (png_ptr
->jmpbuf
, 1);
5890 my_png_warning (png_ptr
, msg
)
5891 png_struct
*png_ptr
;
5894 xassert (png_ptr
!= NULL
);
5895 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5898 /* Memory source for PNG decoding. */
5900 struct png_memory_storage
5902 unsigned char *bytes
; /* The data */
5903 size_t len
; /* How big is it? */
5904 int index
; /* Where are we? */
5908 /* Function set as reader function when reading PNG image from memory.
5909 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5910 bytes from the input to DATA. */
5913 png_read_from_memory (png_ptr
, data
, length
)
5914 png_structp png_ptr
;
5918 struct png_memory_storage
*tbr
5919 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5921 if (length
> tbr
->len
- tbr
->index
)
5922 fn_png_error (png_ptr
, "Read error");
5924 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5925 tbr
->index
= tbr
->index
+ length
;
5929 /* Function set as reader function when reading PNG image from a file.
5930 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5931 bytes from the input to DATA. */
5934 png_read_from_file (png_ptr
, data
, length
)
5935 png_structp png_ptr
;
5939 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
5941 if (fread (data
, 1, length
, fp
) < length
)
5942 fn_png_error (png_ptr
, "Read error");
5946 /* Load PNG image IMG for use on frame F. Value is non-zero if
5954 Lisp_Object file
, specified_file
;
5955 Lisp_Object specified_data
;
5957 XImagePtr ximg
, mask_img
= NULL
;
5958 struct gcpro gcpro1
;
5959 png_struct
*png_ptr
= NULL
;
5960 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5961 FILE *volatile fp
= NULL
;
5963 png_byte
* volatile pixels
= NULL
;
5964 png_byte
** volatile rows
= NULL
;
5965 png_uint_32 width
, height
;
5966 int bit_depth
, color_type
, interlace_type
;
5968 png_uint_32 row_bytes
;
5970 struct png_memory_storage tbr
; /* Data to be read */
5972 /* Find out what file to load. */
5973 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5974 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5978 if (NILP (specified_data
))
5980 file
= x_find_image_file (specified_file
);
5981 if (!STRINGP (file
))
5983 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5988 /* Open the image file. */
5989 fp
= fopen (SDATA (file
), "rb");
5992 image_error ("Cannot open image file `%s'", file
, Qnil
);
5997 /* Check PNG signature. */
5998 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5999 || !fn_png_check_sig (sig
, sizeof sig
))
6001 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6009 /* Read from memory. */
6010 tbr
.bytes
= SDATA (specified_data
);
6011 tbr
.len
= SBYTES (specified_data
);
6014 /* Check PNG signature. */
6015 if (tbr
.len
< sizeof sig
6016 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6018 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6023 /* Need to skip past the signature. */
6024 tbr
.bytes
+= sizeof (sig
);
6027 /* Initialize read and info structs for PNG lib. Casting return
6028 value avoids a GCC warning on W32. */
6029 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6034 if (fp
) fclose (fp
);
6039 /* Casting return value avoids a GCC warning on W32. */
6040 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6043 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6044 if (fp
) fclose (fp
);
6049 /* Casting return value avoids a GCC warning on W32. */
6050 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6053 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6054 if (fp
) fclose (fp
);
6059 /* Set error jump-back. We come back here when the PNG library
6060 detects an error. */
6061 if (setjmp (png_ptr
->jmpbuf
))
6065 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6068 if (fp
) fclose (fp
);
6073 /* Read image info. */
6074 if (!NILP (specified_data
))
6075 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6077 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6079 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6080 fn_png_read_info (png_ptr
, info_ptr
);
6081 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6082 &interlace_type
, NULL
, NULL
);
6084 if (!check_image_size (f
, width
, height
))
6086 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
6089 /* If image contains simply transparency data, we prefer to
6090 construct a clipping mask. */
6091 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6096 /* This function is easier to write if we only have to handle
6097 one data format: RGB or RGBA with 8 bits per channel. Let's
6098 transform other formats into that format. */
6100 /* Strip more than 8 bits per channel. */
6101 if (bit_depth
== 16)
6102 fn_png_set_strip_16 (png_ptr
);
6104 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6106 fn_png_set_expand (png_ptr
);
6108 /* Convert grayscale images to RGB. */
6109 if (color_type
== PNG_COLOR_TYPE_GRAY
6110 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6111 fn_png_set_gray_to_rgb (png_ptr
);
6113 /* Handle alpha channel by combining the image with a background
6114 color. Do this only if a real alpha channel is supplied. For
6115 simple transparency, we prefer a clipping mask. */
6118 /* png_color_16 *image_bg; */
6119 Lisp_Object specified_bg
6120 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6121 int shift
= (bit_depth
== 16) ? 0 : 8;
6123 if (STRINGP (specified_bg
))
6124 /* The user specified `:background', use that. */
6127 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6129 png_color_16 user_bg
;
6131 bzero (&user_bg
, sizeof user_bg
);
6132 user_bg
.red
= color
.red
>> shift
;
6133 user_bg
.green
= color
.green
>> shift
;
6134 user_bg
.blue
= color
.blue
>> shift
;
6136 fn_png_set_background (png_ptr
, &user_bg
,
6137 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6142 /* We use the current frame background, ignoring any default
6143 background color set by the image. */
6144 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
6146 png_color_16 frame_background
;
6148 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6149 x_query_color (f
, &color
);
6151 bzero (&frame_background
, sizeof frame_background
);
6152 frame_background
.red
= color
.red
>> shift
;
6153 frame_background
.green
= color
.green
>> shift
;
6154 frame_background
.blue
= color
.blue
>> shift
;
6155 #endif /* HAVE_X_WINDOWS */
6157 fn_png_set_background (png_ptr
, &frame_background
,
6158 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6162 /* Update info structure. */
6163 fn_png_read_update_info (png_ptr
, info_ptr
);
6165 /* Get number of channels. Valid values are 1 for grayscale images
6166 and images with a palette, 2 for grayscale images with transparency
6167 information (alpha channel), 3 for RGB images, and 4 for RGB
6168 images with alpha channel, i.e. RGBA. If conversions above were
6169 sufficient we should only have 3 or 4 channels here. */
6170 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6171 xassert (channels
== 3 || channels
== 4);
6173 /* Number of bytes needed for one row of the image. */
6174 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6176 /* Allocate memory for the image. */
6177 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6178 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6179 for (i
= 0; i
< height
; ++i
)
6180 rows
[i
] = pixels
+ i
* row_bytes
;
6182 /* Read the entire image. */
6183 fn_png_read_image (png_ptr
, rows
);
6184 fn_png_read_end (png_ptr
, info_ptr
);
6191 /* Create the X image and pixmap. */
6192 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6196 /* Create an image and pixmap serving as mask if the PNG image
6197 contains an alpha channel. */
6200 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6201 &mask_img
, &img
->mask
))
6203 x_destroy_x_image (ximg
);
6204 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6205 img
->pixmap
= NO_PIXMAP
;
6209 /* Fill the X image and mask from PNG data. */
6210 init_color_table ();
6212 for (y
= 0; y
< height
; ++y
)
6214 png_byte
*p
= rows
[y
];
6216 for (x
= 0; x
< width
; ++x
)
6223 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6224 /* An alpha channel, aka mask channel, associates variable
6225 transparency with an image. Where other image formats
6226 support binary transparency---fully transparent or fully
6227 opaque---PNG allows up to 254 levels of partial transparency.
6228 The PNG library implements partial transparency by combining
6229 the image with a specified background color.
6231 I'm not sure how to handle this here nicely: because the
6232 background on which the image is displayed may change, for
6233 real alpha channel support, it would be necessary to create
6234 a new image for each possible background.
6236 What I'm doing now is that a mask is created if we have
6237 boolean transparency information. Otherwise I'm using
6238 the frame's background color to combine the image with. */
6243 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6249 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6250 /* Set IMG's background color from the PNG image, unless the user
6254 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6256 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6257 img
->background_valid
= 1;
6261 #ifdef COLOR_TABLE_SUPPORT
6262 /* Remember colors allocated for this image. */
6263 img
->colors
= colors_in_color_table (&img
->ncolors
);
6264 free_color_table ();
6265 #endif /* COLOR_TABLE_SUPPORT */
6268 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6273 img
->height
= height
;
6275 /* Maybe fill in the background field while we have ximg handy.
6276 Casting avoids a GCC warning. */
6277 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6279 /* Put the image into the pixmap, then free the X image and its buffer. */
6280 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6281 x_destroy_x_image (ximg
);
6283 /* Same for the mask. */
6286 /* Fill in the background_transparent field while we have the
6287 mask handy. Casting avoids a GCC warning. */
6288 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6290 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6291 x_destroy_x_image (mask_img
);
6298 #else /* HAVE_PNG */
6302 png_load (struct frame
*f
, struct image
*img
)
6304 return ns_load_image(f
, img
,
6305 image_spec_value (img
->spec
, QCfile
, NULL
),
6306 image_spec_value (img
->spec
, QCdata
, NULL
));
6308 #endif /* HAVE_NS */
6311 #endif /* !HAVE_PNG */
6315 /***********************************************************************
6317 ***********************************************************************/
6319 #if defined (HAVE_JPEG) || defined (HAVE_NS)
6321 static int jpeg_image_p
P_ ((Lisp_Object object
));
6322 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6324 /* The symbol `jpeg' identifying images of this type. */
6328 /* Indices of image specification fields in gs_format, below. */
6330 enum jpeg_keyword_index
6339 JPEG_HEURISTIC_MASK
,
6345 /* Vector of image_keyword structures describing the format
6346 of valid user-defined image specifications. */
6348 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6350 {":type", IMAGE_SYMBOL_VALUE
, 1},
6351 {":data", IMAGE_STRING_VALUE
, 0},
6352 {":file", IMAGE_STRING_VALUE
, 0},
6353 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6354 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6355 {":relief", IMAGE_INTEGER_VALUE
, 0},
6356 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6357 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6358 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6359 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6362 /* Structure describing the image type `jpeg'. */
6364 static struct image_type jpeg_type
=
6373 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6376 jpeg_image_p (object
)
6379 struct image_keyword fmt
[JPEG_LAST
];
6381 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6383 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6386 /* Must specify either the :data or :file keyword. */
6387 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6390 #endif /* HAVE_JPEG || HAVE_NS */
6394 /* Work around a warning about HAVE_STDLIB_H being redefined in
6396 #ifdef HAVE_STDLIB_H
6397 #define HAVE_STDLIB_H_1
6398 #undef HAVE_STDLIB_H
6399 #endif /* HAVE_STLIB_H */
6401 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6402 /* In older releases of the jpeg library, jpeglib.h will define boolean
6403 differently depending on __WIN32__, so make sure it is defined. */
6407 #include <jpeglib.h>
6411 #ifdef HAVE_STLIB_H_1
6412 #define HAVE_STDLIB_H 1
6417 /* JPEG library details. */
6418 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6419 DEF_IMGLIB_FN (jpeg_start_decompress
);
6420 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6421 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6422 DEF_IMGLIB_FN (jpeg_read_header
);
6423 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6424 DEF_IMGLIB_FN (jpeg_std_error
);
6425 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6428 init_jpeg_functions (Lisp_Object libraries
)
6432 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6435 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6436 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6437 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6438 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6439 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6440 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6441 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6442 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6446 /* Wrapper since we can't directly assign the function pointer
6447 to another function pointer that was declared more completely easily. */
6449 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
6450 j_decompress_ptr cinfo
;
6453 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6458 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6459 #define fn_jpeg_start_decompress jpeg_start_decompress
6460 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6461 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6462 #define fn_jpeg_read_header jpeg_read_header
6463 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6464 #define fn_jpeg_std_error jpeg_std_error
6465 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6467 #endif /* HAVE_NTGUI */
6469 struct my_jpeg_error_mgr
6471 struct jpeg_error_mgr pub
;
6472 jmp_buf setjmp_buffer
;
6477 my_error_exit (cinfo
)
6480 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6481 longjmp (mgr
->setjmp_buffer
, 1);
6485 /* Init source method for JPEG data source manager. Called by
6486 jpeg_read_header() before any data is actually read. See
6487 libjpeg.doc from the JPEG lib distribution. */
6490 our_common_init_source (cinfo
)
6491 j_decompress_ptr cinfo
;
6496 /* Method to terminate data source. Called by
6497 jpeg_finish_decompress() after all data has been processed. */
6500 our_common_term_source (cinfo
)
6501 j_decompress_ptr cinfo
;
6506 /* Fill input buffer method for JPEG data source manager. Called
6507 whenever more data is needed. We read the whole image in one step,
6508 so this only adds a fake end of input marker at the end. */
6510 static JOCTET our_memory_buffer
[2];
6513 our_memory_fill_input_buffer (cinfo
)
6514 j_decompress_ptr cinfo
;
6516 /* Insert a fake EOI marker. */
6517 struct jpeg_source_mgr
*src
= cinfo
->src
;
6519 our_memory_buffer
[0] = (JOCTET
) 0xFF;
6520 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
6522 src
->next_input_byte
= our_memory_buffer
;
6523 src
->bytes_in_buffer
= 2;
6528 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6529 is the JPEG data source manager. */
6532 our_memory_skip_input_data (cinfo
, num_bytes
)
6533 j_decompress_ptr cinfo
;
6536 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6540 if (num_bytes
> src
->bytes_in_buffer
)
6541 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6543 src
->bytes_in_buffer
-= num_bytes
;
6544 src
->next_input_byte
+= num_bytes
;
6549 /* Set up the JPEG lib for reading an image from DATA which contains
6550 LEN bytes. CINFO is the decompression info structure created for
6551 reading the image. */
6554 jpeg_memory_src (cinfo
, data
, len
)
6555 j_decompress_ptr cinfo
;
6559 struct jpeg_source_mgr
*src
;
6561 if (cinfo
->src
== NULL
)
6563 /* First time for this JPEG object? */
6564 cinfo
->src
= (struct jpeg_source_mgr
*)
6565 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6566 sizeof (struct jpeg_source_mgr
));
6567 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6568 src
->next_input_byte
= data
;
6571 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6572 src
->init_source
= our_common_init_source
;
6573 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6574 src
->skip_input_data
= our_memory_skip_input_data
;
6575 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6576 src
->term_source
= our_common_term_source
;
6577 src
->bytes_in_buffer
= len
;
6578 src
->next_input_byte
= data
;
6582 struct jpeg_stdio_mgr
6584 struct jpeg_source_mgr mgr
;
6591 /* Size of buffer to read JPEG from file.
6592 Not too big, as we want to use alloc_small. */
6593 #define JPEG_STDIO_BUFFER_SIZE 8192
6596 /* Fill input buffer method for JPEG data source manager. Called
6597 whenever more data is needed. The data is read from a FILE *. */
6600 our_stdio_fill_input_buffer (cinfo
)
6601 j_decompress_ptr cinfo
;
6603 struct jpeg_stdio_mgr
*src
;
6605 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6610 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6612 src
->mgr
.bytes_in_buffer
= bytes
;
6615 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6617 src
->buffer
[0] = (JOCTET
) 0xFF;
6618 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6619 src
->mgr
.bytes_in_buffer
= 2;
6621 src
->mgr
.next_input_byte
= src
->buffer
;
6628 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6629 is the JPEG data source manager. */
6632 our_stdio_skip_input_data (cinfo
, num_bytes
)
6633 j_decompress_ptr cinfo
;
6636 struct jpeg_stdio_mgr
*src
;
6637 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6639 while (num_bytes
> 0 && !src
->finished
)
6641 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6643 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6644 src
->mgr
.next_input_byte
+= num_bytes
;
6649 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6650 src
->mgr
.bytes_in_buffer
= 0;
6651 src
->mgr
.next_input_byte
= NULL
;
6653 our_stdio_fill_input_buffer (cinfo
);
6659 /* Set up the JPEG lib for reading an image from a FILE *.
6660 CINFO is the decompression info structure created for
6661 reading the image. */
6664 jpeg_file_src (cinfo
, fp
)
6665 j_decompress_ptr cinfo
;
6668 struct jpeg_stdio_mgr
*src
;
6670 if (cinfo
->src
!= NULL
)
6671 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6674 /* First time for this JPEG object? */
6675 cinfo
->src
= (struct jpeg_source_mgr
*)
6676 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6677 sizeof (struct jpeg_stdio_mgr
));
6678 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6679 src
->buffer
= (JOCTET
*)
6680 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6681 JPEG_STDIO_BUFFER_SIZE
);
6686 src
->mgr
.init_source
= our_common_init_source
;
6687 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6688 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6689 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6690 src
->mgr
.term_source
= our_common_term_source
;
6691 src
->mgr
.bytes_in_buffer
= 0;
6692 src
->mgr
.next_input_byte
= NULL
;
6696 /* Load image IMG for use on frame F. Patterned after example.c
6697 from the JPEG lib. */
6704 struct jpeg_decompress_struct cinfo
;
6705 struct my_jpeg_error_mgr mgr
;
6706 Lisp_Object file
, specified_file
;
6707 Lisp_Object specified_data
;
6708 FILE * volatile fp
= NULL
;
6710 int row_stride
, x
, y
;
6711 XImagePtr ximg
= NULL
;
6713 unsigned long *colors
;
6715 struct gcpro gcpro1
;
6717 /* Open the JPEG file. */
6718 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6719 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6723 if (NILP (specified_data
))
6725 file
= x_find_image_file (specified_file
);
6726 if (!STRINGP (file
))
6728 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6733 fp
= fopen (SDATA (file
), "rb");
6736 image_error ("Cannot open `%s'", file
, Qnil
);
6742 /* Customize libjpeg's error handling to call my_error_exit when an
6743 error is detected. This function will perform a longjmp.
6744 Casting return value avoids a GCC warning on W32. */
6745 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
6746 mgr
.pub
.error_exit
= my_error_exit
;
6748 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6752 /* Called from my_error_exit. Display a JPEG error. */
6753 char buffer
[JMSG_LENGTH_MAX
];
6754 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6755 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6756 build_string (buffer
));
6759 /* Close the input file and destroy the JPEG object. */
6761 fclose ((FILE *) fp
);
6762 fn_jpeg_destroy_decompress (&cinfo
);
6764 /* If we already have an XImage, free that. */
6765 x_destroy_x_image (ximg
);
6767 /* Free pixmap and colors. */
6768 x_clear_image (f
, img
);
6774 /* Create the JPEG decompression object. Let it read from fp.
6775 Read the JPEG image header. */
6776 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6778 if (NILP (specified_data
))
6779 jpeg_file_src (&cinfo
, (FILE *) fp
);
6781 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6782 SBYTES (specified_data
));
6784 fn_jpeg_read_header (&cinfo
, 1);
6786 /* Customize decompression so that color quantization will be used.
6787 Start decompression. */
6788 cinfo
.quantize_colors
= 1;
6789 fn_jpeg_start_decompress (&cinfo
);
6790 width
= img
->width
= cinfo
.output_width
;
6791 height
= img
->height
= cinfo
.output_height
;
6793 if (!check_image_size (f
, width
, height
))
6795 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
6796 longjmp (mgr
.setjmp_buffer
, 2);
6799 /* Create X image and pixmap. */
6800 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6801 longjmp (mgr
.setjmp_buffer
, 2);
6803 /* Allocate colors. When color quantization is used,
6804 cinfo.actual_number_of_colors has been set with the number of
6805 colors generated, and cinfo.colormap is a two-dimensional array
6806 of color indices in the range 0..cinfo.actual_number_of_colors.
6807 No more than 255 colors will be generated. */
6811 if (cinfo
.out_color_components
> 2)
6812 ir
= 0, ig
= 1, ib
= 2;
6813 else if (cinfo
.out_color_components
> 1)
6814 ir
= 0, ig
= 1, ib
= 0;
6816 ir
= 0, ig
= 0, ib
= 0;
6818 /* Use the color table mechanism because it handles colors that
6819 cannot be allocated nicely. Such colors will be replaced with
6820 a default color, and we don't have to care about which colors
6821 can be freed safely, and which can't. */
6822 init_color_table ();
6823 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6826 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6828 /* Multiply RGB values with 255 because X expects RGB values
6829 in the range 0..0xffff. */
6830 int r
= cinfo
.colormap
[ir
][i
] << 8;
6831 int g
= cinfo
.colormap
[ig
][i
] << 8;
6832 int b
= cinfo
.colormap
[ib
][i
] << 8;
6833 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6836 #ifdef COLOR_TABLE_SUPPORT
6837 /* Remember those colors actually allocated. */
6838 img
->colors
= colors_in_color_table (&img
->ncolors
);
6839 free_color_table ();
6840 #endif /* COLOR_TABLE_SUPPORT */
6844 row_stride
= width
* cinfo
.output_components
;
6845 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6847 for (y
= 0; y
< height
; ++y
)
6849 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6850 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6851 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6855 fn_jpeg_finish_decompress (&cinfo
);
6856 fn_jpeg_destroy_decompress (&cinfo
);
6858 fclose ((FILE *) fp
);
6860 /* Maybe fill in the background field while we have ximg handy. */
6861 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6862 /* Casting avoids a GCC warning. */
6863 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6865 /* Put the image into the pixmap. */
6866 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6867 x_destroy_x_image (ximg
);
6872 #else /* HAVE_JPEG */
6876 jpeg_load (struct frame
*f
, struct image
*img
)
6878 return ns_load_image(f
, img
,
6879 image_spec_value (img
->spec
, QCfile
, NULL
),
6880 image_spec_value (img
->spec
, QCdata
, NULL
));
6882 #endif /* HAVE_NS */
6884 #endif /* !HAVE_JPEG */
6888 /***********************************************************************
6890 ***********************************************************************/
6892 #if defined (HAVE_TIFF) || defined (HAVE_NS)
6894 static int tiff_image_p
P_ ((Lisp_Object object
));
6895 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6897 /* The symbol `tiff' identifying images of this type. */
6901 /* Indices of image specification fields in tiff_format, below. */
6903 enum tiff_keyword_index
6912 TIFF_HEURISTIC_MASK
,
6919 /* Vector of image_keyword structures describing the format
6920 of valid user-defined image specifications. */
6922 static struct image_keyword tiff_format
[TIFF_LAST
] =
6924 {":type", IMAGE_SYMBOL_VALUE
, 1},
6925 {":data", IMAGE_STRING_VALUE
, 0},
6926 {":file", IMAGE_STRING_VALUE
, 0},
6927 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6928 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6929 {":relief", IMAGE_INTEGER_VALUE
, 0},
6930 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6931 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6932 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6933 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6934 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
6937 /* Structure describing the image type `tiff'. */
6939 static struct image_type tiff_type
=
6948 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6951 tiff_image_p (object
)
6954 struct image_keyword fmt
[TIFF_LAST
];
6955 bcopy (tiff_format
, fmt
, sizeof fmt
);
6957 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6960 /* Must specify either the :data or :file keyword. */
6961 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6964 #endif /* HAVE_TIFF || HAVE_NS */
6972 /* TIFF library details. */
6973 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6974 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6975 DEF_IMGLIB_FN (TIFFOpen
);
6976 DEF_IMGLIB_FN (TIFFClientOpen
);
6977 DEF_IMGLIB_FN (TIFFGetField
);
6978 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6979 DEF_IMGLIB_FN (TIFFClose
);
6980 DEF_IMGLIB_FN (TIFFSetDirectory
);
6983 init_tiff_functions (Lisp_Object libraries
)
6987 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
6990 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6991 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6992 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6993 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6994 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6995 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6996 LOAD_IMGLIB_FN (library
, TIFFClose
);
6997 LOAD_IMGLIB_FN (library
, TIFFSetDirectory
);
7003 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7004 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7005 #define fn_TIFFOpen TIFFOpen
7006 #define fn_TIFFClientOpen TIFFClientOpen
7007 #define fn_TIFFGetField TIFFGetField
7008 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7009 #define fn_TIFFClose TIFFClose
7010 #define fn_TIFFSetDirectory TIFFSetDirectory
7011 #endif /* HAVE_NTGUI */
7014 /* Reading from a memory buffer for TIFF images Based on the PNG
7015 memory source, but we have to provide a lot of extra functions.
7018 We really only need to implement read and seek, but I am not
7019 convinced that the TIFF library is smart enough not to destroy
7020 itself if we only hand it the function pointers we need to
7025 unsigned char *bytes
;
7032 tiff_read_from_memory (data
, buf
, size
)
7037 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7039 if (size
> src
->len
- src
->index
)
7041 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7047 tiff_write_from_memory (data
, buf
, size
)
7056 tiff_seek_in_memory (data
, off
, whence
)
7061 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7066 case SEEK_SET
: /* Go from beginning of source. */
7070 case SEEK_END
: /* Go from end of source. */
7071 idx
= src
->len
+ off
;
7074 case SEEK_CUR
: /* Go from current position. */
7075 idx
= src
->index
+ off
;
7078 default: /* Invalid `whence'. */
7082 if (idx
> src
->len
|| idx
< 0)
7090 tiff_close_memory (data
)
7098 tiff_mmap_memory (data
, pbase
, psize
)
7103 /* It is already _IN_ memory. */
7108 tiff_unmap_memory (data
, base
, size
)
7113 /* We don't need to do this. */
7117 tiff_size_of_memory (data
)
7120 return ((tiff_memory_source
*) data
)->len
;
7125 tiff_error_handler (title
, format
, ap
)
7126 const char *title
, *format
;
7132 len
= sprintf (buf
, "TIFF error: %s ", title
);
7133 vsprintf (buf
+ len
, format
, ap
);
7134 add_to_log (buf
, Qnil
, Qnil
);
7139 tiff_warning_handler (title
, format
, ap
)
7140 const char *title
, *format
;
7146 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7147 vsprintf (buf
+ len
, format
, ap
);
7148 add_to_log (buf
, Qnil
, Qnil
);
7152 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7160 Lisp_Object file
, specified_file
;
7161 Lisp_Object specified_data
;
7163 int width
, height
, x
, y
, count
;
7167 struct gcpro gcpro1
;
7168 tiff_memory_source memsrc
;
7171 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7172 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7176 fn_TIFFSetErrorHandler (tiff_error_handler
);
7177 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7179 if (NILP (specified_data
))
7181 /* Read from a file */
7182 file
= x_find_image_file (specified_file
);
7183 if (!STRINGP (file
))
7185 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7190 /* Try to open the image file. Casting return value avoids a
7191 GCC warning on W32. */
7192 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7195 image_error ("Cannot open `%s'", file
, Qnil
);
7202 /* Memory source! */
7203 memsrc
.bytes
= SDATA (specified_data
);
7204 memsrc
.len
= SBYTES (specified_data
);
7207 /* Casting return value avoids a GCC warning on W32. */
7208 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7209 (TIFFReadWriteProc
) tiff_read_from_memory
,
7210 (TIFFReadWriteProc
) tiff_write_from_memory
,
7211 tiff_seek_in_memory
,
7213 tiff_size_of_memory
,
7219 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7225 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7226 if (INTEGERP (image
))
7228 int ino
= XFASTINT (image
);
7229 if (!fn_TIFFSetDirectory (tiff
, ino
))
7231 image_error ("Invalid image number `%s' in image `%s'",
7233 fn_TIFFClose (tiff
);
7239 /* Get width and height of the image, and allocate a raster buffer
7240 of width x height 32-bit values. */
7241 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7242 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7244 if (!check_image_size (f
, width
, height
))
7246 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
7247 fn_TIFFClose (tiff
);
7252 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7254 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7256 /* Count the number of images in the file. */
7257 for (count
= 1, rc2
= 1; rc2
; count
++)
7258 rc2
= fn_TIFFSetDirectory (tiff
, count
);
7261 img
->data
.lisp_val
= Fcons (Qcount
,
7262 Fcons (make_number (count
),
7263 img
->data
.lisp_val
));
7265 fn_TIFFClose (tiff
);
7268 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7274 /* Create the X image and pixmap. */
7275 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7282 /* Initialize the color table. */
7283 init_color_table ();
7285 /* Process the pixel raster. Origin is in the lower-left corner. */
7286 for (y
= 0; y
< height
; ++y
)
7288 uint32
*row
= buf
+ y
* width
;
7290 for (x
= 0; x
< width
; ++x
)
7292 uint32 abgr
= row
[x
];
7293 int r
= TIFFGetR (abgr
) << 8;
7294 int g
= TIFFGetG (abgr
) << 8;
7295 int b
= TIFFGetB (abgr
) << 8;
7296 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7300 #ifdef COLOR_TABLE_SUPPORT
7301 /* Remember the colors allocated for the image. Free the color table. */
7302 img
->colors
= colors_in_color_table (&img
->ncolors
);
7303 free_color_table ();
7304 #endif /* COLOR_TABLE_SUPPORT */
7307 img
->height
= height
;
7309 /* Maybe fill in the background field while we have ximg handy. */
7310 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7311 /* Casting avoids a GCC warning on W32. */
7312 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7314 /* Put the image into the pixmap, then free the X image and its buffer. */
7315 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7316 x_destroy_x_image (ximg
);
7323 #else /* HAVE_TIFF */
7327 tiff_load (struct frame
*f
, struct image
*img
)
7329 return ns_load_image(f
, img
,
7330 image_spec_value (img
->spec
, QCfile
, NULL
),
7331 image_spec_value (img
->spec
, QCdata
, NULL
));
7333 #endif /* HAVE_NS */
7335 #endif /* !HAVE_TIFF */
7339 /***********************************************************************
7341 ***********************************************************************/
7343 #if defined (HAVE_GIF) || defined (HAVE_NS)
7345 static int gif_image_p
P_ ((Lisp_Object object
));
7346 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7347 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7349 /* The symbol `gif' identifying images of this type. */
7353 /* Indices of image specification fields in gif_format, below. */
7355 enum gif_keyword_index
7371 /* Vector of image_keyword structures describing the format
7372 of valid user-defined image specifications. */
7374 static struct image_keyword gif_format
[GIF_LAST
] =
7376 {":type", IMAGE_SYMBOL_VALUE
, 1},
7377 {":data", IMAGE_STRING_VALUE
, 0},
7378 {":file", IMAGE_STRING_VALUE
, 0},
7379 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7380 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7381 {":relief", IMAGE_INTEGER_VALUE
, 0},
7382 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7383 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7384 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7385 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7386 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7389 /* Structure describing the image type `gif'. */
7391 static struct image_type gif_type
=
7400 /* Free X resources of GIF image IMG which is used on frame F. */
7403 gif_clear_image (f
, img
)
7407 /* IMG->data.ptr_val may contain extension data. */
7408 img
->data
.lisp_val
= Qnil
;
7409 x_clear_image (f
, img
);
7412 /* Return non-zero if OBJECT is a valid GIF image specification. */
7415 gif_image_p (object
)
7418 struct image_keyword fmt
[GIF_LAST
];
7419 bcopy (gif_format
, fmt
, sizeof fmt
);
7421 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7424 /* Must specify either the :data or :file keyword. */
7425 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7428 #endif /* HAVE_GIF */
7432 #if defined (HAVE_NTGUI)
7433 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7434 Undefine before redefining to avoid a preprocessor warning. */
7438 /* avoid conflict with QuickdrawText.h */
7439 #define DrawText gif_DrawText
7440 #include <gif_lib.h>
7443 #else /* HAVE_NTGUI */
7445 #include <gif_lib.h>
7447 #endif /* HAVE_NTGUI */
7452 /* GIF library details. */
7453 DEF_IMGLIB_FN (DGifCloseFile
);
7454 DEF_IMGLIB_FN (DGifSlurp
);
7455 DEF_IMGLIB_FN (DGifOpen
);
7456 DEF_IMGLIB_FN (DGifOpenFileName
);
7459 init_gif_functions (Lisp_Object libraries
)
7463 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7466 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7467 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7468 LOAD_IMGLIB_FN (library
, DGifOpen
);
7469 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7475 #define fn_DGifCloseFile DGifCloseFile
7476 #define fn_DGifSlurp DGifSlurp
7477 #define fn_DGifOpen DGifOpen
7478 #define fn_DGifOpenFileName DGifOpenFileName
7480 #endif /* HAVE_NTGUI */
7482 /* Reading a GIF image from memory
7483 Based on the PNG memory stuff to a certain extent. */
7487 unsigned char *bytes
;
7493 /* Make the current memory source available to gif_read_from_memory.
7494 It's done this way because not all versions of libungif support
7495 a UserData field in the GifFileType structure. */
7496 static gif_memory_source
*current_gif_memory_src
;
7499 gif_read_from_memory (file
, buf
, len
)
7504 gif_memory_source
*src
= current_gif_memory_src
;
7506 if (len
> src
->len
- src
->index
)
7509 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7515 /* Load GIF image IMG for use on frame F. Value is non-zero if
7518 static int interlace_start
[] = {0, 4, 2, 1};
7519 static int interlace_increment
[] = {8, 8, 4, 2};
7526 Lisp_Object file
, specified_file
;
7527 Lisp_Object specified_data
;
7528 int rc
, width
, height
, x
, y
, i
;
7530 ColorMapObject
*gif_color_map
;
7531 unsigned long pixel_colors
[256];
7533 struct gcpro gcpro1
;
7535 int ino
, image_height
, image_width
;
7536 gif_memory_source memsrc
;
7537 unsigned char *raster
;
7539 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7540 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7544 if (NILP (specified_data
))
7546 file
= x_find_image_file (specified_file
);
7547 if (!STRINGP (file
))
7549 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7554 /* Open the GIF file. Casting return value avoids a GCC warning
7556 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7559 image_error ("Cannot open `%s'", file
, Qnil
);
7566 /* Read from memory! */
7567 current_gif_memory_src
= &memsrc
;
7568 memsrc
.bytes
= SDATA (specified_data
);
7569 memsrc
.len
= SBYTES (specified_data
);
7572 /* Casting return value avoids a GCC warning on W32. */
7573 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
7576 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7582 /* Before reading entire contents, check the declared image size. */
7583 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7585 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
7586 fn_DGifCloseFile (gif
);
7591 /* Read entire contents. */
7592 rc
= fn_DGifSlurp (gif
);
7593 if (rc
== GIF_ERROR
)
7595 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7596 fn_DGifCloseFile (gif
);
7601 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7602 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7603 if (ino
>= gif
->ImageCount
)
7605 image_error ("Invalid image number `%s' in image `%s'",
7607 fn_DGifCloseFile (gif
);
7612 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7613 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7614 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7615 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7616 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7617 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7619 width
= img
->width
= max (gif
->SWidth
,
7620 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7621 img
->corners
[RIGHT_CORNER
]));
7622 height
= img
->height
= max (gif
->SHeight
,
7623 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7624 img
->corners
[BOT_CORNER
]));
7626 if (!check_image_size (f
, width
, height
))
7628 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
7629 fn_DGifCloseFile (gif
);
7634 /* Create the X image and pixmap. */
7635 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7637 fn_DGifCloseFile (gif
);
7642 /* Allocate colors. */
7643 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7645 gif_color_map
= gif
->SColorMap
;
7646 init_color_table ();
7647 bzero (pixel_colors
, sizeof pixel_colors
);
7650 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7652 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7653 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7654 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7655 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7658 #ifdef COLOR_TABLE_SUPPORT
7659 img
->colors
= colors_in_color_table (&img
->ncolors
);
7660 free_color_table ();
7661 #endif /* COLOR_TABLE_SUPPORT */
7663 /* Clear the part of the screen image that are not covered by
7664 the image from the GIF file. Full animated GIF support
7665 requires more than can be done here (see the gif89 spec,
7666 disposal methods). Let's simply assume that the part
7667 not covered by a sub-image is in the frame's background color. */
7668 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7669 for (x
= 0; x
< width
; ++x
)
7670 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7672 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7673 for (x
= 0; x
< width
; ++x
)
7674 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7676 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7678 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7679 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7680 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7681 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7684 /* Read the GIF image into the X image. We use a local variable
7685 `raster' here because RasterBits below is a char *, and invites
7686 problems with bytes >= 0x80. */
7687 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7689 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7692 int row
= interlace_start
[0];
7696 for (y
= 0; y
< image_height
; y
++)
7698 if (row
>= image_height
)
7700 row
= interlace_start
[++pass
];
7701 while (row
>= image_height
)
7702 row
= interlace_start
[++pass
];
7705 for (x
= 0; x
< image_width
; x
++)
7707 int i
= raster
[(y
* image_width
) + x
];
7708 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7709 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7712 row
+= interlace_increment
[pass
];
7717 for (y
= 0; y
< image_height
; ++y
)
7718 for (x
= 0; x
< image_width
; ++x
)
7720 int i
= raster
[y
* image_width
+ x
];
7721 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7722 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7726 /* Save GIF image extension data for `image-extension-data'.
7727 Format is (count IMAGES FUNCTION "BYTES" ...). */
7728 img
->data
.lisp_val
= Qnil
;
7729 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
7731 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
7732 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
7733 /* Append (... FUNCTION "BYTES") */
7734 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
7735 Fcons (make_number (ext
->Function
),
7736 img
->data
.lisp_val
));
7737 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
7739 if (gif
->ImageCount
> 1)
7740 img
->data
.lisp_val
= Fcons (Qcount
,
7741 Fcons (make_number (gif
->ImageCount
),
7742 img
->data
.lisp_val
));
7744 fn_DGifCloseFile (gif
);
7746 /* Maybe fill in the background field while we have ximg handy. */
7747 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7748 /* Casting avoids a GCC warning. */
7749 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7751 /* Put the image into the pixmap, then free the X image and its buffer. */
7752 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7753 x_destroy_x_image (ximg
);
7759 #else /* !HAVE_GIF */
7763 gif_load (struct frame
*f
, struct image
*img
)
7765 return ns_load_image(f
, img
,
7766 image_spec_value (img
->spec
, QCfile
, NULL
),
7767 image_spec_value (img
->spec
, QCdata
, NULL
));
7769 #endif /* HAVE_NS */
7771 #endif /* HAVE_GIF */
7775 /***********************************************************************
7777 ***********************************************************************/
7779 #if defined (HAVE_RSVG)
7781 /* Function prototypes. */
7783 static int svg_image_p
P_ ((Lisp_Object object
));
7784 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
7786 static int svg_load_image
P_ ((struct frame
*, struct image
*,
7787 unsigned char *, unsigned int));
7789 /* The symbol `svg' identifying images of this type. */
7793 /* Indices of image specification fields in svg_format, below. */
7795 enum svg_keyword_index
7810 /* Vector of image_keyword structures describing the format
7811 of valid user-defined image specifications. */
7813 static struct image_keyword svg_format
[SVG_LAST
] =
7815 {":type", IMAGE_SYMBOL_VALUE
, 1},
7816 {":data", IMAGE_STRING_VALUE
, 0},
7817 {":file", IMAGE_STRING_VALUE
, 0},
7818 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7819 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7820 {":relief", IMAGE_INTEGER_VALUE
, 0},
7821 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7822 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7823 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7824 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7827 /* Structure describing the image type `svg'. Its the same type of
7828 structure defined for all image formats, handled by emacs image
7829 functions. See struct image_type in dispextern.h. */
7831 static struct image_type svg_type
=
7833 /* An identifier showing that this is an image structure for the SVG format. */
7835 /* Handle to a function that can be used to identify a SVG file. */
7837 /* Handle to function used to load a SVG file. */
7839 /* Handle to function to free sresources for SVG. */
7841 /* An internal field to link to the next image type in a list of
7842 image types, will be filled in when registering the format. */
7847 /* Return non-zero if OBJECT is a valid SVG image specification. Do
7848 this by calling parse_image_spec and supplying the keywords that
7849 identify the SVG format. */
7852 svg_image_p (object
)
7855 struct image_keyword fmt
[SVG_LAST
];
7856 bcopy (svg_format
, fmt
, sizeof fmt
);
7858 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
7861 /* Must specify either the :data or :file keyword. */
7862 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
7865 #include <librsvg/rsvg.h>
7869 /* SVG library functions. */
7870 DEF_IMGLIB_FN (rsvg_handle_new
);
7871 DEF_IMGLIB_FN (rsvg_handle_get_dimensions
);
7872 DEF_IMGLIB_FN (rsvg_handle_write
);
7873 DEF_IMGLIB_FN (rsvg_handle_close
);
7874 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
7875 DEF_IMGLIB_FN (rsvg_handle_free
);
7877 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
7878 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
7879 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
7880 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
7881 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
7882 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
7883 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
7884 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
7886 DEF_IMGLIB_FN (g_type_init
);
7887 DEF_IMGLIB_FN (g_object_unref
);
7888 DEF_IMGLIB_FN (g_error_free
);
7890 Lisp_Object Qgdk_pixbuf
, Qglib
, Qgobject
;
7893 init_svg_functions (Lisp_Object libraries
)
7895 HMODULE library
, gdklib
, glib
, gobject
;
7897 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
7898 || !(gobject
= w32_delayed_load (libraries
, Qgobject
))
7899 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
7900 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
7903 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
7904 LOAD_IMGLIB_FN (library
, rsvg_handle_get_dimensions
);
7905 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
7906 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
7907 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
7908 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
7910 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
7911 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
7912 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
7913 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
7914 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
7915 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
7916 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
7917 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
7919 LOAD_IMGLIB_FN (gobject
, g_type_init
);
7920 LOAD_IMGLIB_FN (gobject
, g_object_unref
);
7921 LOAD_IMGLIB_FN (glib
, g_error_free
);
7927 /* The following aliases for library functions allow dynamic loading
7928 to be used on some platforms. */
7929 #define fn_rsvg_handle_new rsvg_handle_new
7930 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
7931 #define fn_rsvg_handle_write rsvg_handle_write
7932 #define fn_rsvg_handle_close rsvg_handle_close
7933 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
7934 #define fn_rsvg_handle_free rsvg_handle_free
7936 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
7937 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
7938 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
7939 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
7940 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
7941 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
7942 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
7943 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
7945 #define fn_g_type_init g_type_init
7946 #define fn_g_object_unref g_object_unref
7947 #define fn_g_error_free g_error_free
7948 #endif /* !HAVE_NTGUI */
7950 /* Load SVG image IMG for use on frame F. Value is non-zero if
7951 successful. this function will go into the svg_type structure, and
7952 the prototype thus needs to be compatible with that structure. */
7960 Lisp_Object file_name
;
7962 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7963 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7964 if (STRINGP (file_name
))
7967 unsigned char *contents
;
7969 struct gcpro gcpro1
;
7971 file
= x_find_image_file (file_name
);
7973 if (!STRINGP (file
))
7975 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7980 /* Read the entire file into memory. */
7981 contents
= slurp_file (SDATA (file
), &size
);
7982 if (contents
== NULL
)
7984 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
7988 /* If the file was slurped into memory properly, parse it. */
7989 success_p
= svg_load_image (f
, img
, contents
, size
);
7993 /* Else its not a file, its a lisp object. Load the image from a
7994 lisp object rather than a file. */
7999 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8000 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8006 /* svg_load_image is a helper function for svg_load, which does the
8007 actual loading given contents and size, apart from frame and image
8008 structures, passed from svg_load.
8010 Uses librsvg to do most of the image processing.
8012 Returns non-zero when successful. */
8014 svg_load_image (f
, img
, contents
, size
)
8015 /* Pointer to emacs frame structure. */
8017 /* Pointer to emacs image structure. */
8019 /* String containing the SVG XML data to be parsed. */
8020 unsigned char *contents
;
8021 /* Size of data in bytes. */
8024 RsvgHandle
*rsvg_handle
;
8025 RsvgDimensionData dimension_data
;
8026 GError
*error
= NULL
;
8030 const guint8
*pixels
;
8033 Lisp_Object specified_bg
;
8038 /* g_type_init is a glib function that must be called prior to using
8039 gnome type library functions. */
8041 /* Make a handle to a new rsvg object. */
8042 rsvg_handle
= (RsvgHandle
*) fn_rsvg_handle_new ();
8044 /* Parse the contents argument and fill in the rsvg_handle. */
8045 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8046 if (error
) goto rsvg_error
;
8048 /* The parsing is complete, rsvg_handle is ready to used, close it
8049 for further writes. */
8050 fn_rsvg_handle_close (rsvg_handle
, &error
);
8051 if (error
) goto rsvg_error
;
8053 fn_rsvg_handle_get_dimensions (rsvg_handle
, &dimension_data
);
8054 if (! check_image_size (f
, dimension_data
.width
, dimension_data
.height
))
8056 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
8060 /* We can now get a valid pixel buffer from the svg file, if all
8062 pixbuf
= (GdkPixbuf
*) fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8063 if (!pixbuf
) goto rsvg_error
;
8064 fn_g_object_unref (rsvg_handle
);
8066 /* Extract some meta data from the svg handle. */
8067 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8068 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8069 pixels
= (const guint8
*) fn_gdk_pixbuf_get_pixels (pixbuf
);
8070 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8072 /* Validate the svg meta data. */
8073 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8074 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8075 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8076 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8078 /* Try to create a x pixmap to hold the svg pixmap. */
8079 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8081 fn_g_object_unref (pixbuf
);
8085 init_color_table ();
8087 /* Handle alpha channel by combining the image with a background
8089 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8090 if (!STRINGP (specified_bg
)
8091 || !x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8094 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8095 x_query_color (f
, &background
);
8097 ns_query_color(FRAME_BACKGROUND_COLOR (f
), &background
, 1);
8101 /* SVG pixmaps specify transparency in the last byte, so right
8102 shift 8 bits to get rid of it, since emacs doesn't support
8104 background
.red
>>= 8;
8105 background
.green
>>= 8;
8106 background
.blue
>>= 8;
8108 /* This loop handles opacity values, since Emacs assumes
8109 non-transparent images. Each pixel must be "flattened" by
8110 calculating the resulting color, given the transparency of the
8111 pixel, and the image background color. */
8112 for (y
= 0; y
< height
; ++y
)
8114 for (x
= 0; x
< width
; ++x
)
8124 opacity
= *pixels
++;
8126 red
= ((red
* opacity
)
8127 + (background
.red
* ((1 << 8) - opacity
)));
8128 green
= ((green
* opacity
)
8129 + (background
.green
* ((1 << 8) - opacity
)));
8130 blue
= ((blue
* opacity
)
8131 + (background
.blue
* ((1 << 8) - opacity
)));
8133 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8136 pixels
+= rowstride
- 4 * width
;
8139 #ifdef COLOR_TABLE_SUPPORT
8140 /* Remember colors allocated for this image. */
8141 img
->colors
= colors_in_color_table (&img
->ncolors
);
8142 free_color_table ();
8143 #endif /* COLOR_TABLE_SUPPORT */
8145 fn_g_object_unref (pixbuf
);
8148 img
->height
= height
;
8150 /* Maybe fill in the background field while we have ximg handy.
8151 Casting avoids a GCC warning. */
8152 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8154 /* Put the image into the pixmap, then free the X image and its
8156 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8157 x_destroy_x_image (ximg
);
8162 fn_g_object_unref (rsvg_handle
);
8163 /* FIXME: Use error->message so the user knows what is the actual
8164 problem with the image. */
8165 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8166 fn_g_error_free (error
);
8170 #endif /* defined (HAVE_RSVG) */
8175 /***********************************************************************
8177 ***********************************************************************/
8179 #ifdef HAVE_X_WINDOWS
8180 #define HAVE_GHOSTSCRIPT 1
8181 #endif /* HAVE_X_WINDOWS */
8183 /* The symbol `postscript' identifying images of this type. */
8185 Lisp_Object Qpostscript
;
8187 #ifdef HAVE_GHOSTSCRIPT
8189 static int gs_image_p
P_ ((Lisp_Object object
));
8190 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8191 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8193 /* Keyword symbols. */
8195 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8197 /* Indices of image specification fields in gs_format, below. */
8199 enum gs_keyword_index
8217 /* Vector of image_keyword structures describing the format
8218 of valid user-defined image specifications. */
8220 static struct image_keyword gs_format
[GS_LAST
] =
8222 {":type", IMAGE_SYMBOL_VALUE
, 1},
8223 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8224 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8225 {":file", IMAGE_STRING_VALUE
, 1},
8226 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8227 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8228 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8229 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8230 {":relief", IMAGE_INTEGER_VALUE
, 0},
8231 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8232 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8233 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8234 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8237 /* Structure describing the image type `ghostscript'. */
8239 static struct image_type gs_type
=
8249 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8252 gs_clear_image (f
, img
)
8256 /* IMG->data.ptr_val may contain a recorded colormap. */
8257 xfree (img
->data
.ptr_val
);
8258 x_clear_image (f
, img
);
8262 /* Return non-zero if OBJECT is a valid Ghostscript image
8269 struct image_keyword fmt
[GS_LAST
];
8273 bcopy (gs_format
, fmt
, sizeof fmt
);
8275 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8278 /* Bounding box must be a list or vector containing 4 integers. */
8279 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8282 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8283 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8288 else if (VECTORP (tem
))
8290 if (XVECTOR (tem
)->size
!= 4)
8292 for (i
= 0; i
< 4; ++i
)
8293 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8303 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8312 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8313 struct gcpro gcpro1
, gcpro2
;
8315 double in_width
, in_height
;
8316 Lisp_Object pixel_colors
= Qnil
;
8318 /* Compute pixel size of pixmap needed from the given size in the
8319 image specification. Sizes in the specification are in pt. 1 pt
8320 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8322 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8323 in_width
= XFASTINT (pt_width
) / 72.0;
8324 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8325 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8326 in_height
= XFASTINT (pt_height
) / 72.0;
8327 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8329 if (!check_image_size (f
, img
->width
, img
->height
))
8331 image_error ("Invalid image size (see `max-image-size')", Qnil
, Qnil
);
8335 /* Create the pixmap. */
8336 xassert (img
->pixmap
== NO_PIXMAP
);
8338 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8340 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8341 img
->width
, img
->height
,
8342 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8347 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8351 /* Call the loader to fill the pixmap. It returns a process object
8352 if successful. We do not record_unwind_protect here because
8353 other places in redisplay like calling window scroll functions
8354 don't either. Let the Lisp loader use `unwind-protect' instead. */
8355 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8357 sprintf (buffer
, "%lu %lu",
8358 (unsigned long) FRAME_X_WINDOW (f
),
8359 (unsigned long) img
->pixmap
);
8360 window_and_pixmap_id
= build_string (buffer
);
8362 sprintf (buffer
, "%lu %lu",
8363 FRAME_FOREGROUND_PIXEL (f
),
8364 FRAME_BACKGROUND_PIXEL (f
));
8365 pixel_colors
= build_string (buffer
);
8367 XSETFRAME (frame
, f
);
8368 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8370 loader
= intern ("gs-load-image");
8372 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8373 make_number (img
->width
),
8374 make_number (img
->height
),
8375 window_and_pixmap_id
,
8378 return PROCESSP (img
->data
.lisp_val
);
8382 /* Kill the Ghostscript process that was started to fill PIXMAP on
8383 frame F. Called from XTread_socket when receiving an event
8384 telling Emacs that Ghostscript has finished drawing. */
8387 x_kill_gs_process (pixmap
, f
)
8391 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
8395 /* Find the image containing PIXMAP. */
8396 for (i
= 0; i
< c
->used
; ++i
)
8397 if (c
->images
[i
]->pixmap
== pixmap
)
8400 /* Should someone in between have cleared the image cache, for
8401 instance, give up. */
8405 /* Kill the GS process. We should have found PIXMAP in the image
8406 cache and its image should contain a process object. */
8408 xassert (PROCESSP (img
->data
.lisp_val
));
8409 Fkill_process (img
->data
.lisp_val
, Qnil
);
8410 img
->data
.lisp_val
= Qnil
;
8412 #if defined (HAVE_X_WINDOWS)
8414 /* On displays with a mutable colormap, figure out the colors
8415 allocated for the image by looking at the pixels of an XImage for
8417 class = FRAME_X_VISUAL (f
)->class;
8418 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8424 /* Try to get an XImage for img->pixmep. */
8425 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8426 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8431 /* Initialize the color table. */
8432 init_color_table ();
8434 /* For each pixel of the image, look its color up in the
8435 color table. After having done so, the color table will
8436 contain an entry for each color used by the image. */
8437 for (y
= 0; y
< img
->height
; ++y
)
8438 for (x
= 0; x
< img
->width
; ++x
)
8440 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8441 lookup_pixel_color (f
, pixel
);
8444 /* Record colors in the image. Free color table and XImage. */
8445 #ifdef COLOR_TABLE_SUPPORT
8446 img
->colors
= colors_in_color_table (&img
->ncolors
);
8447 free_color_table ();
8449 XDestroyImage (ximg
);
8451 #if 0 /* This doesn't seem to be the case. If we free the colors
8452 here, we get a BadAccess later in x_clear_image when
8453 freeing the colors. */
8454 /* We have allocated colors once, but Ghostscript has also
8455 allocated colors on behalf of us. So, to get the
8456 reference counts right, free them once. */
8458 x_free_colors (f
, img
->colors
, img
->ncolors
);
8462 image_error ("Cannot get X image of `%s'; colors will not be freed",
8467 #endif /* HAVE_X_WINDOWS */
8469 /* Now that we have the pixmap, compute mask and transform the
8470 image if requested. */
8472 postprocess_image (f
, img
);
8476 #endif /* HAVE_GHOSTSCRIPT */
8479 /***********************************************************************
8481 ***********************************************************************/
8485 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8486 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8490 return valid_image_p (spec
) ? Qt
: Qnil
;
8494 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8500 if (valid_image_p (spec
))
8501 id
= lookup_image (SELECTED_FRAME (), spec
);
8504 return make_number (id
);
8507 #endif /* GLYPH_DEBUG != 0 */
8510 /***********************************************************************
8512 ***********************************************************************/
8515 /* Image types that rely on external libraries are loaded dynamically
8516 if the library is available. */
8517 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8518 define_image_type (image_type, init_lib_fn (libraries))
8520 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8521 define_image_type (image_type, 1)
8522 #endif /* HAVE_NTGUI */
8524 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8525 doc
: /* Initialize image library implementing image type TYPE.
8526 Return non-nil if TYPE is a supported image type.
8528 Image types pbm and xbm are prebuilt; other types are loaded here.
8529 Libraries to load are specified in alist LIBRARIES (usually, the value
8530 of `image-library-alist', which see). */)
8532 Lisp_Object type
, libraries
;
8536 /* Don't try to reload the library. */
8537 tested
= Fassq (type
, Vimage_type_cache
);
8539 return XCDR (tested
);
8541 #if defined (HAVE_XPM) || defined (HAVE_NS)
8542 if (EQ (type
, Qxpm
))
8543 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8546 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8547 if (EQ (type
, Qjpeg
))
8548 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8551 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8552 if (EQ (type
, Qtiff
))
8553 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8556 #if defined (HAVE_GIF) || defined (HAVE_NS)
8557 if (EQ (type
, Qgif
))
8558 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8561 #if defined (HAVE_PNG) || defined (HAVE_NS)
8562 if (EQ (type
, Qpng
))
8563 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8566 #if defined (HAVE_RSVG)
8567 if (EQ (type
, Qsvg
))
8568 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
8571 #ifdef HAVE_GHOSTSCRIPT
8572 if (EQ (type
, Qpostscript
))
8573 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8576 /* If the type is not recognized, avoid testing it ever again. */
8577 CACHE_IMAGE_TYPE (type
, Qnil
);
8584 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8586 /* Initialize this only once, since that's what we do with Vimage_types
8587 and they are supposed to be in sync. Initializing here gives correct
8588 operation on GNU/Linux of calling dump-emacs after loading some images. */
8591 /* Must be defined now becase we're going to update it below, while
8592 defining the supported image types. */
8593 DEFVAR_LISP ("image-types", &Vimage_types
,
8594 doc
: /* List of potentially supported image types.
8595 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8596 To check whether it is really supported, use `image-type-available-p'. */);
8597 Vimage_types
= Qnil
;
8599 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8600 doc
: /* Alist of image types vs external libraries needed to display them.
8602 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8603 representing a supported image type, and the rest are strings giving
8604 alternate filenames for the corresponding external libraries.
8606 Emacs tries to load the libraries in the order they appear on the
8607 list; if none is loaded, the running session of Emacs won't
8608 support the image type. Types 'pbm and 'xbm don't need to be
8609 listed; they are always supported. */);
8610 Vimage_library_alist
= Qnil
;
8611 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8613 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8614 doc
: /* Maximum size of images.
8615 Emacs will not load an image into memory if its pixel width or
8616 pixel height exceeds this limit.
8618 If the value is an integer, it directly specifies the maximum
8619 image height and width, measured in pixels. If it is a floating
8620 point number, it specifies the maximum image height and width
8621 as a ratio to the frame height and width. If the value is
8622 non-numeric, there is no explicit limit on the size of images. */);
8623 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
8625 Vimage_type_cache
= Qnil
;
8626 staticpro (&Vimage_type_cache
);
8628 Qpbm
= intern ("pbm");
8630 ADD_IMAGE_TYPE (Qpbm
);
8632 Qxbm
= intern ("xbm");
8634 ADD_IMAGE_TYPE (Qxbm
);
8636 define_image_type (&xbm_type
, 1);
8637 define_image_type (&pbm_type
, 1);
8639 Qcount
= intern ("count");
8640 staticpro (&Qcount
);
8642 QCascent
= intern (":ascent");
8643 staticpro (&QCascent
);
8644 QCmargin
= intern (":margin");
8645 staticpro (&QCmargin
);
8646 QCrelief
= intern (":relief");
8647 staticpro (&QCrelief
);
8648 QCconversion
= intern (":conversion");
8649 staticpro (&QCconversion
);
8650 QCcolor_symbols
= intern (":color-symbols");
8651 staticpro (&QCcolor_symbols
);
8652 QCheuristic_mask
= intern (":heuristic-mask");
8653 staticpro (&QCheuristic_mask
);
8654 QCindex
= intern (":index");
8655 staticpro (&QCindex
);
8656 QCmatrix
= intern (":matrix");
8657 staticpro (&QCmatrix
);
8658 QCcolor_adjustment
= intern (":color-adjustment");
8659 staticpro (&QCcolor_adjustment
);
8660 QCmask
= intern (":mask");
8661 staticpro (&QCmask
);
8663 Qlaplace
= intern ("laplace");
8664 staticpro (&Qlaplace
);
8665 Qemboss
= intern ("emboss");
8666 staticpro (&Qemboss
);
8667 Qedge_detection
= intern ("edge-detection");
8668 staticpro (&Qedge_detection
);
8669 Qheuristic
= intern ("heuristic");
8670 staticpro (&Qheuristic
);
8672 Qpostscript
= intern ("postscript");
8673 staticpro (&Qpostscript
);
8674 #ifdef HAVE_GHOSTSCRIPT
8675 ADD_IMAGE_TYPE (Qpostscript
);
8676 QCloader
= intern (":loader");
8677 staticpro (&QCloader
);
8678 QCbounding_box
= intern (":bounding-box");
8679 staticpro (&QCbounding_box
);
8680 QCpt_width
= intern (":pt-width");
8681 staticpro (&QCpt_width
);
8682 QCpt_height
= intern (":pt-height");
8683 staticpro (&QCpt_height
);
8684 #endif /* HAVE_GHOSTSCRIPT */
8686 #if defined (HAVE_XPM) || defined (HAVE_NS)
8687 Qxpm
= intern ("xpm");
8689 ADD_IMAGE_TYPE (Qxpm
);
8692 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8693 Qjpeg
= intern ("jpeg");
8695 ADD_IMAGE_TYPE (Qjpeg
);
8698 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8699 Qtiff
= intern ("tiff");
8701 ADD_IMAGE_TYPE (Qtiff
);
8704 #if defined (HAVE_GIF) || defined (HAVE_NS)
8705 Qgif
= intern ("gif");
8707 ADD_IMAGE_TYPE (Qgif
);
8710 #if defined (HAVE_PNG) || defined (HAVE_NS)
8711 Qpng
= intern ("png");
8713 ADD_IMAGE_TYPE (Qpng
);
8716 #if defined (HAVE_RSVG)
8717 Qsvg
= intern ("svg");
8719 ADD_IMAGE_TYPE (Qsvg
);
8721 /* Other libraries used directly by svg code. */
8722 Qgdk_pixbuf
= intern ("gdk-pixbuf");
8723 staticpro (&Qgdk_pixbuf
);
8724 Qglib
= intern ("glib");
8726 Qgobject
= intern ("gobject");
8727 staticpro (&Qgobject
);
8728 #endif /* HAVE_NTGUI */
8729 #endif /* HAVE_RSVG */
8731 defsubr (&Sinit_image_library
);
8732 defsubr (&Sclear_image_cache
);
8733 defsubr (&Simage_refresh
);
8734 defsubr (&Simage_size
);
8735 defsubr (&Simage_mask_p
);
8736 defsubr (&Simage_extension_data
);
8740 defsubr (&Slookup_image
);
8743 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8744 doc
: /* Non-nil means always draw a cross over disabled images.
8745 Disabled images are those having a `:conversion disabled' property.
8746 A cross is always drawn on black & white displays. */);
8747 cross_disabled_images
= 0;
8749 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8750 doc
: /* List of directories to search for window system bitmap files. */);
8751 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8753 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8754 doc
: /* Time after which cached images are removed from the cache.
8755 When an image has not been displayed this many seconds, remove it
8756 from the image cache. Value must be an integer or nil with nil
8757 meaning don't clear the cache. */);
8758 Vimage_cache_eviction_delay
= make_number (30 * 60);
8766 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8767 (do not change this comment) */