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
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)
82 #endif /* HAVE_NTGUI */
86 #include <sys/types.h>
89 #undef COLOR_TABLE_SUPPORT
91 typedef struct ns_bitmap_record Bitmap_Record
;
93 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
96 #define RGB_PIXEL_COLOR unsigned long
99 #define PIX_MASK_RETAIN 0
100 #define PIX_MASK_DRAW 1
102 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
103 #define x_defined_color(f, name, color_def, alloc) \
104 ns_defined_color (f, name, color_def, alloc, 0)
105 #define FRAME_X_SCREEN(f) 0
106 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
110 /* Search path for bitmap files. */
112 Lisp_Object Vx_bitmap_file_path
;
115 static void x_disable_image
P_ ((struct frame
*, struct image
*));
116 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
119 static void init_color_table
P_ ((void));
120 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
121 #ifdef COLOR_TABLE_SUPPORT
122 static void free_color_table
P_ ((void));
123 static unsigned long *colors_in_color_table
P_ ((int *n
));
124 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
127 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
128 id, which is just an int that this section returns. Bitmaps are
129 reference counted so they can be shared among frames.
131 Bitmap indices are guaranteed to be > 0, so a negative number can
132 be used to indicate no bitmap.
134 If you use x_create_bitmap_from_data, then you must keep track of
135 the bitmaps yourself. That is, creating a bitmap from the same
136 data more than once will not be caught. */
141 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
142 Display
*display
; /* not used */
144 int x
, y
; /* not used */
145 unsigned int width
, height
; /* not used */
146 unsigned long plane_mask
; /* not used */
147 int format
; /* not used */
149 #if !USE_MAC_IMAGE_IO
151 xassert (x
== 0 && y
== 0);
154 SetRect (&ri
, 0, 0, width
, height
);
155 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
157 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
160 LockPixels (GetGWorldPixMap (pixmap
));
167 XPutPixel (ximage
, x
, y
, pixel
)
173 if (ximage
->bits_per_pixel
== 32)
174 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
176 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
178 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
179 short depth
= GetPixDepth (pixmap
);
181 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
184 char *base_addr
= GetPixBaseAddr (pixmap
);
185 short row_bytes
= GetPixRowBytes (pixmap
);
187 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
193 char *base_addr
= GetPixBaseAddr (pixmap
);
194 short row_bytes
= GetPixRowBytes (pixmap
);
196 if (pixel
== PIX_MASK_DRAW
)
197 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
199 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
207 GetGWorld (&old_port
, &old_gdh
);
208 SetGWorld (ximage
, NULL
);
210 color
.red
= RED16_FROM_ULONG (pixel
);
211 color
.green
= GREEN16_FROM_ULONG (pixel
);
212 color
.blue
= BLUE16_FROM_ULONG (pixel
);
214 SetCPixel (x
, y
, &color
);
216 SetGWorld (old_port
, old_gdh
);
222 XGetPixel (ximage
, x
, y
)
227 if (ximage
->bits_per_pixel
== 32)
228 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
230 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
232 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
233 short depth
= GetPixDepth (pixmap
);
235 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
238 char *base_addr
= GetPixBaseAddr (pixmap
);
239 short row_bytes
= GetPixRowBytes (pixmap
);
241 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
247 char *base_addr
= GetPixBaseAddr (pixmap
);
248 short row_bytes
= GetPixRowBytes (pixmap
);
250 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
251 return PIX_MASK_DRAW
;
253 return PIX_MASK_RETAIN
;
261 GetGWorld (&old_port
, &old_gdh
);
262 SetGWorld (ximage
, NULL
);
264 GetCPixel (x
, y
, &color
);
266 SetGWorld (old_port
, old_gdh
);
267 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
276 #if !USE_MAC_IMAGE_IO
277 UnlockPixels (GetGWorldPixMap (ximg
));
284 mac_data_provider_release_data (info
, data
, size
)
289 xfree ((void *)data
);
294 mac_create_cg_image_from_image (f
, img
)
299 XImagePtr ximg
= img
->pixmap
;
300 CGDataProviderRef provider
;
306 unsigned long color
, alpha
;
308 for (y
= 0; y
< ximg
->height
; y
++)
309 for (x
= 0; x
< ximg
->width
; x
++)
311 color
= XGetPixel (ximg
, x
, y
);
312 alpha
= XGetPixel (img
->mask
, x
, y
);
313 XPutPixel (ximg
, x
, y
,
314 ARGB_TO_ULONG (alpha
,
315 RED_FROM_ULONG (color
)
316 * alpha
/ PIX_MASK_DRAW
,
317 GREEN_FROM_ULONG (color
)
318 * alpha
/ PIX_MASK_DRAW
,
319 BLUE_FROM_ULONG (color
)
320 * alpha
/ PIX_MASK_DRAW
));
322 xfree (img
->mask
->data
);
323 img
->mask
->data
= NULL
;
326 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
327 ximg
->bytes_per_line
* ximg
->height
,
328 mac_data_provider_release_data
);
330 result
= CGImageCreate (ximg
->width
, ximg
->height
, 8, 32,
331 ximg
->bytes_per_line
, mac_cg_color_space_rgb
,
332 ((img
->mask
? kCGImageAlphaPremultipliedFirst
333 : kCGImageAlphaNoneSkipFirst
)
334 | kCGBitmapByteOrder32Host
),
335 provider
, NULL
, 0, kCGRenderingIntentDefault
);
336 CGDataProviderRelease (provider
);
342 CGImageRef result
= NULL
;
349 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
350 img
->width
, img
->height
, 1);
357 GetGWorld (&old_port
, &old_gdh
);
358 SetGWorld (mask
, NULL
);
359 BackColor (blackColor
); /* Don't mask. */
360 SetRect (&r
, 0, 0, img
->width
, img
->height
);
362 SetGWorld (old_port
, old_gdh
);
367 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
368 GetGWorldPixMap (mask
), &result
);
369 if (mask
!= img
->mask
)
370 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
377 #endif /* USE_CG_DRAWING */
382 XGetImage (Display
*display
, Pixmap pixmap
, int x
, int y
,
383 unsigned int width
, unsigned int height
,
384 unsigned long plane_mask
, int format
)
386 /* TODO: not sure what this function is supposed to do.. */
387 ns_retain_object(pixmap
);
391 /* use with imgs created by ns_image_for_XPM */
393 XGetPixel (XImagePtr ximage
, int x
, int y
)
395 return ns_get_pixel(ximage
, x
, y
);
398 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
399 pixel is assumed to be in form RGB */
401 XPutPixel (XImagePtr ximage
, int x
, int y
, unsigned long pixel
)
403 ns_put_pixel(ximage
, x
, y
, pixel
);
408 /* Functions to access the contents of a bitmap, given an id. */
411 x_bitmap_height (f
, id
)
415 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
419 x_bitmap_width (f
, id
)
423 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
426 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
428 x_bitmap_pixmap (f
, id
)
432 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
436 #ifdef HAVE_X_WINDOWS
438 x_bitmap_mask (f
, id
)
442 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
446 /* Allocate a new bitmap record. Returns index of new record. */
449 x_allocate_bitmap_record (f
)
452 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
455 if (dpyinfo
->bitmaps
== NULL
)
457 dpyinfo
->bitmaps_size
= 10;
459 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
460 dpyinfo
->bitmaps_last
= 1;
464 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
465 return ++dpyinfo
->bitmaps_last
;
467 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
468 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
471 dpyinfo
->bitmaps_size
*= 2;
473 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
474 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
475 return ++dpyinfo
->bitmaps_last
;
478 /* Add one reference to the reference count of the bitmap with id ID. */
481 x_reference_bitmap (f
, id
)
485 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
488 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
491 x_create_bitmap_from_data (f
, bits
, width
, height
)
494 unsigned int width
, height
;
496 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
499 #ifdef HAVE_X_WINDOWS
501 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
502 bits
, width
, height
);
505 #endif /* HAVE_X_WINDOWS */
509 bitmap
= CreateBitmap (width
, height
,
510 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
511 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
515 #endif /* HAVE_NTGUI */
518 void *bitmap
= ns_image_from_XBM(bits
, width
, height
);
523 id
= x_allocate_bitmap_record (f
);
526 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
527 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
530 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
531 dpyinfo
->bitmaps
[id
- 1].height
= height
;
532 dpyinfo
->bitmaps
[id
- 1].width
= width
;
533 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
535 #ifdef HAVE_X_WINDOWS
536 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
537 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
538 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
539 #endif /* HAVE_X_WINDOWS */
542 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
543 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
544 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
545 #endif /* HAVE_NTGUI */
550 /* Create bitmap from file FILE for frame F. */
553 x_create_bitmap_from_file (f
, file
)
557 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
560 return -1; /* W32_TODO : bitmap support */
561 #endif /* HAVE_NTGUI */
565 void *bitmap
= ns_image_from_file(file
);
571 id
= x_allocate_bitmap_record (f
);
572 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
573 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
574 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
575 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
576 dpyinfo
->bitmaps
[id
- 1].height
= ns_image_width(bitmap
);
577 dpyinfo
->bitmaps
[id
- 1].width
= ns_image_height(bitmap
);
578 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
582 #ifdef HAVE_X_WINDOWS
583 unsigned int width
, height
;
585 int xhot
, yhot
, result
, id
;
590 /* Look for an existing bitmap with the same name. */
591 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
593 if (dpyinfo
->bitmaps
[id
].refcount
594 && dpyinfo
->bitmaps
[id
].file
595 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
597 ++dpyinfo
->bitmaps
[id
].refcount
;
602 /* Search bitmap-file-path for the file, if appropriate. */
603 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
608 filename
= (char *) SDATA (found
);
610 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
611 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
612 if (result
!= BitmapSuccess
)
615 id
= x_allocate_bitmap_record (f
);
616 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
617 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
618 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
619 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
620 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
621 dpyinfo
->bitmaps
[id
- 1].height
= height
;
622 dpyinfo
->bitmaps
[id
- 1].width
= width
;
623 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
626 #endif /* HAVE_X_WINDOWS */
632 free_bitmap_record (dpyinfo
, bm
)
633 Display_Info
*dpyinfo
;
636 #ifdef HAVE_X_WINDOWS
637 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
639 XFreePixmap (dpyinfo
->display
, bm
->mask
);
640 #endif /* HAVE_X_WINDOWS */
643 DeleteObject (bm
->pixmap
);
644 #endif /* HAVE_NTGUI */
647 ns_release_object(bm
->img
);
657 /* Remove reference to bitmap with id number ID. */
660 x_destroy_bitmap (f
, id
)
664 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
668 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
670 if (--bm
->refcount
== 0)
673 free_bitmap_record (dpyinfo
, bm
);
679 /* Free all the bitmaps for the display specified by DPYINFO. */
682 x_destroy_all_bitmaps (dpyinfo
)
683 Display_Info
*dpyinfo
;
686 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
688 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
689 if (bm
->refcount
> 0)
690 free_bitmap_record (dpyinfo
, bm
);
692 dpyinfo
->bitmaps_last
= 0;
696 #ifdef HAVE_X_WINDOWS
698 /* Useful functions defined in the section
699 `Image type independent image structures' below. */
701 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
704 unsigned long height
));
706 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
707 int depth
, XImagePtr
*ximg
,
710 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
713 /* Create a mask of a bitmap. Note is this not a perfect mask.
714 It's nicer with some borders in this context */
717 x_create_bitmap_mask (f
, id
)
722 XImagePtr ximg
, mask_img
;
723 unsigned long width
, height
;
726 unsigned long x
, y
, xp
, xm
, yp
, ym
;
729 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
734 pixmap
= x_bitmap_pixmap (f
, id
);
735 width
= x_bitmap_width (f
, id
);
736 height
= x_bitmap_height (f
, id
);
739 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
748 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
753 XDestroyImage (ximg
);
757 bg
= four_corners_best (ximg
, NULL
, width
, height
);
759 for (y
= 0; y
< ximg
->height
; ++y
)
761 for (x
= 0; x
< ximg
->width
; ++x
)
763 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
764 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
765 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
766 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
767 if (XGetPixel (ximg
, x
, y
) == bg
768 && XGetPixel (ximg
, x
, yp
) == bg
769 && XGetPixel (ximg
, x
, ym
) == bg
770 && XGetPixel (ximg
, xp
, y
) == bg
771 && XGetPixel (ximg
, xp
, yp
) == bg
772 && XGetPixel (ximg
, xp
, ym
) == bg
773 && XGetPixel (ximg
, xm
, y
) == bg
774 && XGetPixel (ximg
, xm
, yp
) == bg
775 && XGetPixel (ximg
, xm
, ym
) == bg
)
776 XPutPixel (mask_img
, x
, y
, 0);
778 XPutPixel (mask_img
, x
, y
, 1);
782 xassert (interrupt_input_blocked
);
783 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
784 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
786 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
788 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
789 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
791 XDestroyImage (ximg
);
792 x_destroy_x_image (mask_img
);
797 #endif /* HAVE_X_WINDOWS */
800 /***********************************************************************
802 ***********************************************************************/
804 /* Value is the number of elements of vector VECTOR. */
806 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
808 /* List of supported image types. Use define_image_type to add new
809 types. Use lookup_image_type to find a type for a given symbol. */
811 static struct image_type
*image_types
;
813 /* A list of symbols, one for each supported image type. */
815 Lisp_Object Vimage_types
;
817 /* An alist of image types and libraries that implement the type. */
819 Lisp_Object Vimage_library_alist
;
821 /* Cache for delayed-loading image types. */
823 static Lisp_Object Vimage_type_cache
;
825 /* The symbol `xbm' which is used as the type symbol for XBM images. */
831 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
832 extern Lisp_Object QCdata
, QCtype
;
833 extern Lisp_Object Qcenter
;
834 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
835 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
836 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
840 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
842 /* Time in seconds after which images should be removed from the cache
845 Lisp_Object Vimage_cache_eviction_delay
;
847 /* Function prototypes. */
849 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
850 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
851 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
852 static void x_laplace
P_ ((struct frame
*, struct image
*));
853 static void x_emboss
P_ ((struct frame
*, struct image
*));
854 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
857 #define CACHE_IMAGE_TYPE(type, status) \
858 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
860 #define ADD_IMAGE_TYPE(type) \
861 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
863 /* Define a new image type from TYPE. This adds a copy of TYPE to
864 image_types and caches the loading status of TYPE. */
867 define_image_type (type
, loaded
)
868 struct image_type
*type
;
877 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
878 The initialized data segment is read-only. */
879 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
880 bcopy (type
, p
, sizeof *p
);
881 p
->next
= image_types
;
886 CACHE_IMAGE_TYPE (*type
->type
, success
);
891 /* Look up image type SYMBOL, and return a pointer to its image_type
892 structure. Value is null if SYMBOL is not a known image type. */
894 static INLINE
struct image_type
*
895 lookup_image_type (symbol
)
898 struct image_type
*type
;
900 /* We must initialize the image-type if it hasn't been already. */
901 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
902 return 0; /* unimplemented */
904 for (type
= image_types
; type
; type
= type
->next
)
905 if (EQ (symbol
, *type
->type
))
912 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
913 valid image specification is a list whose car is the symbol
914 `image', and whose rest is a property list. The property list must
915 contain a value for key `:type'. That value must be the name of a
916 supported image type. The rest of the property list depends on the
920 valid_image_p (object
)
929 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
930 if (EQ (XCAR (tem
), QCtype
))
933 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
935 struct image_type
*type
;
936 type
= lookup_image_type (XCAR (tem
));
938 valid_p
= type
->valid_p (object
);
949 /* Log error message with format string FORMAT and argument ARG.
950 Signaling an error, e.g. when an image cannot be loaded, is not a
951 good idea because this would interrupt redisplay, and the error
952 message display would lead to another redisplay. This function
953 therefore simply displays a message. */
956 image_error (format
, arg1
, arg2
)
958 Lisp_Object arg1
, arg2
;
960 add_to_log (format
, arg1
, arg2
);
965 /***********************************************************************
967 ***********************************************************************/
969 enum image_value_type
971 IMAGE_DONT_CHECK_VALUE_TYPE
,
973 IMAGE_STRING_OR_NIL_VALUE
,
975 IMAGE_POSITIVE_INTEGER_VALUE
,
976 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
977 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
980 IMAGE_FUNCTION_VALUE
,
985 /* Structure used when parsing image specifications. */
989 /* Name of keyword. */
992 /* The type of value allowed. */
993 enum image_value_type type
;
995 /* Non-zero means key must be present. */
998 /* Used to recognize duplicate keywords in a property list. */
1001 /* The value that was found. */
1006 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
1008 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
1011 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
1012 has the format (image KEYWORD VALUE ...). One of the keyword/
1013 value pairs must be `:type TYPE'. KEYWORDS is a vector of
1014 image_keywords structures of size NKEYWORDS describing other
1015 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1018 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1020 struct image_keyword
*keywords
;
1030 plist
= XCDR (spec
);
1031 while (CONSP (plist
))
1033 Lisp_Object key
, value
;
1035 /* First element of a pair must be a symbol. */
1037 plist
= XCDR (plist
);
1041 /* There must follow a value. */
1044 value
= XCAR (plist
);
1045 plist
= XCDR (plist
);
1047 /* Find key in KEYWORDS. Error if not found. */
1048 for (i
= 0; i
< nkeywords
; ++i
)
1049 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1055 /* Record that we recognized the keyword. If a keywords
1056 was found more than once, it's an error. */
1057 keywords
[i
].value
= value
;
1058 ++keywords
[i
].count
;
1060 if (keywords
[i
].count
> 1)
1063 /* Check type of value against allowed type. */
1064 switch (keywords
[i
].type
)
1066 case IMAGE_STRING_VALUE
:
1067 if (!STRINGP (value
))
1071 case IMAGE_STRING_OR_NIL_VALUE
:
1072 if (!STRINGP (value
) && !NILP (value
))
1076 case IMAGE_SYMBOL_VALUE
:
1077 if (!SYMBOLP (value
))
1081 case IMAGE_POSITIVE_INTEGER_VALUE
:
1082 if (!INTEGERP (value
) || XINT (value
) <= 0)
1086 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1087 if (INTEGERP (value
) && XINT (value
) >= 0)
1090 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1091 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1095 case IMAGE_ASCENT_VALUE
:
1096 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1098 else if (INTEGERP (value
)
1099 && XINT (value
) >= 0
1100 && XINT (value
) <= 100)
1104 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1105 if (!INTEGERP (value
) || XINT (value
) < 0)
1109 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1112 case IMAGE_FUNCTION_VALUE
:
1113 value
= indirect_function (value
);
1115 || COMPILEDP (value
)
1116 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1120 case IMAGE_NUMBER_VALUE
:
1121 if (!INTEGERP (value
) && !FLOATP (value
))
1125 case IMAGE_INTEGER_VALUE
:
1126 if (!INTEGERP (value
))
1130 case IMAGE_BOOL_VALUE
:
1131 if (!NILP (value
) && !EQ (value
, Qt
))
1140 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1144 /* Check that all mandatory fields are present. */
1145 for (i
= 0; i
< nkeywords
; ++i
)
1146 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1149 return NILP (plist
);
1153 /* Return the value of KEY in image specification SPEC. Value is nil
1154 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1155 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1158 image_spec_value (spec
, key
, found
)
1159 Lisp_Object spec
, key
;
1164 xassert (valid_image_p (spec
));
1166 for (tail
= XCDR (spec
);
1167 CONSP (tail
) && CONSP (XCDR (tail
));
1168 tail
= XCDR (XCDR (tail
)))
1170 if (EQ (XCAR (tail
), key
))
1174 return XCAR (XCDR (tail
));
1184 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1185 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1186 PIXELS non-nil means return the size in pixels, otherwise return the
1187 size in canonical character units.
1188 FRAME is the frame on which the image will be displayed. FRAME nil
1189 or omitted means use the selected frame. */)
1190 (spec
, pixels
, frame
)
1191 Lisp_Object spec
, pixels
, frame
;
1196 if (valid_image_p (spec
))
1198 struct frame
*f
= check_x_frame (frame
);
1199 int id
= lookup_image (f
, spec
);
1200 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1201 int width
= img
->width
+ 2 * img
->hmargin
;
1202 int height
= img
->height
+ 2 * img
->vmargin
;
1205 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1206 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1208 size
= Fcons (make_number (width
), make_number (height
));
1211 error ("Invalid image specification");
1217 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1218 doc
: /* Return t if image SPEC has a mask bitmap.
1219 FRAME is the frame on which the image will be displayed. FRAME nil
1220 or omitted means use the selected frame. */)
1222 Lisp_Object spec
, frame
;
1227 if (valid_image_p (spec
))
1229 struct frame
*f
= check_x_frame (frame
);
1230 int id
= lookup_image (f
, spec
);
1231 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1236 error ("Invalid image specification");
1241 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1242 doc
: /* Return extension data for image SPEC.
1243 FRAME is the frame on which the image will be displayed. FRAME nil
1244 or omitted means use the selected frame. */)
1246 Lisp_Object spec
, frame
;
1251 if (valid_image_p (spec
))
1253 struct frame
*f
= check_x_frame (frame
);
1254 int id
= lookup_image (f
, spec
);
1255 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1256 ext
= img
->data
.lisp_val
;
1263 /***********************************************************************
1264 Image type independent image structures
1265 ***********************************************************************/
1267 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1268 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1269 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1271 #define MAX_IMAGE_SIZE 6.0
1272 Lisp_Object Vmax_image_size
;
1274 /* Allocate and return a new image structure for image specification
1275 SPEC. SPEC has a hash value of HASH. */
1277 static struct image
*
1278 make_image (spec
, hash
)
1282 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1283 Lisp_Object file
= image_spec_value (spec
, QCfile
, NULL
);
1285 xassert (valid_image_p (spec
));
1286 bzero (img
, sizeof *img
);
1287 img
->dependencies
= NILP (file
) ? Qnil
: list1 (file
);
1288 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1289 xassert (img
->type
!= NULL
);
1291 img
->data
.lisp_val
= Qnil
;
1292 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1294 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1299 /* Free image IMG which was used on frame F, including its resources. */
1308 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1310 /* Remove IMG from the hash table of its cache. */
1312 img
->prev
->next
= img
->next
;
1314 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1317 img
->next
->prev
= img
->prev
;
1319 c
->images
[img
->id
] = NULL
;
1321 /* Free resources, then free IMG. */
1322 img
->type
->free (f
, img
);
1327 /* Return 1 if the given widths and heights are valid for display;
1328 otherwise, return 0. */
1331 check_image_size (f
, width
, height
)
1338 if (width
<= 0 || height
<= 0)
1341 if (INTEGERP (Vmax_image_size
))
1342 w
= h
= XINT (Vmax_image_size
);
1343 else if (FLOATP (Vmax_image_size
))
1347 w
= FRAME_PIXEL_WIDTH (f
);
1348 h
= FRAME_PIXEL_HEIGHT (f
);
1351 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1352 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1353 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1358 return (width
<= w
&& height
<= h
);
1361 /* Prepare image IMG for display on frame F. Must be called before
1362 drawing an image. */
1365 prepare_image_for_display (f
, img
)
1371 /* We're about to display IMG, so set its timestamp to `now'. */
1373 img
->timestamp
= EMACS_SECS (t
);
1375 /* If IMG doesn't have a pixmap yet, load it now, using the image
1376 type dependent loader function. */
1377 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1378 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1383 /* Value is the number of pixels for the ascent of image IMG when
1384 drawn in face FACE. */
1387 image_ascent (img
, face
, slice
)
1390 struct glyph_slice
*slice
;
1395 if (slice
->height
== img
->height
)
1396 height
= img
->height
+ img
->vmargin
;
1397 else if (slice
->y
== 0)
1398 height
= slice
->height
+ img
->vmargin
;
1400 height
= slice
->height
;
1402 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1407 /* W32 specific version. Why?. ++kfs */
1408 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1409 - FONT_BASE (face
->font
)) / 2;
1411 /* This expression is arranged so that if the image can't be
1412 exactly centered, it will be moved slightly up. This is
1413 because a typical font is `top-heavy' (due to the presence
1414 uppercase letters), so the image placement should err towards
1415 being top-heavy too. It also just generally looks better. */
1416 ascent
= (height
+ FONT_BASE(face
->font
)
1417 - FONT_DESCENT(face
->font
) + 1) / 2;
1418 #endif /* HAVE_NTGUI */
1421 ascent
= height
/ 2;
1424 ascent
= (int) (height
* img
->ascent
/ 100.0);
1430 /* Image background colors. */
1432 /* Find the "best" corner color of a bitmap.
1433 On W32, XIMG is assumed to a device context with the bitmap selected. */
1435 static RGB_PIXEL_COLOR
1436 four_corners_best (ximg
, corners
, width
, height
)
1437 XImagePtr_or_DC ximg
;
1439 unsigned long width
, height
;
1441 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1444 if (corners
&& corners
[BOT_CORNER
] >= 0)
1446 /* Get the colors at the corner_pixels of ximg. */
1447 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1448 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1449 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1450 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1454 /* Get the colors at the corner_pixels of ximg. */
1455 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1456 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1457 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1458 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1460 /* Choose the most frequently found color as background. */
1461 for (i
= best_count
= 0; i
< 4; ++i
)
1465 for (j
= n
= 0; j
< 4; ++j
)
1466 if (corner_pixels
[i
] == corner_pixels
[j
])
1470 best
= corner_pixels
[i
], best_count
= n
;
1476 /* Portability macros */
1480 #define Destroy_Image(img_dc, prev) \
1481 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1483 #define Free_Pixmap(display, pixmap) \
1484 DeleteObject (pixmap)
1486 #elif defined (HAVE_NS)
1488 #define Destroy_Image(ximg, dummy) \
1489 ns_release_object(ximg)
1491 #define Free_Pixmap(display, pixmap) \
1492 ns_release_object(pixmap)
1496 #define Destroy_Image(ximg, dummy) \
1497 XDestroyImage (ximg)
1499 #define Free_Pixmap(display, pixmap) \
1500 XFreePixmap (display, pixmap)
1502 #endif /* !HAVE_NTGUI && !HAVE_NS */
1505 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1506 it is guessed heuristically. If non-zero, XIMG is an existing
1507 XImage object (or device context with the image selected on W32) to
1508 use for the heuristic. */
1511 image_background (img
, f
, ximg
)
1514 XImagePtr_or_DC ximg
;
1516 if (! img
->background_valid
)
1517 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1519 int free_ximg
= !ximg
;
1522 #endif /* HAVE_NTGUI */
1527 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1528 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1530 HDC frame_dc
= get_frame_dc (f
);
1531 ximg
= CreateCompatibleDC (frame_dc
);
1532 release_frame_dc (f
, frame_dc
);
1533 prev
= SelectObject (ximg
, img
->pixmap
);
1534 #endif /* !HAVE_NTGUI */
1537 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1540 Destroy_Image (ximg
, prev
);
1542 img
->background_valid
= 1;
1545 return img
->background
;
1548 /* Return the `background_transparent' field of IMG. If IMG doesn't
1549 have one yet, it is guessed heuristically. If non-zero, MASK is an
1550 existing XImage object to use for the heuristic. */
1553 image_background_transparent (img
, f
, mask
)
1556 XImagePtr_or_DC mask
;
1558 if (! img
->background_transparent_valid
)
1559 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1563 int free_mask
= !mask
;
1566 #endif /* HAVE_NTGUI */
1571 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1572 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1574 HDC frame_dc
= get_frame_dc (f
);
1575 mask
= CreateCompatibleDC (frame_dc
);
1576 release_frame_dc (f
, frame_dc
);
1577 prev
= SelectObject (mask
, img
->mask
);
1578 #endif /* HAVE_NTGUI */
1581 img
->background_transparent
1582 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1585 Destroy_Image (mask
, prev
);
1588 img
->background_transparent
= 0;
1590 img
->background_transparent_valid
= 1;
1593 return img
->background_transparent
;
1597 /***********************************************************************
1598 Helper functions for X image types
1599 ***********************************************************************/
1601 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1603 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1604 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1606 Lisp_Object color_name
,
1607 unsigned long dflt
));
1610 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1611 free the pixmap if any. MASK_P non-zero means clear the mask
1612 pixmap if any. COLORS_P non-zero means free colors allocated for
1613 the image, if any. */
1616 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1619 int pixmap_p
, mask_p
, colors_p
;
1621 if (pixmap_p
&& img
->pixmap
)
1623 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1624 img
->pixmap
= NO_PIXMAP
;
1625 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1626 img
->background_valid
= 0;
1629 if (mask_p
&& img
->mask
)
1631 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1632 img
->mask
= NO_PIXMAP
;
1633 img
->background_transparent_valid
= 0;
1636 if (colors_p
&& img
->ncolors
)
1638 /* W32_TODO: color table support. */
1639 #ifdef HAVE_X_WINDOWS
1640 x_free_colors (f
, img
->colors
, img
->ncolors
);
1641 #endif /* HAVE_X_WINDOWS */
1642 xfree (img
->colors
);
1649 /* Free X resources of image IMG which is used on frame F. */
1652 x_clear_image (f
, img
)
1657 x_clear_image_1 (f
, img
, 1, 1, 1);
1662 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1663 cannot be allocated, use DFLT. Add a newly allocated color to
1664 IMG->colors, so that it can be freed again. Value is the pixel
1667 static unsigned long
1668 x_alloc_image_color (f
, img
, color_name
, dflt
)
1671 Lisp_Object color_name
;
1675 unsigned long result
;
1677 xassert (STRINGP (color_name
));
1679 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1681 /* This isn't called frequently so we get away with simply
1682 reallocating the color vector to the needed size, here. */
1685 (unsigned long *) xrealloc (img
->colors
,
1686 img
->ncolors
* sizeof *img
->colors
);
1687 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1688 result
= color
.pixel
;
1698 /***********************************************************************
1700 ***********************************************************************/
1702 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1703 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1704 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1706 /* Return a new, initialized image cache that is allocated from the
1707 heap. Call free_image_cache to free an image cache. */
1709 struct image_cache
*
1712 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1715 bzero (c
, sizeof *c
);
1717 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1718 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1719 c
->buckets
= (struct image
**) xmalloc (size
);
1720 bzero (c
->buckets
, size
);
1725 /* Find an image matching SPEC in the cache, and return it. If no
1726 image is found, return NULL. */
1727 static struct image
*
1728 search_image_cache (f
, spec
, hash
)
1734 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1735 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1737 if (!c
) return NULL
;
1739 /* If the image spec does not specify a background color, the cached
1740 image must have the same background color as the current frame.
1741 The foreground color must also match, for the sake of monochrome
1744 In fact, we could ignore the foreground color matching condition
1745 for color images, or if the image spec specifies :foreground;
1746 similarly we could ignore the background color matching condition
1747 for formats that don't use transparency (such as jpeg), or if the
1748 image spec specifies :background. However, the extra memory
1749 usage is probably negligible in practice, so we don't bother. */
1751 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1752 if (img
->hash
== hash
1753 && !NILP (Fequal (img
->spec
, spec
))
1754 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1755 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1761 /* Search frame F for an image with spec SPEC, and free it. */
1764 uncache_image (f
, spec
)
1768 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1770 free_image (f
, img
);
1774 /* Free image cache of frame F. Be aware that X frames share images
1778 free_image_cache (f
)
1781 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1786 /* Cache should not be referenced by any frame when freed. */
1787 xassert (c
->refcount
== 0);
1789 for (i
= 0; i
< c
->used
; ++i
)
1790 free_image (f
, c
->images
[i
]);
1794 FRAME_IMAGE_CACHE (f
) = NULL
;
1799 /* Clear image cache of frame F. FILTER=t means free all images.
1800 FILTER=nil means clear only images that haven't been
1801 displayed for some time.
1802 Else, only free the images which have FILTER in their `dependencies'.
1803 Should be called from time to time to reduce the number of loaded images.
1804 If image-cache-eviction-delay is non-nil, this frees images in the cache
1805 which weren't displayed for at least that many seconds. */
1808 clear_image_cache (struct frame
*f
, Lisp_Object filter
)
1810 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1812 if (c
&& (!NILP (filter
) || INTEGERP (Vimage_cache_eviction_delay
)))
1819 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1821 /* Block input so that we won't be interrupted by a SIGIO
1822 while being in an inconsistent state. */
1825 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1827 struct image
*img
= c
->images
[i
];
1829 && (NILP (filter
) ? img
->timestamp
< old
1831 || !NILP (Fmember (filter
, img
->dependencies
)))))
1833 free_image (f
, img
);
1838 /* We may be clearing the image cache because, for example,
1839 Emacs was iconified for a longer period of time. In that
1840 case, current matrices may still contain references to
1841 images freed above. So, clear these matrices. */
1844 Lisp_Object tail
, frame
;
1846 FOR_EACH_FRAME (tail
, frame
)
1848 struct frame
*f
= XFRAME (frame
);
1849 if (FRAME_IMAGE_CACHE (f
) == c
)
1850 clear_current_matrices (f
);
1853 ++windows_or_buffers_changed
;
1861 clear_image_caches (Lisp_Object filter
)
1863 /* FIXME: We want to do
1864 * struct terminal *t;
1865 * for (t = terminal_list; t; t = t->next_terminal)
1866 * clear_image_cache (t, filter); */
1867 Lisp_Object tail
, frame
;
1868 FOR_EACH_FRAME (tail
, frame
)
1869 if (FRAME_WINDOW_P (XFRAME (frame
)))
1870 clear_image_cache (XFRAME (frame
), filter
);
1873 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1875 doc
: /* Clear the image cache.
1876 FILTER nil or a frame means clear all images in the selected frame.
1877 FILTER t means clear the image caches of all frames.
1878 Anything else, means only clear those images which refer to FILTER,
1879 which is then usually a filename. */)
1883 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1884 clear_image_caches (filter
);
1886 clear_image_cache (check_x_frame (filter
), Qt
);
1892 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1894 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1895 If SPEC specifies an image file, the displayed image is updated with
1896 the current contents of that file.
1897 FRAME nil or omitted means use the selected frame.
1898 FRAME t means refresh the image on all frames. */)
1900 Lisp_Object spec
, frame
;
1902 if (!valid_image_p (spec
))
1903 error ("Invalid image specification");
1908 FOR_EACH_FRAME (tail
, frame
)
1910 struct frame
*f
= XFRAME (frame
);
1911 if (FRAME_WINDOW_P (f
))
1912 uncache_image (f
, spec
);
1916 uncache_image (check_x_frame (frame
), spec
);
1922 /* Compute masks and transform image IMG on frame F, as specified
1923 by the image's specification, */
1926 postprocess_image (f
, img
)
1930 /* Manipulation of the image's mask. */
1933 Lisp_Object conversion
, spec
;
1938 /* `:heuristic-mask t'
1940 means build a mask heuristically.
1941 `:heuristic-mask (R G B)'
1942 `:mask (heuristic (R G B))'
1943 means build a mask from color (R G B) in the
1946 means remove a mask, if any. */
1948 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1950 x_build_heuristic_mask (f
, img
, mask
);
1955 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1957 if (EQ (mask
, Qheuristic
))
1958 x_build_heuristic_mask (f
, img
, Qt
);
1959 else if (CONSP (mask
)
1960 && EQ (XCAR (mask
), Qheuristic
))
1962 if (CONSP (XCDR (mask
)))
1963 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1965 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1967 else if (NILP (mask
) && found_p
&& img
->mask
)
1969 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1970 img
->mask
= NO_PIXMAP
;
1975 /* Should we apply an image transformation algorithm? */
1976 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1977 if (EQ (conversion
, Qdisabled
))
1978 x_disable_image (f
, img
);
1979 else if (EQ (conversion
, Qlaplace
))
1981 else if (EQ (conversion
, Qemboss
))
1983 else if (CONSP (conversion
)
1984 && EQ (XCAR (conversion
), Qedge_detection
))
1987 tem
= XCDR (conversion
);
1989 x_edge_detection (f
, img
,
1990 Fplist_get (tem
, QCmatrix
),
1991 Fplist_get (tem
, QCcolor_adjustment
));
1997 /* Return the id of image with Lisp specification SPEC on frame F.
1998 SPEC must be a valid Lisp image specification (see valid_image_p). */
2001 lookup_image (f
, spec
)
2005 struct image_cache
*c
;
2008 struct gcpro gcpro1
;
2011 /* F must be a window-system frame, and SPEC must be a valid image
2013 xassert (FRAME_WINDOW_P (f
));
2014 xassert (valid_image_p (spec
));
2016 c
= FRAME_IMAGE_CACHE (f
);
2020 /* Look up SPEC in the hash table of the image cache. */
2021 hash
= sxhash (spec
, 0);
2022 img
= search_image_cache (f
, spec
, hash
);
2023 if (img
&& img
->load_failed_p
)
2025 free_image (f
, img
);
2029 /* If not found, create a new image and cache it. */
2032 extern Lisp_Object Qpostscript
;
2035 img
= make_image (spec
, hash
);
2036 cache_image (f
, img
);
2037 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2038 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2039 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2041 /* If we can't load the image, and we don't have a width and
2042 height, use some arbitrary width and height so that we can
2043 draw a rectangle for it. */
2044 if (img
->load_failed_p
)
2048 value
= image_spec_value (spec
, QCwidth
, NULL
);
2049 img
->width
= (INTEGERP (value
)
2050 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2051 value
= image_spec_value (spec
, QCheight
, NULL
);
2052 img
->height
= (INTEGERP (value
)
2053 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2057 /* Handle image type independent image attributes
2058 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2059 `:background COLOR'. */
2060 Lisp_Object ascent
, margin
, relief
, bg
;
2062 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2063 if (INTEGERP (ascent
))
2064 img
->ascent
= XFASTINT (ascent
);
2065 else if (EQ (ascent
, Qcenter
))
2066 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2068 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2069 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2070 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2071 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2072 && INTEGERP (XCDR (margin
)))
2074 if (XINT (XCAR (margin
)) > 0)
2075 img
->hmargin
= XFASTINT (XCAR (margin
));
2076 if (XINT (XCDR (margin
)) > 0)
2077 img
->vmargin
= XFASTINT (XCDR (margin
));
2080 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2081 if (INTEGERP (relief
))
2083 img
->relief
= XINT (relief
);
2084 img
->hmargin
+= eabs (img
->relief
);
2085 img
->vmargin
+= eabs (img
->relief
);
2088 if (! img
->background_valid
)
2090 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2094 = x_alloc_image_color (f
, img
, bg
,
2095 FRAME_BACKGROUND_PIXEL (f
));
2096 img
->background_valid
= 1;
2100 /* Do image transformations and compute masks, unless we
2101 don't have the image yet. */
2102 if (!EQ (*img
->type
->type
, Qpostscript
))
2103 postprocess_image (f
, img
);
2109 /* We're using IMG, so set its timestamp to `now'. */
2110 EMACS_GET_TIME (now
);
2111 img
->timestamp
= EMACS_SECS (now
);
2115 /* Value is the image id. */
2120 /* Cache image IMG in the image cache of frame F. */
2123 cache_image (f
, img
)
2127 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2130 /* Find a free slot in c->images. */
2131 for (i
= 0; i
< c
->used
; ++i
)
2132 if (c
->images
[i
] == NULL
)
2135 /* If no free slot found, maybe enlarge c->images. */
2136 if (i
== c
->used
&& c
->used
== c
->size
)
2139 c
->images
= (struct image
**) xrealloc (c
->images
,
2140 c
->size
* sizeof *c
->images
);
2143 /* Add IMG to c->images, and assign IMG an id. */
2149 /* Add IMG to the cache's hash table. */
2150 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2151 img
->next
= c
->buckets
[i
];
2153 img
->next
->prev
= img
;
2155 c
->buckets
[i
] = img
;
2159 /* Call FN on every image in the image cache of frame F. Used to mark
2160 Lisp Objects in the image cache. */
2162 /* Mark Lisp objects in image IMG. */
2168 mark_object (img
->spec
);
2169 mark_object (img
->dependencies
);
2171 if (!NILP (img
->data
.lisp_val
))
2172 mark_object (img
->data
.lisp_val
);
2177 mark_image_cache (struct image_cache
*c
)
2182 for (i
= 0; i
< c
->used
; ++i
)
2184 mark_image (c
->images
[i
]);
2190 /***********************************************************************
2191 X / NS / W32 support code
2192 ***********************************************************************/
2196 /* Macro for defining functions that will be loaded from image DLLs. */
2197 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2199 /* Macro for loading those image functions from the library. */
2200 #define LOAD_IMGLIB_FN(lib,func) { \
2201 fn_##func = (void *) GetProcAddress (lib, #func); \
2202 if (!fn_##func) return 0; \
2205 /* Load a DLL implementing an image type.
2206 The `image-library-alist' variable associates a symbol,
2207 identifying an image type, to a list of possible filenames.
2208 The function returns NULL if no library could be loaded for
2209 the given image type, or if the library was previously loaded;
2210 else the handle of the DLL. */
2212 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2214 HMODULE library
= NULL
;
2216 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2218 Lisp_Object dlls
= Fassq (type
, libraries
);
2221 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2223 CHECK_STRING_CAR (dlls
);
2224 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2232 #endif /* HAVE_NTGUI */
2234 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2235 XImagePtr
*, Pixmap
*));
2236 static void x_destroy_x_image
P_ ((XImagePtr
));
2237 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2240 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2241 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2242 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2243 via xmalloc. Print error messages via image_error if an error
2244 occurs. Value is non-zero if successful.
2246 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2247 should indicate the bit depth of the image. */
2250 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2252 int width
, height
, depth
;
2256 #ifdef HAVE_X_WINDOWS
2257 Display
*display
= FRAME_X_DISPLAY (f
);
2258 Window window
= FRAME_X_WINDOW (f
);
2259 Screen
*screen
= FRAME_X_SCREEN (f
);
2261 xassert (interrupt_input_blocked
);
2264 depth
= DefaultDepthOfScreen (screen
);
2265 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2266 depth
, ZPixmap
, 0, NULL
, width
, height
,
2267 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2270 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2274 /* Allocate image raster. */
2275 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2277 /* Allocate a pixmap of the same size. */
2278 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2279 if (*pixmap
== NO_PIXMAP
)
2281 x_destroy_x_image (*ximg
);
2283 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2288 #endif /* HAVE_X_WINDOWS */
2292 BITMAPINFOHEADER
*header
;
2294 int scanline_width_bits
;
2296 int palette_colors
= 0;
2301 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2302 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2304 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2308 scanline_width_bits
= width
* depth
;
2309 remainder
= scanline_width_bits
% 32;
2312 scanline_width_bits
+= 32 - remainder
;
2314 /* Bitmaps with a depth less than 16 need a palette. */
2315 /* BITMAPINFO structure already contains the first RGBQUAD. */
2317 palette_colors
= 1 << depth
- 1;
2319 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2322 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2326 header
= &((*ximg
)->info
.bmiHeader
);
2327 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2328 header
->biSize
= sizeof (*header
);
2329 header
->biWidth
= width
;
2330 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2331 header
->biPlanes
= 1;
2332 header
->biBitCount
= depth
;
2333 header
->biCompression
= BI_RGB
;
2334 header
->biClrUsed
= palette_colors
;
2336 /* TODO: fill in palette. */
2339 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2340 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2341 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2342 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2343 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2344 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2345 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2346 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2349 hdc
= get_frame_dc (f
);
2351 /* Create a DIBSection and raster array for the bitmap,
2352 and store its handle in *pixmap. */
2353 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2354 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2355 /* casting avoids a GCC warning */
2356 (void **)&((*ximg
)->data
), NULL
, 0);
2358 /* Realize display palette and garbage all frames. */
2359 release_frame_dc (f
, hdc
);
2361 if (*pixmap
== NULL
)
2363 DWORD err
= GetLastError ();
2364 Lisp_Object errcode
;
2365 /* All system errors are < 10000, so the following is safe. */
2366 XSETINT (errcode
, (int) err
);
2367 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2368 x_destroy_x_image (*ximg
);
2374 #endif /* HAVE_NTGUI */
2377 *pixmap
= ns_image_for_XPM(width
, height
, depth
);
2381 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil
, Qnil
);
2390 /* Destroy XImage XIMG. Free XIMG->data. */
2393 x_destroy_x_image (ximg
)
2396 xassert (interrupt_input_blocked
);
2399 #ifdef HAVE_X_WINDOWS
2402 XDestroyImage (ximg
);
2403 #endif /* HAVE_X_WINDOWS */
2405 /* Data will be freed by DestroyObject. */
2408 #endif /* HAVE_NTGUI */
2410 ns_release_object(ximg
);
2411 #endif /* HAVE_NS */
2416 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2417 are width and height of both the image and pixmap. */
2420 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2426 #ifdef HAVE_X_WINDOWS
2429 xassert (interrupt_input_blocked
);
2430 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2431 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2432 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2433 #endif /* HAVE_X_WINDOWS */
2436 #if 0 /* I don't think this is necessary looking at where it is used. */
2437 HDC hdc
= get_frame_dc (f
);
2438 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2439 release_frame_dc (f
, hdc
);
2441 #endif /* HAVE_NTGUI */
2444 xassert (ximg
== pixmap
);
2445 ns_retain_object(ximg
);
2450 /***********************************************************************
2452 ***********************************************************************/
2454 static unsigned char *slurp_file
P_ ((char *, int *));
2457 /* Find image file FILE. Look in data-directory/images, then
2458 x-bitmap-file-path. Value is the encoded full name of the file
2459 found, or nil if not found. */
2462 x_find_image_file (file
)
2465 Lisp_Object file_found
, search_path
;
2466 struct gcpro gcpro1
, gcpro2
;
2470 /* TODO I think this should use something like image-load-path
2471 instead. Unfortunately, that can contain non-string elements. */
2472 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2474 Vx_bitmap_file_path
);
2475 GCPRO2 (file_found
, search_path
);
2477 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2478 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2484 file_found
= ENCODE_FILE (file_found
);
2493 /* Read FILE into memory. Value is a pointer to a buffer allocated
2494 with xmalloc holding FILE's contents. Value is null if an error
2495 occurred. *SIZE is set to the size of the file. */
2497 static unsigned char *
2498 slurp_file (file
, size
)
2503 unsigned char *buf
= NULL
;
2506 if (stat (file
, &st
) == 0
2507 && (fp
= fopen (file
, "rb")) != NULL
2508 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2509 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2530 /***********************************************************************
2532 ***********************************************************************/
2534 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2535 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2536 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2537 unsigned char *, unsigned char *));
2538 static int xbm_image_p
P_ ((Lisp_Object object
));
2539 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2540 unsigned char *, unsigned char *,
2541 int *, int *, unsigned char **));
2542 static int xbm_file_p
P_ ((Lisp_Object
));
2545 /* Indices of image specification fields in xbm_format, below. */
2547 enum xbm_keyword_index
2565 /* Vector of image_keyword structures describing the format
2566 of valid XBM image specifications. */
2568 static struct image_keyword xbm_format
[XBM_LAST
] =
2570 {":type", IMAGE_SYMBOL_VALUE
, 1},
2571 {":file", IMAGE_STRING_VALUE
, 0},
2572 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2573 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2574 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2575 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2576 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2577 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2578 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2579 {":relief", IMAGE_INTEGER_VALUE
, 0},
2580 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2581 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2582 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2585 /* Structure describing the image type XBM. */
2587 static struct image_type xbm_type
=
2596 /* Tokens returned from xbm_scan. */
2605 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2606 A valid specification is a list starting with the symbol `image'
2607 The rest of the list is a property list which must contain an
2610 If the specification specifies a file to load, it must contain
2611 an entry `:file FILENAME' where FILENAME is a string.
2613 If the specification is for a bitmap loaded from memory it must
2614 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2615 WIDTH and HEIGHT are integers > 0. DATA may be:
2617 1. a string large enough to hold the bitmap data, i.e. it must
2618 have a size >= (WIDTH + 7) / 8 * HEIGHT
2620 2. a bool-vector of size >= WIDTH * HEIGHT
2622 3. a vector of strings or bool-vectors, one for each line of the
2625 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2626 may not be specified in this case because they are defined in the
2629 Both the file and data forms may contain the additional entries
2630 `:background COLOR' and `:foreground COLOR'. If not present,
2631 foreground and background of the frame on which the image is
2632 displayed is used. */
2635 xbm_image_p (object
)
2638 struct image_keyword kw
[XBM_LAST
];
2640 bcopy (xbm_format
, kw
, sizeof kw
);
2641 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2644 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2646 if (kw
[XBM_FILE
].count
)
2648 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2651 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2653 /* In-memory XBM file. */
2654 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2662 /* Entries for `:width', `:height' and `:data' must be present. */
2663 if (!kw
[XBM_WIDTH
].count
2664 || !kw
[XBM_HEIGHT
].count
2665 || !kw
[XBM_DATA
].count
)
2668 data
= kw
[XBM_DATA
].value
;
2669 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2670 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2672 /* Check type of data, and width and height against contents of
2678 /* Number of elements of the vector must be >= height. */
2679 if (XVECTOR (data
)->size
< height
)
2682 /* Each string or bool-vector in data must be large enough
2683 for one line of the image. */
2684 for (i
= 0; i
< height
; ++i
)
2686 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2691 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2694 else if (BOOL_VECTOR_P (elt
))
2696 if (XBOOL_VECTOR (elt
)->size
< width
)
2703 else if (STRINGP (data
))
2706 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2709 else if (BOOL_VECTOR_P (data
))
2711 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2722 /* Scan a bitmap file. FP is the stream to read from. Value is
2723 either an enumerator from enum xbm_token, or a character for a
2724 single-character token, or 0 at end of file. If scanning an
2725 identifier, store the lexeme of the identifier in SVAL. If
2726 scanning a number, store its value in *IVAL. */
2729 xbm_scan (s
, end
, sval
, ival
)
2730 unsigned char **s
, *end
;
2738 /* Skip white space. */
2739 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2744 else if (isdigit (c
))
2746 int value
= 0, digit
;
2748 if (c
== '0' && *s
< end
)
2751 if (c
== 'x' || c
== 'X')
2758 else if (c
>= 'a' && c
<= 'f')
2759 digit
= c
- 'a' + 10;
2760 else if (c
>= 'A' && c
<= 'F')
2761 digit
= c
- 'A' + 10;
2764 value
= 16 * value
+ digit
;
2767 else if (isdigit (c
))
2771 && (c
= *(*s
)++, isdigit (c
)))
2772 value
= 8 * value
+ c
- '0';
2779 && (c
= *(*s
)++, isdigit (c
)))
2780 value
= 10 * value
+ c
- '0';
2788 else if (isalpha (c
) || c
== '_')
2792 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2799 else if (c
== '/' && **s
== '*')
2801 /* C-style comment. */
2803 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2817 /* Create a Windows bitmap from X bitmap data. */
2819 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2821 static unsigned char swap_nibble
[16]
2822 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2823 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2824 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2825 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2827 unsigned char *bits
, *p
;
2830 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2831 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2832 bits
= (unsigned char *) alloca (height
* w2
);
2833 bzero (bits
, height
* w2
);
2834 for (i
= 0; i
< height
; i
++)
2837 for (j
= 0; j
< w1
; j
++)
2839 /* Bitswap XBM bytes to match how Windows does things. */
2840 unsigned char c
= *data
++;
2841 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2842 | (swap_nibble
[(c
>>4) & 0xf]));
2845 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2851 convert_mono_to_color_image (f
, img
, foreground
, background
)
2854 COLORREF foreground
, background
;
2856 HDC hdc
, old_img_dc
, new_img_dc
;
2857 HGDIOBJ old_prev
, new_prev
;
2860 hdc
= get_frame_dc (f
);
2861 old_img_dc
= CreateCompatibleDC (hdc
);
2862 new_img_dc
= CreateCompatibleDC (hdc
);
2863 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2864 release_frame_dc (f
, hdc
);
2865 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2866 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2867 /* Windows convention for mono bitmaps is black = background,
2868 white = foreground. */
2869 SetTextColor (new_img_dc
, background
);
2870 SetBkColor (new_img_dc
, foreground
);
2872 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2875 SelectObject (old_img_dc
, old_prev
);
2876 SelectObject (new_img_dc
, new_prev
);
2877 DeleteDC (old_img_dc
);
2878 DeleteDC (new_img_dc
);
2879 DeleteObject (img
->pixmap
);
2880 if (new_pixmap
== 0)
2881 fprintf (stderr
, "Failed to convert image to color.\n");
2883 img
->pixmap
= new_pixmap
;
2886 #define XBM_BIT_SHUFFLE(b) (~(b))
2890 #define XBM_BIT_SHUFFLE(b) (b)
2892 #endif /* HAVE_NTGUI */
2896 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
2900 RGB_PIXEL_COLOR fg
, bg
;
2901 int non_default_colors
;
2905 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2907 /* If colors were specified, transfer the bitmap to a color one. */
2908 if (non_default_colors
)
2909 convert_mono_to_color_image (f
, img
, fg
, bg
);
2911 #elif defined (HAVE_NS)
2912 img
->pixmap
= ns_image_from_XBM(data
, img
->width
, img
->height
);
2916 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2919 img
->width
, img
->height
,
2921 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2922 #endif /* !HAVE_NTGUI && !HAVE_NS */
2927 /* Replacement for XReadBitmapFileData which isn't available under old
2928 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2929 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2930 the image. Return in *DATA the bitmap data allocated with xmalloc.
2931 Value is non-zero if successful. DATA null means just test if
2932 CONTENTS looks like an in-memory XBM file. */
2935 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
2937 unsigned char *contents
, *end
;
2938 int *width
, *height
;
2939 unsigned char **data
;
2941 unsigned char *s
= contents
;
2942 char buffer
[BUFSIZ
];
2945 int bytes_per_line
, i
, nbytes
;
2951 LA1 = xbm_scan (&s, end, buffer, &value)
2953 #define expect(TOKEN) \
2954 if (LA1 != (TOKEN)) \
2959 #define expect_ident(IDENT) \
2960 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2965 *width
= *height
= -1;
2968 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2970 /* Parse defines for width, height and hot-spots. */
2974 expect_ident ("define");
2975 expect (XBM_TK_IDENT
);
2977 if (LA1
== XBM_TK_NUMBER
)
2979 char *p
= strrchr (buffer
, '_');
2980 p
= p
? p
+ 1 : buffer
;
2981 if (strcmp (p
, "width") == 0)
2983 else if (strcmp (p
, "height") == 0)
2986 expect (XBM_TK_NUMBER
);
2989 if (!check_image_size (f
, *width
, *height
))
2991 else if (data
== NULL
)
2994 /* Parse bits. Must start with `static'. */
2995 expect_ident ("static");
2996 if (LA1
== XBM_TK_IDENT
)
2998 if (strcmp (buffer
, "unsigned") == 0)
3001 expect_ident ("char");
3003 else if (strcmp (buffer
, "short") == 0)
3007 if (*width
% 16 && *width
% 16 < 9)
3010 else if (strcmp (buffer
, "char") == 0)
3018 expect (XBM_TK_IDENT
);
3024 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3025 nbytes
= bytes_per_line
* *height
;
3026 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3030 for (i
= 0; i
< nbytes
; i
+= 2)
3033 expect (XBM_TK_NUMBER
);
3035 *p
++ = XBM_BIT_SHUFFLE (val
);
3036 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3037 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3039 if (LA1
== ',' || LA1
== '}')
3047 for (i
= 0; i
< nbytes
; ++i
)
3050 expect (XBM_TK_NUMBER
);
3052 *p
++ = XBM_BIT_SHUFFLE (val
);
3054 if (LA1
== ',' || LA1
== '}')
3079 /* Load XBM image IMG which will be displayed on frame F from buffer
3080 CONTENTS. END is the end of the buffer. Value is non-zero if
3084 xbm_load_image (f
, img
, contents
, end
)
3087 unsigned char *contents
, *end
;
3090 unsigned char *data
;
3093 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3096 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3097 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3098 int non_default_colors
= 0;
3101 xassert (img
->width
> 0 && img
->height
> 0);
3103 /* Get foreground and background colors, maybe allocate colors. */
3104 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3107 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3108 non_default_colors
= 1;
3110 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3113 background
= x_alloc_image_color (f
, img
, value
, background
);
3114 img
->background
= background
;
3115 img
->background_valid
= 1;
3116 non_default_colors
= 1;
3119 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3120 foreground
, background
,
3121 non_default_colors
);
3124 if (img
->pixmap
== NO_PIXMAP
)
3126 x_clear_image (f
, img
);
3127 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3133 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3139 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3146 return (STRINGP (data
)
3147 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3154 /* Fill image IMG which is used on frame F with pixmap data. Value is
3155 non-zero if successful. */
3163 Lisp_Object file_name
;
3165 xassert (xbm_image_p (img
->spec
));
3167 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3168 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3169 if (STRINGP (file_name
))
3172 unsigned char *contents
;
3174 struct gcpro gcpro1
;
3176 file
= x_find_image_file (file_name
);
3178 if (!STRINGP (file
))
3180 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3185 contents
= slurp_file (SDATA (file
), &size
);
3186 if (contents
== NULL
)
3188 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3193 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3198 struct image_keyword fmt
[XBM_LAST
];
3200 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3201 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3202 int non_default_colors
= 0;
3205 int in_memory_file_p
= 0;
3207 /* See if data looks like an in-memory XBM file. */
3208 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3209 in_memory_file_p
= xbm_file_p (data
);
3211 /* Parse the image specification. */
3212 bcopy (xbm_format
, fmt
, sizeof fmt
);
3213 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3216 /* Get specified width, and height. */
3217 if (!in_memory_file_p
)
3219 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3220 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3221 xassert (img
->width
> 0 && img
->height
> 0);
3224 /* Get foreground and background colors, maybe allocate colors. */
3225 if (fmt
[XBM_FOREGROUND
].count
3226 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3228 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3230 non_default_colors
= 1;
3233 if (fmt
[XBM_BACKGROUND
].count
3234 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3236 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3238 non_default_colors
= 1;
3241 if (in_memory_file_p
)
3242 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3251 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3253 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3254 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3256 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3258 bcopy (SDATA (line
), p
, nbytes
);
3260 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3263 else if (STRINGP (data
))
3264 bits
= SDATA (data
);
3266 bits
= XBOOL_VECTOR (data
)->data
;
3272 /* Windows mono bitmaps are reversed compared with X. */
3273 invertedBits
= bits
;
3274 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3276 bits
= (char *) alloca(nbytes
);
3277 for (i
= 0; i
< nbytes
; i
++)
3278 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3281 /* Create the pixmap. */
3283 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3284 foreground
, background
,
3285 non_default_colors
);
3290 image_error ("Unable to create pixmap for XBM image `%s'",
3292 x_clear_image (f
, img
);
3302 /***********************************************************************
3304 ***********************************************************************/
3306 #if defined (HAVE_XPM) || defined (HAVE_NS)
3308 static int xpm_image_p
P_ ((Lisp_Object object
));
3309 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3310 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3312 #endif /* HAVE_XPM || HAVE_NS */
3316 /* Indicate to xpm.h that we don't have Xlib. */
3318 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3319 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3320 #define XColor xpm_XColor
3321 #define XImage xpm_XImage
3322 #define Display xpm_Display
3323 #define PIXEL_ALREADY_TYPEDEFED
3324 #include "X11/xpm.h"
3329 #undef PIXEL_ALREADY_TYPEDEFED
3331 #include "X11/xpm.h"
3332 #endif /* HAVE_NTGUI */
3333 #endif /* HAVE_XPM */
3335 #if defined (HAVE_XPM) || defined (HAVE_NS)
3336 /* The symbol `xpm' identifying XPM-format images. */
3340 /* Indices of image specification fields in xpm_format, below. */
3342 enum xpm_keyword_index
3358 /* Vector of image_keyword structures describing the format
3359 of valid XPM image specifications. */
3361 static struct image_keyword xpm_format
[XPM_LAST
] =
3363 {":type", IMAGE_SYMBOL_VALUE
, 1},
3364 {":file", IMAGE_STRING_VALUE
, 0},
3365 {":data", IMAGE_STRING_VALUE
, 0},
3366 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3367 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3368 {":relief", IMAGE_INTEGER_VALUE
, 0},
3369 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3370 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3371 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3372 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3373 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3376 /* Structure describing the image type XPM. */
3378 static struct image_type xpm_type
=
3387 #ifdef HAVE_X_WINDOWS
3389 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3390 functions for allocating image colors. Our own functions handle
3391 color allocation failures more gracefully than the ones on the XPM
3394 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3395 #define ALLOC_XPM_COLORS
3397 #endif /* HAVE_X_WINDOWS */
3399 #ifdef ALLOC_XPM_COLORS
3401 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3402 static void xpm_free_color_cache
P_ ((void));
3403 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3404 static int xpm_color_bucket
P_ ((char *));
3405 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3408 /* An entry in a hash table used to cache color definitions of named
3409 colors. This cache is necessary to speed up XPM image loading in
3410 case we do color allocations ourselves. Without it, we would need
3411 a call to XParseColor per pixel in the image. */
3413 struct xpm_cached_color
3415 /* Next in collision chain. */
3416 struct xpm_cached_color
*next
;
3418 /* Color definition (RGB and pixel color). */
3425 /* The hash table used for the color cache, and its bucket vector
3428 #define XPM_COLOR_CACHE_BUCKETS 1001
3429 struct xpm_cached_color
**xpm_color_cache
;
3431 /* Initialize the color cache. */
3434 xpm_init_color_cache (f
, attrs
)
3436 XpmAttributes
*attrs
;
3438 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3439 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3440 memset (xpm_color_cache
, 0, nbytes
);
3441 init_color_table ();
3443 if (attrs
->valuemask
& XpmColorSymbols
)
3448 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3449 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3450 attrs
->colorsymbols
[i
].value
, &color
))
3452 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3454 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3459 /* Free the color cache. */
3462 xpm_free_color_cache ()
3464 struct xpm_cached_color
*p
, *next
;
3467 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3468 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3474 xfree (xpm_color_cache
);
3475 xpm_color_cache
= NULL
;
3476 free_color_table ();
3479 /* Return the bucket index for color named COLOR_NAME in the color
3483 xpm_color_bucket (color_name
)
3489 for (s
= color_name
; *s
; ++s
)
3491 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3495 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3496 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3499 static struct xpm_cached_color
*
3500 xpm_cache_color (f
, color_name
, color
, bucket
)
3507 struct xpm_cached_color
*p
;
3510 bucket
= xpm_color_bucket (color_name
);
3512 nbytes
= sizeof *p
+ strlen (color_name
);
3513 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3514 strcpy (p
->name
, color_name
);
3516 p
->next
= xpm_color_cache
[bucket
];
3517 xpm_color_cache
[bucket
] = p
;
3521 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3522 return the cached definition in *COLOR. Otherwise, make a new
3523 entry in the cache and allocate the color. Value is zero if color
3524 allocation failed. */
3527 xpm_lookup_color (f
, color_name
, color
)
3532 struct xpm_cached_color
*p
;
3533 int h
= xpm_color_bucket (color_name
);
3535 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3536 if (strcmp (p
->name
, color_name
) == 0)
3541 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3544 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3546 p
= xpm_cache_color (f
, color_name
, color
, h
);
3548 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3549 with transparency, and it's useful. */
3550 else if (strcmp ("opaque", color_name
) == 0)
3552 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3553 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3554 p
= xpm_cache_color (f
, color_name
, color
, h
);
3561 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3562 CLOSURE is a pointer to the frame on which we allocate the
3563 color. Return in *COLOR the allocated color. Value is non-zero
3567 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3574 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3578 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3579 is a pointer to the frame on which we allocate the color. Value is
3580 non-zero if successful. */
3583 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3593 #endif /* ALLOC_XPM_COLORS */
3598 /* XPM library details. */
3600 DEF_IMGLIB_FN (XpmFreeAttributes
);
3601 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3602 DEF_IMGLIB_FN (XpmReadFileToImage
);
3603 DEF_IMGLIB_FN (XImageFree
);
3606 init_xpm_functions (Lisp_Object libraries
)
3610 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3613 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3614 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3615 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3616 LOAD_IMGLIB_FN (library
, XImageFree
);
3620 #endif /* HAVE_NTGUI */
3623 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3624 for XPM images. Such a list must consist of conses whose car and
3628 xpm_valid_color_symbols_p (color_symbols
)
3629 Lisp_Object color_symbols
;
3631 while (CONSP (color_symbols
))
3633 Lisp_Object sym
= XCAR (color_symbols
);
3635 || !STRINGP (XCAR (sym
))
3636 || !STRINGP (XCDR (sym
)))
3638 color_symbols
= XCDR (color_symbols
);
3641 return NILP (color_symbols
);
3645 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3648 xpm_image_p (object
)
3651 struct image_keyword fmt
[XPM_LAST
];
3652 bcopy (xpm_format
, fmt
, sizeof fmt
);
3653 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3654 /* Either `:file' or `:data' must be present. */
3655 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3656 /* Either no `:color-symbols' or it's a list of conses
3657 whose car and cdr are strings. */
3658 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3659 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3662 #endif /* HAVE_XPM || HAVE_NS */
3664 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3666 x_create_bitmap_from_xpm_data (f
, bits
)
3670 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3672 XpmAttributes attrs
;
3673 Pixmap bitmap
, mask
;
3675 bzero (&attrs
, sizeof attrs
);
3677 attrs
.visual
= FRAME_X_VISUAL (f
);
3678 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3679 attrs
.valuemask
|= XpmVisual
;
3680 attrs
.valuemask
|= XpmColormap
;
3682 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3683 bits
, &bitmap
, &mask
, &attrs
);
3684 if (rc
!= XpmSuccess
)
3686 XpmFreeAttributes (&attrs
);
3690 id
= x_allocate_bitmap_record (f
);
3691 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3692 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3693 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3694 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3695 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3696 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3697 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3698 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3700 XpmFreeAttributes (&attrs
);
3703 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3705 /* Load image IMG which will be displayed on frame F. Value is
3706 non-zero if successful. */
3716 XpmAttributes attrs
;
3717 Lisp_Object specified_file
, color_symbols
;
3720 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3721 #endif /* HAVE_NTGUI */
3723 /* Configure the XPM lib. Use the visual of frame F. Allocate
3724 close colors. Return colors allocated. */
3725 bzero (&attrs
, sizeof attrs
);
3728 attrs
.visual
= FRAME_X_VISUAL (f
);
3729 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3730 attrs
.valuemask
|= XpmVisual
;
3731 attrs
.valuemask
|= XpmColormap
;
3732 #endif /* HAVE_NTGUI */
3734 #ifdef ALLOC_XPM_COLORS
3735 /* Allocate colors with our own functions which handle
3736 failing color allocation more gracefully. */
3737 attrs
.color_closure
= f
;
3738 attrs
.alloc_color
= xpm_alloc_color
;
3739 attrs
.free_colors
= xpm_free_colors
;
3740 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3741 #else /* not ALLOC_XPM_COLORS */
3742 /* Let the XPM lib allocate colors. */
3743 attrs
.valuemask
|= XpmReturnAllocPixels
;
3744 #ifdef XpmAllocCloseColors
3745 attrs
.alloc_close_colors
= 1;
3746 attrs
.valuemask
|= XpmAllocCloseColors
;
3747 #else /* not XpmAllocCloseColors */
3748 attrs
.closeness
= 600;
3749 attrs
.valuemask
|= XpmCloseness
;
3750 #endif /* not XpmAllocCloseColors */
3751 #endif /* ALLOC_XPM_COLORS */
3753 /* If image specification contains symbolic color definitions, add
3754 these to `attrs'. */
3755 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3756 if (CONSP (color_symbols
))
3759 XpmColorSymbol
*xpm_syms
;
3762 attrs
.valuemask
|= XpmColorSymbols
;
3764 /* Count number of symbols. */
3765 attrs
.numsymbols
= 0;
3766 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3769 /* Allocate an XpmColorSymbol array. */
3770 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3771 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3772 bzero (xpm_syms
, size
);
3773 attrs
.colorsymbols
= xpm_syms
;
3775 /* Fill the color symbol array. */
3776 for (tail
= color_symbols
, i
= 0;
3778 ++i
, tail
= XCDR (tail
))
3780 Lisp_Object name
= XCAR (XCAR (tail
));
3781 Lisp_Object color
= XCDR (XCAR (tail
));
3782 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3783 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3784 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3785 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3789 /* Create a pixmap for the image, either from a file, or from a
3790 string buffer containing data in the same format as an XPM file. */
3791 #ifdef ALLOC_XPM_COLORS
3792 xpm_init_color_cache (f
, &attrs
);
3795 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3799 HDC frame_dc
= get_frame_dc (f
);
3800 hdc
= CreateCompatibleDC (frame_dc
);
3801 release_frame_dc (f
, frame_dc
);
3803 #endif /* HAVE_NTGUI */
3805 if (STRINGP (specified_file
))
3807 Lisp_Object file
= x_find_image_file (specified_file
);
3808 if (!STRINGP (file
))
3810 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3815 /* XpmReadFileToPixmap is not available in the Windows port of
3816 libxpm. But XpmReadFileToImage almost does what we want. */
3817 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3818 &xpm_image
, &xpm_mask
,
3821 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3822 SDATA (file
), &img
->pixmap
, &img
->mask
,
3824 #endif /* HAVE_NTGUI */
3828 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3830 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3831 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3832 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3833 &xpm_image
, &xpm_mask
,
3836 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3838 &img
->pixmap
, &img
->mask
,
3840 #endif /* HAVE_NTGUI */
3843 if (rc
== XpmSuccess
)
3845 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3846 img
->colors
= colors_in_color_table (&img
->ncolors
);
3847 #else /* not ALLOC_XPM_COLORS */
3851 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3852 plus some duplicate attributes. */
3853 if (xpm_image
&& xpm_image
->bitmap
)
3855 img
->pixmap
= xpm_image
->bitmap
;
3856 /* XImageFree in libXpm frees XImage struct without destroying
3857 the bitmap, which is what we want. */
3858 fn_XImageFree (xpm_image
);
3860 if (xpm_mask
&& xpm_mask
->bitmap
)
3862 /* The mask appears to be inverted compared with what we expect.
3863 TODO: invert our expectations. See other places where we
3864 have to invert bits because our idea of masks is backwards. */
3866 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3868 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3869 SelectObject (hdc
, old_obj
);
3871 img
->mask
= xpm_mask
->bitmap
;
3872 fn_XImageFree (xpm_mask
);
3877 #endif /* HAVE_NTGUI */
3879 /* Remember allocated colors. */
3880 img
->ncolors
= attrs
.nalloc_pixels
;
3881 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3882 * sizeof *img
->colors
);
3883 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3885 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3886 #ifdef DEBUG_X_COLORS
3887 register_color (img
->colors
[i
]);
3890 #endif /* not ALLOC_XPM_COLORS */
3892 img
->width
= attrs
.width
;
3893 img
->height
= attrs
.height
;
3894 xassert (img
->width
> 0 && img
->height
> 0);
3896 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3898 fn_XpmFreeAttributes (&attrs
);
3900 XpmFreeAttributes (&attrs
);
3901 #endif /* HAVE_NTGUI */
3907 #endif /* HAVE_NTGUI */
3912 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3915 case XpmFileInvalid
:
3916 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3920 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3923 case XpmColorFailed
:
3924 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3928 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3933 #ifdef ALLOC_XPM_COLORS
3934 xpm_free_color_cache ();
3936 return rc
== XpmSuccess
;
3939 #endif /* HAVE_XPM */
3941 #if defined (HAVE_NS) && !defined (HAVE_XPM)
3943 /* XPM support functions for NS where libxpm is not available.
3944 Only XPM version 3 (without any extensions) is supported. */
3946 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
3947 const unsigned char **, int *));
3948 static Lisp_Object xpm_make_color_table_v
3949 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3950 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3951 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
3953 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3954 const unsigned char *, int));
3955 static Lisp_Object xpm_make_color_table_h
3956 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3957 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3958 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
3960 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3961 const unsigned char *, int));
3962 static int xpm_str_to_color_key
P_ ((const char *));
3963 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3964 const unsigned char *, const unsigned char *));
3966 /* Tokens returned from xpm_scan. */
3975 /* Scan an XPM data and return a character (< 256) or a token defined
3976 by enum xpm_token above. *S and END are the start (inclusive) and
3977 the end (exclusive) addresses of the data, respectively. Advance
3978 *S while scanning. If token is either XPM_TK_IDENT or
3979 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3980 length of the corresponding token, respectively. */
3983 xpm_scan (s
, end
, beg
, len
)
3984 const unsigned char **s
, *end
, **beg
;
3991 /* Skip white-space. */
3992 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3995 /* gnus-pointer.xpm uses '-' in its identifier.
3996 sb-dir-plus.xpm uses '+' in its identifier. */
3997 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4001 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4004 return XPM_TK_IDENT
;
4009 while (*s
< end
&& **s
!= '"')
4014 return XPM_TK_STRING
;
4018 if (*s
< end
&& **s
== '*')
4020 /* C-style comment. */
4024 while (*s
< end
&& *(*s
)++ != '*')
4027 while (*s
< end
&& **s
!= '/');
4041 /* Functions for color table lookup in XPM data. A key is a string
4042 specifying the color of each pixel in XPM data. A value is either
4043 an integer that specifies a pixel color, Qt that specifies
4044 transparency, or Qnil for the unspecified color. If the length of
4045 the key string is one, a vector is used as a table. Otherwise, a
4046 hash table is used. */
4049 xpm_make_color_table_v (put_func
, get_func
)
4050 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4051 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4053 *put_func
= xpm_put_color_table_v
;
4054 *get_func
= xpm_get_color_table_v
;
4055 return Fmake_vector (make_number (256), Qnil
);
4059 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4060 Lisp_Object color_table
;
4061 const unsigned char *chars_start
;
4065 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4069 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4070 Lisp_Object color_table
;
4071 const unsigned char *chars_start
;
4074 return XVECTOR (color_table
)->contents
[*chars_start
];
4078 xpm_make_color_table_h (put_func
, get_func
)
4079 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4080 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4082 *put_func
= xpm_put_color_table_h
;
4083 *get_func
= xpm_get_color_table_h
;
4084 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4085 make_float (DEFAULT_REHASH_SIZE
),
4086 make_float (DEFAULT_REHASH_THRESHOLD
),
4091 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4092 Lisp_Object color_table
;
4093 const unsigned char *chars_start
;
4097 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4099 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4101 hash_lookup (table
, chars
, &hash_code
);
4102 hash_put (table
, chars
, color
, hash_code
);
4106 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4107 Lisp_Object color_table
;
4108 const unsigned char *chars_start
;
4111 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4112 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4115 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4118 enum xpm_color_key
{
4126 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4129 xpm_str_to_color_key (s
)
4135 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4137 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4143 xpm_load_image (f
, img
, contents
, end
)
4146 const unsigned char *contents
, *end
;
4148 const unsigned char *s
= contents
, *beg
, *str
;
4149 unsigned char buffer
[BUFSIZ
];
4150 int width
, height
, x
, y
;
4151 int num_colors
, chars_per_pixel
;
4153 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4154 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4155 Lisp_Object frame
, color_symbols
, color_table
;
4156 int best_key
, have_mask
= 0;
4157 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4160 LA1 = xpm_scan (&s, end, &beg, &len)
4162 #define expect(TOKEN) \
4163 if (LA1 != (TOKEN)) \
4168 #define expect_ident(IDENT) \
4169 if (LA1 == XPM_TK_IDENT \
4170 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4175 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4179 expect_ident ("static");
4180 expect_ident ("char");
4182 expect (XPM_TK_IDENT
);
4187 expect (XPM_TK_STRING
);
4190 memcpy (buffer
, beg
, len
);
4192 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4193 &num_colors
, &chars_per_pixel
) != 4
4194 || width
<= 0 || height
<= 0
4195 || num_colors
<= 0 || chars_per_pixel
<= 0)
4198 if (!check_image_size (f
, width
, height
))
4200 image_error ("Invalid image size", Qnil
, Qnil
);
4206 XSETFRAME (frame
, f
);
4207 if (!NILP (Fxw_display_color_p (frame
)))
4208 best_key
= XPM_COLOR_KEY_C
;
4209 else if (!NILP (Fx_display_grayscale_p (frame
)))
4210 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4211 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4213 best_key
= XPM_COLOR_KEY_M
;
4215 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4216 if (chars_per_pixel
== 1)
4217 color_table
= xpm_make_color_table_v (&put_color_table
,
4220 color_table
= xpm_make_color_table_h (&put_color_table
,
4223 while (num_colors
-- > 0)
4225 unsigned char *color
, *max_color
;
4226 int key
, next_key
, max_key
= 0;
4227 Lisp_Object symbol_color
= Qnil
, color_val
;
4230 expect (XPM_TK_STRING
);
4231 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4233 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4234 buffer
[len
- chars_per_pixel
] = '\0';
4236 str
= strtok (buffer
, " \t");
4239 key
= xpm_str_to_color_key (str
);
4244 color
= strtok (NULL
, " \t");
4248 while ((str
= strtok (NULL
, " \t")) != NULL
)
4250 next_key
= xpm_str_to_color_key (str
);
4253 color
[strlen (color
)] = ' ';
4256 if (key
== XPM_COLOR_KEY_S
)
4258 if (NILP (symbol_color
))
4259 symbol_color
= build_string (color
);
4261 else if (max_key
< key
&& key
<= best_key
)
4271 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4273 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4275 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4277 if (xstrcasecmp (SDATA (XCDR (specified_color
)), "None") == 0)
4279 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4281 color_val
= make_number (cdef
.pixel
);
4284 if (NILP (color_val
) && max_key
> 0)
4286 if (xstrcasecmp (max_color
, "None") == 0)
4288 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4289 color_val
= make_number (cdef
.pixel
);
4291 if (!NILP (color_val
))
4292 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4297 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4298 &ximg
, &img
->pixmap
)
4300 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4301 &mask_img
, &img
->mask
)
4305 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4309 for (y
= 0; y
< height
; y
++)
4311 expect (XPM_TK_STRING
);
4313 if (len
< width
* chars_per_pixel
)
4315 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4317 Lisp_Object color_val
=
4318 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4320 XPutPixel (ximg
, x
, y
,
4321 (INTEGERP (color_val
) ? XINT (color_val
)
4322 : FRAME_FOREGROUND_PIXEL (f
)));
4324 XPutPixel (mask_img
, x
, y
,
4325 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4326 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4328 if (EQ(color_val
, Qt
))
4329 ns_set_alpha(ximg
, x
, y
, 0);
4337 img
->height
= height
;
4339 /* Maybe fill in the background field while we have ximg handy. */
4340 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4341 IMAGE_BACKGROUND (img
, f
, ximg
);
4343 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4344 x_destroy_x_image (ximg
);
4348 /* Fill in the background_transparent field while we have the
4350 image_background_transparent (img
, f
, mask_img
);
4352 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4353 x_destroy_x_image (mask_img
);
4357 x_destroy_x_image (mask_img
);
4358 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4359 img
->mask
= NO_PIXMAP
;
4365 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4367 x_destroy_x_image (ximg
);
4368 x_destroy_x_image (mask_img
);
4369 x_clear_image (f
, img
);
4383 Lisp_Object file_name
;
4385 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4386 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4387 if (STRINGP (file_name
))
4390 unsigned char *contents
;
4392 struct gcpro gcpro1
;
4394 file
= x_find_image_file (file_name
);
4396 if (!STRINGP (file
))
4398 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4403 contents
= slurp_file (SDATA (file
), &size
);
4404 if (contents
== NULL
)
4406 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4411 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4419 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4420 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4421 SDATA (data
) + SBYTES (data
));
4427 #endif /* HAVE_NS && !HAVE_XPM */
4431 /***********************************************************************
4433 ***********************************************************************/
4435 #ifdef COLOR_TABLE_SUPPORT
4437 /* An entry in the color table mapping an RGB color to a pixel color. */
4442 unsigned long pixel
;
4444 /* Next in color table collision list. */
4445 struct ct_color
*next
;
4448 /* The bucket vector size to use. Must be prime. */
4452 /* Value is a hash of the RGB color given by R, G, and B. */
4454 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4456 /* The color hash table. */
4458 struct ct_color
**ct_table
;
4460 /* Number of entries in the color table. */
4462 int ct_colors_allocated
;
4464 /* Initialize the color table. */
4469 int size
= CT_SIZE
* sizeof (*ct_table
);
4470 ct_table
= (struct ct_color
**) xmalloc (size
);
4471 bzero (ct_table
, size
);
4472 ct_colors_allocated
= 0;
4476 /* Free memory associated with the color table. */
4482 struct ct_color
*p
, *next
;
4484 for (i
= 0; i
< CT_SIZE
; ++i
)
4485 for (p
= ct_table
[i
]; p
; p
= next
)
4496 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4497 entry for that color already is in the color table, return the
4498 pixel color of that entry. Otherwise, allocate a new color for R,
4499 G, B, and make an entry in the color table. */
4501 static unsigned long
4502 lookup_rgb_color (f
, r
, g
, b
)
4506 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4507 int i
= hash
% CT_SIZE
;
4509 Display_Info
*dpyinfo
;
4511 /* Handle TrueColor visuals specially, which improves performance by
4512 two orders of magnitude. Freeing colors on TrueColor visuals is
4513 a nop, and pixel colors specify RGB values directly. See also
4514 the Xlib spec, chapter 3.1. */
4515 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4516 if (dpyinfo
->red_bits
> 0)
4518 unsigned long pr
, pg
, pb
;
4520 /* Apply gamma-correction like normal color allocation does. */
4524 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4525 gamma_correct (f
, &color
);
4526 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4529 /* Scale down RGB values to the visual's bits per RGB, and shift
4530 them to the right position in the pixel color. Note that the
4531 original RGB values are 16-bit values, as usual in X. */
4532 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4533 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4534 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4536 /* Assemble the pixel color. */
4537 return pr
| pg
| pb
;
4540 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4541 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4547 #ifdef HAVE_X_WINDOWS
4556 cmap
= FRAME_X_COLORMAP (f
);
4557 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4560 ++ct_colors_allocated
;
4561 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4565 p
->pixel
= color
.pixel
;
4566 p
->next
= ct_table
[i
];
4570 return FRAME_FOREGROUND_PIXEL (f
);
4575 color
= PALETTERGB (r
, g
, b
);
4577 color
= RGB_TO_ULONG (r
, g
, b
);
4578 #endif /* HAVE_NTGUI */
4579 ++ct_colors_allocated
;
4580 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4585 p
->next
= ct_table
[i
];
4587 #endif /* HAVE_X_WINDOWS */
4595 /* Look up pixel color PIXEL which is used on frame F in the color
4596 table. If not already present, allocate it. Value is PIXEL. */
4598 static unsigned long
4599 lookup_pixel_color (f
, pixel
)
4601 unsigned long pixel
;
4603 int i
= pixel
% CT_SIZE
;
4606 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4607 if (p
->pixel
== pixel
)
4616 #ifdef HAVE_X_WINDOWS
4617 cmap
= FRAME_X_COLORMAP (f
);
4618 color
.pixel
= pixel
;
4619 x_query_color (f
, &color
);
4620 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4623 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4624 color
.pixel
= pixel
;
4625 XQueryColor (NULL
, cmap
, &color
);
4626 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4628 #endif /* HAVE_X_WINDOWS */
4632 ++ct_colors_allocated
;
4634 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4639 p
->next
= ct_table
[i
];
4643 return FRAME_FOREGROUND_PIXEL (f
);
4649 /* Value is a vector of all pixel colors contained in the color table,
4650 allocated via xmalloc. Set *N to the number of colors. */
4652 static unsigned long *
4653 colors_in_color_table (n
)
4658 unsigned long *colors
;
4660 if (ct_colors_allocated
== 0)
4667 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4669 *n
= ct_colors_allocated
;
4671 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4672 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4673 colors
[j
++] = p
->pixel
;
4679 #else /* COLOR_TABLE_SUPPORT */
4681 static unsigned long
4682 lookup_rgb_color (f
, r
, g
, b
)
4686 unsigned long pixel
;
4689 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4690 #endif /* HAVE_NTGUI */
4693 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4694 #endif /* HAVE_NS */
4702 #endif /* COLOR_TABLE_SUPPORT */
4705 /***********************************************************************
4707 ***********************************************************************/
4709 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4710 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4711 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4714 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4715 #endif /* HAVE_NTGUI */
4717 /* Non-zero means draw a cross on images having `:conversion
4720 int cross_disabled_images
;
4722 /* Edge detection matrices for different edge-detection
4725 static int emboss_matrix
[9] = {
4727 2, -1, 0, /* y - 1 */
4729 0, 1, -2 /* y + 1 */
4732 static int laplace_matrix
[9] = {
4734 1, 0, 0, /* y - 1 */
4736 0, 0, -1 /* y + 1 */
4739 /* Value is the intensity of the color whose red/green/blue values
4742 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4745 /* On frame F, return an array of XColor structures describing image
4746 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4747 non-zero means also fill the red/green/blue members of the XColor
4748 structures. Value is a pointer to the array of XColors structures,
4749 allocated with xmalloc; it must be freed by the caller. */
4752 x_to_xcolors (f
, img
, rgb_p
)
4759 XImagePtr_or_DC ximg
;
4763 #endif /* HAVE_NTGUI */
4765 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4768 /* Get the X image IMG->pixmap. */
4769 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4770 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4772 /* Load the image into a memory device context. */
4773 hdc
= get_frame_dc (f
);
4774 ximg
= CreateCompatibleDC (hdc
);
4775 release_frame_dc (f
, hdc
);
4776 prev
= SelectObject (ximg
, img
->pixmap
);
4777 #endif /* HAVE_NTGUI */
4779 /* Fill the `pixel' members of the XColor array. I wished there
4780 were an easy and portable way to circumvent XGetPixel. */
4782 for (y
= 0; y
< img
->height
; ++y
)
4786 #ifdef HAVE_X_WINDOWS
4787 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4788 p
->pixel
= XGetPixel (ximg
, x
, y
);
4790 x_query_colors (f
, row
, img
->width
);
4794 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4796 /* W32_TODO: palette support needed here? */
4797 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4800 #if defined (HAVE_NS)
4801 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4802 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4803 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4804 #endif /* HAVE_NS */
4806 p
->red
= 256 * GetRValue (p
->pixel
);
4807 p
->green
= 256 * GetGValue (p
->pixel
);
4808 p
->blue
= 256 * GetBValue (p
->pixel
);
4809 #endif /* HAVE_NTGUI */
4812 #endif /* HAVE_X_WINDOWS */
4815 Destroy_Image (ximg
, prev
);
4822 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4823 created with CreateDIBSection, with the pointer to the bit values
4824 stored in ximg->data. */
4827 XPutPixel (ximg
, x
, y
, color
)
4832 int width
= ximg
->info
.bmiHeader
.biWidth
;
4833 int height
= ximg
->info
.bmiHeader
.biHeight
;
4834 unsigned char * pixel
;
4836 /* True color images. */
4837 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4839 int rowbytes
= width
* 3;
4840 /* Ensure scanlines are aligned on 4 byte boundaries. */
4842 rowbytes
+= 4 - (rowbytes
% 4);
4844 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4845 /* Windows bitmaps are in BGR order. */
4846 *pixel
= GetBValue (color
);
4847 *(pixel
+ 1) = GetGValue (color
);
4848 *(pixel
+ 2) = GetRValue (color
);
4850 /* Monochrome images. */
4851 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4853 int rowbytes
= width
/ 8;
4854 /* Ensure scanlines are aligned on 4 byte boundaries. */
4856 rowbytes
+= 4 - (rowbytes
% 4);
4857 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4858 /* Filter out palette info. */
4859 if (color
& 0x00ffffff)
4860 *pixel
= *pixel
| (1 << x
% 8);
4862 *pixel
= *pixel
& ~(1 << x
% 8);
4865 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4868 #endif /* HAVE_NTGUI */
4870 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4871 RGB members are set. F is the frame on which this all happens.
4872 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4875 x_from_xcolors (f
, img
, colors
)
4881 XImagePtr oimg
= NULL
;
4885 init_color_table ();
4887 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4890 for (y
= 0; y
< img
->height
; ++y
)
4891 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4893 unsigned long pixel
;
4894 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4895 XPutPixel (oimg
, x
, y
, pixel
);
4899 x_clear_image_1 (f
, img
, 1, 0, 1);
4901 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4902 x_destroy_x_image (oimg
);
4903 img
->pixmap
= pixmap
;
4904 #ifdef COLOR_TABLE_SUPPORT
4905 img
->colors
= colors_in_color_table (&img
->ncolors
);
4906 free_color_table ();
4907 #endif /* COLOR_TABLE_SUPPORT */
4911 /* On frame F, perform edge-detection on image IMG.
4913 MATRIX is a nine-element array specifying the transformation
4914 matrix. See emboss_matrix for an example.
4916 COLOR_ADJUST is a color adjustment added to each pixel of the
4920 x_detect_edges (f
, img
, matrix
, color_adjust
)
4923 int matrix
[9], color_adjust
;
4925 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4929 for (i
= sum
= 0; i
< 9; ++i
)
4930 sum
+= eabs (matrix
[i
]);
4932 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4934 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4936 for (y
= 0; y
< img
->height
; ++y
)
4938 p
= COLOR (new, 0, y
);
4939 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4940 p
= COLOR (new, img
->width
- 1, y
);
4941 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4944 for (x
= 1; x
< img
->width
- 1; ++x
)
4946 p
= COLOR (new, x
, 0);
4947 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4948 p
= COLOR (new, x
, img
->height
- 1);
4949 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4952 for (y
= 1; y
< img
->height
- 1; ++y
)
4954 p
= COLOR (new, 1, y
);
4956 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4958 int r
, g
, b
, y1
, x1
;
4961 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4962 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4965 XColor
*t
= COLOR (colors
, x1
, y1
);
4966 r
+= matrix
[i
] * t
->red
;
4967 g
+= matrix
[i
] * t
->green
;
4968 b
+= matrix
[i
] * t
->blue
;
4971 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4972 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4973 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4974 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4979 x_from_xcolors (f
, img
, new);
4985 /* Perform the pre-defined `emboss' edge-detection on image IMG
4993 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4997 /* Transform image IMG which is used on frame F with a Laplace
4998 edge-detection algorithm. The result is an image that can be used
4999 to draw disabled buttons, for example. */
5006 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5010 /* Perform edge-detection on image IMG on frame F, with specified
5011 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5013 MATRIX must be either
5015 - a list of at least 9 numbers in row-major form
5016 - a vector of at least 9 numbers
5018 COLOR_ADJUST nil means use a default; otherwise it must be a
5022 x_edge_detection (f
, img
, matrix
, color_adjust
)
5025 Lisp_Object matrix
, color_adjust
;
5033 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5034 ++i
, matrix
= XCDR (matrix
))
5035 trans
[i
] = XFLOATINT (XCAR (matrix
));
5037 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5039 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5040 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5043 if (NILP (color_adjust
))
5044 color_adjust
= make_number (0xffff / 2);
5046 if (i
== 9 && NUMBERP (color_adjust
))
5047 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5051 /* Transform image IMG on frame F so that it looks disabled. */
5054 x_disable_image (f
, img
)
5058 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5060 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5062 int n_planes
= dpyinfo
->n_planes
;
5063 #endif /* HAVE_NTGUI */
5067 /* Color (or grayscale). Convert to gray, and equalize. Just
5068 drawing such images with a stipple can look very odd, so
5069 we're using this method instead. */
5070 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5072 const int h
= 15000;
5073 const int l
= 30000;
5075 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5079 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5080 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5081 p
->red
= p
->green
= p
->blue
= i2
;
5084 x_from_xcolors (f
, img
, colors
);
5087 /* Draw a cross over the disabled image, if we must or if we
5089 if (n_planes
< 2 || cross_disabled_images
)
5092 Display
*dpy
= FRAME_X_DISPLAY (f
);
5095 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5097 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5099 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5100 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5101 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5102 img
->width
- 1, img
->height
- 1);
5103 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5109 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5110 XSetForeground (dpy
, gc
, MaskForeground (f
));
5111 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5112 img
->width
- 1, img
->height
- 1);
5113 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5117 #endif /* !HAVE_NS */
5122 hdc
= get_frame_dc (f
);
5123 bmpdc
= CreateCompatibleDC (hdc
);
5124 release_frame_dc (f
, hdc
);
5126 prev
= SelectObject (bmpdc
, img
->pixmap
);
5128 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5129 MoveToEx (bmpdc
, 0, 0, NULL
);
5130 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5131 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5132 LineTo (bmpdc
, img
->width
- 1, 0);
5136 SelectObject (bmpdc
, img
->mask
);
5137 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5138 MoveToEx (bmpdc
, 0, 0, NULL
);
5139 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5140 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5141 LineTo (bmpdc
, img
->width
- 1, 0);
5143 SelectObject (bmpdc
, prev
);
5145 #endif /* HAVE_NTGUI */
5150 /* Build a mask for image IMG which is used on frame F. FILE is the
5151 name of an image file, for error messages. HOW determines how to
5152 determine the background color of IMG. If it is a list '(R G B)',
5153 with R, G, and B being integers >= 0, take that as the color of the
5154 background. Otherwise, determine the background color of IMG
5155 heuristically. Value is non-zero if successful. */
5158 x_build_heuristic_mask (f
, img
, how
)
5163 XImagePtr_or_DC ximg
;
5171 #endif /* HAVE_NTGUI */
5172 int x
, y
, rc
, use_img_background
;
5173 unsigned long bg
= 0;
5177 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5178 img
->mask
= NO_PIXMAP
;
5179 img
->background_transparent_valid
= 0;
5184 /* Create an image and pixmap serving as mask. */
5185 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5186 &mask_img
, &img
->mask
);
5189 #endif /* !HAVE_NS */
5191 /* Get the X image of IMG->pixmap. */
5192 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5193 img
->width
, img
->height
,
5196 /* Create the bit array serving as mask. */
5197 row_width
= (img
->width
+ 7) / 8;
5198 mask_img
= xmalloc (row_width
* img
->height
);
5199 bzero (mask_img
, row_width
* img
->height
);
5201 /* Create a memory device context for IMG->pixmap. */
5202 frame_dc
= get_frame_dc (f
);
5203 ximg
= CreateCompatibleDC (frame_dc
);
5204 release_frame_dc (f
, frame_dc
);
5205 prev
= SelectObject (ximg
, img
->pixmap
);
5206 #endif /* HAVE_NTGUI */
5208 /* Determine the background color of ximg. If HOW is `(R G B)'
5209 take that as color. Otherwise, use the image's background color. */
5210 use_img_background
= 1;
5216 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5218 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5222 if (i
== 3 && NILP (how
))
5224 char color_name
[30];
5225 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5228 0x00ffffff & /* Filter out palette info. */
5229 #endif /* HAVE_NTGUI */
5230 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5231 use_img_background
= 0;
5235 if (use_img_background
)
5236 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5238 /* Set all bits in mask_img to 1 whose color in ximg is different
5239 from the background color bg. */
5241 for (y
= 0; y
< img
->height
; ++y
)
5242 for (x
= 0; x
< img
->width
; ++x
)
5244 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5245 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5247 if (XGetPixel (ximg
, x
, y
) == bg
)
5248 ns_set_alpha(ximg
, x
, y
, 0);
5249 #endif /* HAVE_NS */
5251 /* Fill in the background_transparent field while we have the mask handy. */
5252 image_background_transparent (img
, f
, mask_img
);
5254 /* Put mask_img into img->mask. */
5255 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5256 x_destroy_x_image (mask_img
);
5257 #endif /* !HAVE_NS */
5259 for (y
= 0; y
< img
->height
; ++y
)
5260 for (x
= 0; x
< img
->width
; ++x
)
5262 COLORREF p
= GetPixel (ximg
, x
, y
);
5264 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5267 /* Create the mask image. */
5268 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5270 /* Fill in the background_transparent field while we have the mask handy. */
5271 SelectObject (ximg
, img
->mask
);
5272 image_background_transparent (img
, f
, ximg
);
5274 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5276 #endif /* HAVE_NTGUI */
5278 Destroy_Image (ximg
, prev
);
5284 /***********************************************************************
5285 PBM (mono, gray, color)
5286 ***********************************************************************/
5288 static int pbm_image_p
P_ ((Lisp_Object object
));
5289 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5290 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5292 /* The symbol `pbm' identifying images of this type. */
5296 /* Indices of image specification fields in gs_format, below. */
5298 enum pbm_keyword_index
5314 /* Vector of image_keyword structures describing the format
5315 of valid user-defined image specifications. */
5317 static struct image_keyword pbm_format
[PBM_LAST
] =
5319 {":type", IMAGE_SYMBOL_VALUE
, 1},
5320 {":file", IMAGE_STRING_VALUE
, 0},
5321 {":data", IMAGE_STRING_VALUE
, 0},
5322 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5323 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5324 {":relief", IMAGE_INTEGER_VALUE
, 0},
5325 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5326 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5327 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5328 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5329 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5332 /* Structure describing the image type `pbm'. */
5334 static struct image_type pbm_type
=
5344 /* Return non-zero if OBJECT is a valid PBM image specification. */
5347 pbm_image_p (object
)
5350 struct image_keyword fmt
[PBM_LAST
];
5352 bcopy (pbm_format
, fmt
, sizeof fmt
);
5354 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5357 /* Must specify either :data or :file. */
5358 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5362 /* Scan a decimal number from *S and return it. Advance *S while
5363 reading the number. END is the end of the string. Value is -1 at
5367 pbm_scan_number (s
, end
)
5368 unsigned char **s
, *end
;
5370 int c
= 0, val
= -1;
5374 /* Skip white-space. */
5375 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5380 /* Skip comment to end of line. */
5381 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5384 else if (isdigit (c
))
5386 /* Read decimal number. */
5388 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5389 val
= 10 * val
+ c
- '0';
5401 #if 0 /* Unused. ++kfs */
5403 /* Read FILE into memory. Value is a pointer to a buffer allocated
5404 with xmalloc holding FILE's contents. Value is null if an error
5405 occurred. *SIZE is set to the size of the file. */
5408 pbm_read_file (file
, size
)
5416 if (stat (SDATA (file
), &st
) == 0
5417 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5418 && (buf
= (char *) xmalloc (st
.st_size
),
5419 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5438 #endif /* HAVE_NTGUI */
5440 /* Load PBM image IMG for use on frame F. */
5448 int width
, height
, max_color_idx
= 0;
5450 Lisp_Object file
, specified_file
;
5451 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5452 struct gcpro gcpro1
;
5453 unsigned char *contents
= NULL
;
5454 unsigned char *end
, *p
;
5457 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5461 if (STRINGP (specified_file
))
5463 file
= x_find_image_file (specified_file
);
5464 if (!STRINGP (file
))
5466 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5471 contents
= slurp_file (SDATA (file
), &size
);
5472 if (contents
== NULL
)
5474 image_error ("Error reading `%s'", file
, Qnil
);
5480 end
= contents
+ size
;
5485 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5487 end
= p
+ SBYTES (data
);
5490 /* Check magic number. */
5491 if (end
- p
< 2 || *p
++ != 'P')
5493 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5503 raw_p
= 0, type
= PBM_MONO
;
5507 raw_p
= 0, type
= PBM_GRAY
;
5511 raw_p
= 0, type
= PBM_COLOR
;
5515 raw_p
= 1, type
= PBM_MONO
;
5519 raw_p
= 1, type
= PBM_GRAY
;
5523 raw_p
= 1, type
= PBM_COLOR
;
5527 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5531 /* Read width, height, maximum color-component. Characters
5532 starting with `#' up to the end of a line are ignored. */
5533 width
= pbm_scan_number (&p
, end
);
5534 height
= pbm_scan_number (&p
, end
);
5536 if (type
!= PBM_MONO
)
5538 max_color_idx
= pbm_scan_number (&p
, end
);
5539 if (max_color_idx
> 65535 || max_color_idx
< 0)
5541 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
5546 if (!check_image_size (f
, width
, height
))
5548 image_error ("Invalid image size", Qnil
, Qnil
);
5552 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5553 &ximg
, &img
->pixmap
))
5556 /* Initialize the color hash table. */
5557 init_color_table ();
5559 if (type
== PBM_MONO
)
5562 struct image_keyword fmt
[PBM_LAST
];
5563 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5564 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5566 /* Parse the image specification. */
5567 bcopy (pbm_format
, fmt
, sizeof fmt
);
5568 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5570 /* Get foreground and background colors, maybe allocate colors. */
5571 if (fmt
[PBM_FOREGROUND
].count
5572 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5573 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5574 if (fmt
[PBM_BACKGROUND
].count
5575 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5577 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5578 img
->background
= bg
;
5579 img
->background_valid
= 1;
5582 for (y
= 0; y
< height
; ++y
)
5583 for (x
= 0; x
< width
; ++x
)
5591 x_destroy_x_image (ximg
);
5592 x_clear_image (f
, img
);
5593 image_error ("Invalid image size in image `%s'",
5603 g
= pbm_scan_number (&p
, end
);
5605 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5610 int expected_size
= height
* width
;
5611 if (max_color_idx
> 255)
5613 if (type
== PBM_COLOR
)
5616 if (raw_p
&& p
+ expected_size
> end
)
5618 x_destroy_x_image (ximg
);
5619 x_clear_image (f
, img
);
5620 image_error ("Invalid image size in image `%s'",
5625 for (y
= 0; y
< height
; ++y
)
5626 for (x
= 0; x
< width
; ++x
)
5630 if (type
== PBM_GRAY
&& raw_p
)
5633 if (max_color_idx
> 255)
5634 r
= g
= b
= r
* 256 + *p
++;
5636 else if (type
== PBM_GRAY
)
5637 r
= g
= b
= pbm_scan_number (&p
, end
);
5641 if (max_color_idx
> 255)
5644 if (max_color_idx
> 255)
5647 if (max_color_idx
> 255)
5652 r
= pbm_scan_number (&p
, end
);
5653 g
= pbm_scan_number (&p
, end
);
5654 b
= pbm_scan_number (&p
, end
);
5657 if (r
< 0 || g
< 0 || b
< 0)
5659 x_destroy_x_image (ximg
);
5660 image_error ("Invalid pixel value in image `%s'",
5665 /* RGB values are now in the range 0..max_color_idx.
5666 Scale this to the range 0..0xffff supported by X. */
5667 r
= (double) r
* 65535 / max_color_idx
;
5668 g
= (double) g
* 65535 / max_color_idx
;
5669 b
= (double) b
* 65535 / max_color_idx
;
5670 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5674 #ifdef COLOR_TABLE_SUPPORT
5675 /* Store in IMG->colors the colors allocated for the image, and
5676 free the color table. */
5677 img
->colors
= colors_in_color_table (&img
->ncolors
);
5678 free_color_table ();
5679 #endif /* COLOR_TABLE_SUPPORT */
5682 img
->height
= height
;
5684 /* Maybe fill in the background field while we have ximg handy. */
5686 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5687 /* Casting avoids a GCC warning. */
5688 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5690 /* Put the image into a pixmap. */
5691 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5692 x_destroy_x_image (ximg
);
5694 /* X and W32 versions did it here, MAC version above. ++kfs
5696 img->height = height; */
5704 /***********************************************************************
5706 ***********************************************************************/
5708 #if defined (HAVE_PNG) || defined (HAVE_NS)
5710 /* Function prototypes. */
5712 static int png_image_p
P_ ((Lisp_Object object
));
5713 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5715 /* The symbol `png' identifying images of this type. */
5719 /* Indices of image specification fields in png_format, below. */
5721 enum png_keyword_index
5736 /* Vector of image_keyword structures describing the format
5737 of valid user-defined image specifications. */
5739 static struct image_keyword png_format
[PNG_LAST
] =
5741 {":type", IMAGE_SYMBOL_VALUE
, 1},
5742 {":data", IMAGE_STRING_VALUE
, 0},
5743 {":file", IMAGE_STRING_VALUE
, 0},
5744 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5745 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5746 {":relief", IMAGE_INTEGER_VALUE
, 0},
5747 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5748 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5749 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5750 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5753 /* Structure describing the image type `png'. */
5755 static struct image_type png_type
=
5764 /* Return non-zero if OBJECT is a valid PNG image specification. */
5767 png_image_p (object
)
5770 struct image_keyword fmt
[PNG_LAST
];
5771 bcopy (png_format
, fmt
, sizeof fmt
);
5773 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5776 /* Must specify either the :data or :file keyword. */
5777 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5780 #endif /* HAVE_PNG || HAVE_NS */
5785 #if defined HAVE_LIBPNG_PNG_H
5786 # include <libpng/png.h>
5792 /* PNG library details. */
5794 DEF_IMGLIB_FN (png_get_io_ptr
);
5795 DEF_IMGLIB_FN (png_check_sig
);
5796 DEF_IMGLIB_FN (png_create_read_struct
);
5797 DEF_IMGLIB_FN (png_create_info_struct
);
5798 DEF_IMGLIB_FN (png_destroy_read_struct
);
5799 DEF_IMGLIB_FN (png_set_read_fn
);
5800 DEF_IMGLIB_FN (png_set_sig_bytes
);
5801 DEF_IMGLIB_FN (png_read_info
);
5802 DEF_IMGLIB_FN (png_get_IHDR
);
5803 DEF_IMGLIB_FN (png_get_valid
);
5804 DEF_IMGLIB_FN (png_set_strip_16
);
5805 DEF_IMGLIB_FN (png_set_expand
);
5806 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5807 DEF_IMGLIB_FN (png_set_background
);
5808 DEF_IMGLIB_FN (png_get_bKGD
);
5809 DEF_IMGLIB_FN (png_read_update_info
);
5810 DEF_IMGLIB_FN (png_get_channels
);
5811 DEF_IMGLIB_FN (png_get_rowbytes
);
5812 DEF_IMGLIB_FN (png_read_image
);
5813 DEF_IMGLIB_FN (png_read_end
);
5814 DEF_IMGLIB_FN (png_error
);
5817 init_png_functions (Lisp_Object libraries
)
5821 /* Try loading libpng under probable names. */
5822 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5825 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5826 LOAD_IMGLIB_FN (library
, png_check_sig
);
5827 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5828 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5829 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5830 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5831 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5832 LOAD_IMGLIB_FN (library
, png_read_info
);
5833 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5834 LOAD_IMGLIB_FN (library
, png_get_valid
);
5835 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5836 LOAD_IMGLIB_FN (library
, png_set_expand
);
5837 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5838 LOAD_IMGLIB_FN (library
, png_set_background
);
5839 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5840 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5841 LOAD_IMGLIB_FN (library
, png_get_channels
);
5842 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5843 LOAD_IMGLIB_FN (library
, png_read_image
);
5844 LOAD_IMGLIB_FN (library
, png_read_end
);
5845 LOAD_IMGLIB_FN (library
, png_error
);
5850 #define fn_png_get_io_ptr png_get_io_ptr
5851 #define fn_png_check_sig png_check_sig
5852 #define fn_png_create_read_struct png_create_read_struct
5853 #define fn_png_create_info_struct png_create_info_struct
5854 #define fn_png_destroy_read_struct png_destroy_read_struct
5855 #define fn_png_set_read_fn png_set_read_fn
5856 #define fn_png_set_sig_bytes png_set_sig_bytes
5857 #define fn_png_read_info png_read_info
5858 #define fn_png_get_IHDR png_get_IHDR
5859 #define fn_png_get_valid png_get_valid
5860 #define fn_png_set_strip_16 png_set_strip_16
5861 #define fn_png_set_expand png_set_expand
5862 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5863 #define fn_png_set_background png_set_background
5864 #define fn_png_get_bKGD png_get_bKGD
5865 #define fn_png_read_update_info png_read_update_info
5866 #define fn_png_get_channels png_get_channels
5867 #define fn_png_get_rowbytes png_get_rowbytes
5868 #define fn_png_read_image png_read_image
5869 #define fn_png_read_end png_read_end
5870 #define fn_png_error png_error
5872 #endif /* HAVE_NTGUI */
5874 /* Error and warning handlers installed when the PNG library
5878 my_png_error (png_ptr
, msg
)
5879 png_struct
*png_ptr
;
5882 xassert (png_ptr
!= NULL
);
5883 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5884 longjmp (png_ptr
->jmpbuf
, 1);
5889 my_png_warning (png_ptr
, msg
)
5890 png_struct
*png_ptr
;
5893 xassert (png_ptr
!= NULL
);
5894 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5897 /* Memory source for PNG decoding. */
5899 struct png_memory_storage
5901 unsigned char *bytes
; /* The data */
5902 size_t len
; /* How big is it? */
5903 int index
; /* Where are we? */
5907 /* Function set as reader function when reading PNG image from memory.
5908 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5909 bytes from the input to DATA. */
5912 png_read_from_memory (png_ptr
, data
, length
)
5913 png_structp png_ptr
;
5917 struct png_memory_storage
*tbr
5918 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5920 if (length
> tbr
->len
- tbr
->index
)
5921 fn_png_error (png_ptr
, "Read error");
5923 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5924 tbr
->index
= tbr
->index
+ length
;
5928 /* Function set as reader function when reading PNG image from a file.
5929 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5930 bytes from the input to DATA. */
5933 png_read_from_file (png_ptr
, data
, length
)
5934 png_structp png_ptr
;
5938 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
5940 if (fread (data
, 1, length
, fp
) < length
)
5941 fn_png_error (png_ptr
, "Read error");
5945 /* Load PNG image IMG for use on frame F. Value is non-zero if
5953 Lisp_Object file
, specified_file
;
5954 Lisp_Object specified_data
;
5956 XImagePtr ximg
, mask_img
= NULL
;
5957 struct gcpro gcpro1
;
5958 png_struct
*png_ptr
= NULL
;
5959 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5960 FILE *volatile fp
= NULL
;
5962 png_byte
* volatile pixels
= NULL
;
5963 png_byte
** volatile rows
= NULL
;
5964 png_uint_32 width
, height
;
5965 int bit_depth
, color_type
, interlace_type
;
5967 png_uint_32 row_bytes
;
5969 struct png_memory_storage tbr
; /* Data to be read */
5971 /* Find out what file to load. */
5972 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5973 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5977 if (NILP (specified_data
))
5979 file
= x_find_image_file (specified_file
);
5980 if (!STRINGP (file
))
5982 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5987 /* Open the image file. */
5988 fp
= fopen (SDATA (file
), "rb");
5991 image_error ("Cannot open image file `%s'", file
, Qnil
);
5996 /* Check PNG signature. */
5997 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5998 || !fn_png_check_sig (sig
, sizeof sig
))
6000 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6008 /* Read from memory. */
6009 tbr
.bytes
= SDATA (specified_data
);
6010 tbr
.len
= SBYTES (specified_data
);
6013 /* Check PNG signature. */
6014 if (tbr
.len
< sizeof sig
6015 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6017 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6022 /* Need to skip past the signature. */
6023 tbr
.bytes
+= sizeof (sig
);
6026 /* Initialize read and info structs for PNG lib. Casting return
6027 value avoids a GCC warning on W32. */
6028 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6033 if (fp
) fclose (fp
);
6038 /* Casting return value avoids a GCC warning on W32. */
6039 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6042 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6043 if (fp
) fclose (fp
);
6048 /* Casting return value avoids a GCC warning on W32. */
6049 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6052 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6053 if (fp
) fclose (fp
);
6058 /* Set error jump-back. We come back here when the PNG library
6059 detects an error. */
6060 if (setjmp (png_ptr
->jmpbuf
))
6064 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6067 if (fp
) fclose (fp
);
6072 /* Read image info. */
6073 if (!NILP (specified_data
))
6074 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6076 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6078 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6079 fn_png_read_info (png_ptr
, info_ptr
);
6080 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6081 &interlace_type
, NULL
, NULL
);
6083 if (!check_image_size (f
, width
, height
))
6086 /* If image contains simply transparency data, we prefer to
6087 construct a clipping mask. */
6088 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6093 /* This function is easier to write if we only have to handle
6094 one data format: RGB or RGBA with 8 bits per channel. Let's
6095 transform other formats into that format. */
6097 /* Strip more than 8 bits per channel. */
6098 if (bit_depth
== 16)
6099 fn_png_set_strip_16 (png_ptr
);
6101 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6103 fn_png_set_expand (png_ptr
);
6105 /* Convert grayscale images to RGB. */
6106 if (color_type
== PNG_COLOR_TYPE_GRAY
6107 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6108 fn_png_set_gray_to_rgb (png_ptr
);
6110 /* Handle alpha channel by combining the image with a background
6111 color. Do this only if a real alpha channel is supplied. For
6112 simple transparency, we prefer a clipping mask. */
6115 /* png_color_16 *image_bg; */
6116 Lisp_Object specified_bg
6117 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6118 int shift
= (bit_depth
== 16) ? 0 : 8;
6120 if (STRINGP (specified_bg
))
6121 /* The user specified `:background', use that. */
6123 /* W32 version incorrectly used COLORREF here!! ++kfs */
6125 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6127 png_color_16 user_bg
;
6129 bzero (&user_bg
, sizeof user_bg
);
6130 user_bg
.red
= color
.red
>> shift
;
6131 user_bg
.green
= color
.green
>> shift
;
6132 user_bg
.blue
= color
.blue
>> shift
;
6134 fn_png_set_background (png_ptr
, &user_bg
,
6135 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6140 /* We use the current frame background, ignoring any default
6141 background color set by the image. */
6142 #ifdef HAVE_X_WINDOWS
6144 png_color_16 frame_background
;
6146 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6147 x_query_color (f
, &color
);
6149 bzero (&frame_background
, sizeof frame_background
);
6150 frame_background
.red
= color
.red
>> shift
;
6151 frame_background
.green
= color
.green
>> shift
;
6152 frame_background
.blue
= color
.blue
>> shift
;
6153 #endif /* HAVE_X_WINDOWS */
6157 png_color_16 frame_background
;
6158 color
= FRAME_BACKGROUND_PIXEL (f
);
6159 #if 0 /* W32 TODO : Colormap support. */
6160 x_query_color (f
, &color
);
6162 bzero (&frame_background
, sizeof frame_background
);
6163 frame_background
.red
= GetRValue (color
);
6164 frame_background
.green
= GetGValue (color
);
6165 frame_background
.blue
= GetBValue (color
);
6166 #endif /* HAVE_NTGUI */
6168 fn_png_set_background (png_ptr
, &frame_background
,
6169 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6173 /* Update info structure. */
6174 fn_png_read_update_info (png_ptr
, info_ptr
);
6176 /* Get number of channels. Valid values are 1 for grayscale images
6177 and images with a palette, 2 for grayscale images with transparency
6178 information (alpha channel), 3 for RGB images, and 4 for RGB
6179 images with alpha channel, i.e. RGBA. If conversions above were
6180 sufficient we should only have 3 or 4 channels here. */
6181 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6182 xassert (channels
== 3 || channels
== 4);
6184 /* Number of bytes needed for one row of the image. */
6185 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6187 /* Allocate memory for the image. */
6188 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6189 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6190 for (i
= 0; i
< height
; ++i
)
6191 rows
[i
] = pixels
+ i
* row_bytes
;
6193 /* Read the entire image. */
6194 fn_png_read_image (png_ptr
, rows
);
6195 fn_png_read_end (png_ptr
, info_ptr
);
6202 /* Create the X image and pixmap. */
6203 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6207 /* Create an image and pixmap serving as mask if the PNG image
6208 contains an alpha channel. */
6211 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6212 &mask_img
, &img
->mask
))
6214 x_destroy_x_image (ximg
);
6215 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6216 img
->pixmap
= NO_PIXMAP
;
6220 /* Fill the X image and mask from PNG data. */
6221 init_color_table ();
6223 for (y
= 0; y
< height
; ++y
)
6225 png_byte
*p
= rows
[y
];
6227 for (x
= 0; x
< width
; ++x
)
6234 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6235 /* An alpha channel, aka mask channel, associates variable
6236 transparency with an image. Where other image formats
6237 support binary transparency---fully transparent or fully
6238 opaque---PNG allows up to 254 levels of partial transparency.
6239 The PNG library implements partial transparency by combining
6240 the image with a specified background color.
6242 I'm not sure how to handle this here nicely: because the
6243 background on which the image is displayed may change, for
6244 real alpha channel support, it would be necessary to create
6245 a new image for each possible background.
6247 What I'm doing now is that a mask is created if we have
6248 boolean transparency information. Otherwise I'm using
6249 the frame's background color to combine the image with. */
6254 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6260 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6261 /* Set IMG's background color from the PNG image, unless the user
6265 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6267 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6268 img
->background_valid
= 1;
6272 #ifdef COLOR_TABLE_SUPPORT
6273 /* Remember colors allocated for this image. */
6274 img
->colors
= colors_in_color_table (&img
->ncolors
);
6275 free_color_table ();
6276 #endif /* COLOR_TABLE_SUPPORT */
6279 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6284 img
->height
= height
;
6286 /* Maybe fill in the background field while we have ximg handy.
6287 Casting avoids a GCC warning. */
6288 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6290 /* Put the image into the pixmap, then free the X image and its buffer. */
6291 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6292 x_destroy_x_image (ximg
);
6294 /* Same for the mask. */
6297 /* Fill in the background_transparent field while we have the
6298 mask handy. Casting avoids a GCC warning. */
6299 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6301 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6302 x_destroy_x_image (mask_img
);
6309 #else /* HAVE_PNG */
6313 png_load (struct frame
*f
, struct image
*img
)
6315 return ns_load_image(f
, img
,
6316 image_spec_value (img
->spec
, QCfile
, NULL
),
6317 image_spec_value (img
->spec
, QCdata
, NULL
));
6319 #endif /* HAVE_NS */
6322 #endif /* !HAVE_PNG */
6326 /***********************************************************************
6328 ***********************************************************************/
6330 #if defined (HAVE_JPEG) || defined (HAVE_NS)
6332 static int jpeg_image_p
P_ ((Lisp_Object object
));
6333 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6335 /* The symbol `jpeg' identifying images of this type. */
6339 /* Indices of image specification fields in gs_format, below. */
6341 enum jpeg_keyword_index
6350 JPEG_HEURISTIC_MASK
,
6356 /* Vector of image_keyword structures describing the format
6357 of valid user-defined image specifications. */
6359 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6361 {":type", IMAGE_SYMBOL_VALUE
, 1},
6362 {":data", IMAGE_STRING_VALUE
, 0},
6363 {":file", IMAGE_STRING_VALUE
, 0},
6364 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6365 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6366 {":relief", IMAGE_INTEGER_VALUE
, 0},
6367 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6368 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6369 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6370 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6373 /* Structure describing the image type `jpeg'. */
6375 static struct image_type jpeg_type
=
6384 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6387 jpeg_image_p (object
)
6390 struct image_keyword fmt
[JPEG_LAST
];
6392 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6394 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6397 /* Must specify either the :data or :file keyword. */
6398 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6401 #endif /* HAVE_JPEG || HAVE_NS */
6405 /* Work around a warning about HAVE_STDLIB_H being redefined in
6407 #ifdef HAVE_STDLIB_H
6408 #define HAVE_STDLIB_H_1
6409 #undef HAVE_STDLIB_H
6410 #endif /* HAVE_STLIB_H */
6412 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6413 /* In older releases of the jpeg library, jpeglib.h will define boolean
6414 differently depending on __WIN32__, so make sure it is defined. */
6418 #include <jpeglib.h>
6422 #ifdef HAVE_STLIB_H_1
6423 #define HAVE_STDLIB_H 1
6428 /* JPEG library details. */
6429 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6430 DEF_IMGLIB_FN (jpeg_start_decompress
);
6431 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6432 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6433 DEF_IMGLIB_FN (jpeg_read_header
);
6434 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6435 DEF_IMGLIB_FN (jpeg_std_error
);
6436 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6439 init_jpeg_functions (Lisp_Object libraries
)
6443 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6446 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6447 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6448 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6449 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6450 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6451 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6452 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6453 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6457 /* Wrapper since we can't directly assign the function pointer
6458 to another function pointer that was declared more completely easily. */
6460 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
6461 j_decompress_ptr cinfo
;
6464 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6469 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6470 #define fn_jpeg_start_decompress jpeg_start_decompress
6471 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6472 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6473 #define fn_jpeg_read_header jpeg_read_header
6474 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6475 #define fn_jpeg_std_error jpeg_std_error
6476 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6478 #endif /* HAVE_NTGUI */
6480 struct my_jpeg_error_mgr
6482 struct jpeg_error_mgr pub
;
6483 jmp_buf setjmp_buffer
;
6488 my_error_exit (cinfo
)
6491 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6492 longjmp (mgr
->setjmp_buffer
, 1);
6496 /* Init source method for JPEG data source manager. Called by
6497 jpeg_read_header() before any data is actually read. See
6498 libjpeg.doc from the JPEG lib distribution. */
6501 our_common_init_source (cinfo
)
6502 j_decompress_ptr cinfo
;
6507 /* Method to terminate data source. Called by
6508 jpeg_finish_decompress() after all data has been processed. */
6511 our_common_term_source (cinfo
)
6512 j_decompress_ptr cinfo
;
6517 /* Fill input buffer method for JPEG data source manager. Called
6518 whenever more data is needed. We read the whole image in one step,
6519 so this only adds a fake end of input marker at the end. */
6521 static JOCTET our_memory_buffer
[2];
6524 our_memory_fill_input_buffer (cinfo
)
6525 j_decompress_ptr cinfo
;
6527 /* Insert a fake EOI marker. */
6528 struct jpeg_source_mgr
*src
= cinfo
->src
;
6530 our_memory_buffer
[0] = (JOCTET
) 0xFF;
6531 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
6533 src
->next_input_byte
= our_memory_buffer
;
6534 src
->bytes_in_buffer
= 2;
6539 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6540 is the JPEG data source manager. */
6543 our_memory_skip_input_data (cinfo
, num_bytes
)
6544 j_decompress_ptr cinfo
;
6547 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6551 if (num_bytes
> src
->bytes_in_buffer
)
6552 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6554 src
->bytes_in_buffer
-= num_bytes
;
6555 src
->next_input_byte
+= num_bytes
;
6560 /* Set up the JPEG lib for reading an image from DATA which contains
6561 LEN bytes. CINFO is the decompression info structure created for
6562 reading the image. */
6565 jpeg_memory_src (cinfo
, data
, len
)
6566 j_decompress_ptr cinfo
;
6570 struct jpeg_source_mgr
*src
;
6572 if (cinfo
->src
== NULL
)
6574 /* First time for this JPEG object? */
6575 cinfo
->src
= (struct jpeg_source_mgr
*)
6576 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6577 sizeof (struct jpeg_source_mgr
));
6578 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6579 src
->next_input_byte
= data
;
6582 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6583 src
->init_source
= our_common_init_source
;
6584 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6585 src
->skip_input_data
= our_memory_skip_input_data
;
6586 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6587 src
->term_source
= our_common_term_source
;
6588 src
->bytes_in_buffer
= len
;
6589 src
->next_input_byte
= data
;
6593 struct jpeg_stdio_mgr
6595 struct jpeg_source_mgr mgr
;
6602 /* Size of buffer to read JPEG from file.
6603 Not too big, as we want to use alloc_small. */
6604 #define JPEG_STDIO_BUFFER_SIZE 8192
6607 /* Fill input buffer method for JPEG data source manager. Called
6608 whenever more data is needed. The data is read from a FILE *. */
6611 our_stdio_fill_input_buffer (cinfo
)
6612 j_decompress_ptr cinfo
;
6614 struct jpeg_stdio_mgr
*src
;
6616 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6621 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6623 src
->mgr
.bytes_in_buffer
= bytes
;
6626 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6628 src
->buffer
[0] = (JOCTET
) 0xFF;
6629 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6630 src
->mgr
.bytes_in_buffer
= 2;
6632 src
->mgr
.next_input_byte
= src
->buffer
;
6639 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6640 is the JPEG data source manager. */
6643 our_stdio_skip_input_data (cinfo
, num_bytes
)
6644 j_decompress_ptr cinfo
;
6647 struct jpeg_stdio_mgr
*src
;
6648 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6650 while (num_bytes
> 0 && !src
->finished
)
6652 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6654 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6655 src
->mgr
.next_input_byte
+= num_bytes
;
6660 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6661 src
->mgr
.bytes_in_buffer
= 0;
6662 src
->mgr
.next_input_byte
= NULL
;
6664 our_stdio_fill_input_buffer (cinfo
);
6670 /* Set up the JPEG lib for reading an image from a FILE *.
6671 CINFO is the decompression info structure created for
6672 reading the image. */
6675 jpeg_file_src (cinfo
, fp
)
6676 j_decompress_ptr cinfo
;
6679 struct jpeg_stdio_mgr
*src
;
6681 if (cinfo
->src
!= NULL
)
6682 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6685 /* First time for this JPEG object? */
6686 cinfo
->src
= (struct jpeg_source_mgr
*)
6687 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6688 sizeof (struct jpeg_stdio_mgr
));
6689 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6690 src
->buffer
= (JOCTET
*)
6691 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6692 JPEG_STDIO_BUFFER_SIZE
);
6697 src
->mgr
.init_source
= our_common_init_source
;
6698 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6699 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6700 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6701 src
->mgr
.term_source
= our_common_term_source
;
6702 src
->mgr
.bytes_in_buffer
= 0;
6703 src
->mgr
.next_input_byte
= NULL
;
6707 /* Load image IMG for use on frame F. Patterned after example.c
6708 from the JPEG lib. */
6715 struct jpeg_decompress_struct cinfo
;
6716 struct my_jpeg_error_mgr mgr
;
6717 Lisp_Object file
, specified_file
;
6718 Lisp_Object specified_data
;
6719 FILE * volatile fp
= NULL
;
6721 int row_stride
, x
, y
;
6722 XImagePtr ximg
= NULL
;
6724 unsigned long *colors
;
6726 struct gcpro gcpro1
;
6728 /* Open the JPEG file. */
6729 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6730 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6734 if (NILP (specified_data
))
6736 file
= x_find_image_file (specified_file
);
6737 if (!STRINGP (file
))
6739 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6744 fp
= fopen (SDATA (file
), "rb");
6747 image_error ("Cannot open `%s'", file
, Qnil
);
6753 /* Customize libjpeg's error handling to call my_error_exit when an
6754 error is detected. This function will perform a longjmp.
6755 Casting return value avoids a GCC warning on W32. */
6756 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
6757 mgr
.pub
.error_exit
= my_error_exit
;
6759 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6763 /* Called from my_error_exit. Display a JPEG error. */
6764 char buffer
[JMSG_LENGTH_MAX
];
6765 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6766 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6767 build_string (buffer
));
6770 /* Close the input file and destroy the JPEG object. */
6772 fclose ((FILE *) fp
);
6773 fn_jpeg_destroy_decompress (&cinfo
);
6775 /* If we already have an XImage, free that. */
6776 x_destroy_x_image (ximg
);
6778 /* Free pixmap and colors. */
6779 x_clear_image (f
, img
);
6785 /* Create the JPEG decompression object. Let it read from fp.
6786 Read the JPEG image header. */
6787 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6789 if (NILP (specified_data
))
6790 jpeg_file_src (&cinfo
, (FILE *) fp
);
6792 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6793 SBYTES (specified_data
));
6795 fn_jpeg_read_header (&cinfo
, 1);
6797 /* Customize decompression so that color quantization will be used.
6798 Start decompression. */
6799 cinfo
.quantize_colors
= 1;
6800 fn_jpeg_start_decompress (&cinfo
);
6801 width
= img
->width
= cinfo
.output_width
;
6802 height
= img
->height
= cinfo
.output_height
;
6804 if (!check_image_size (f
, width
, height
))
6806 image_error ("Invalid image size", Qnil
, Qnil
);
6807 longjmp (mgr
.setjmp_buffer
, 2);
6810 /* Create X image and pixmap. */
6811 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6812 longjmp (mgr
.setjmp_buffer
, 2);
6814 /* Allocate colors. When color quantization is used,
6815 cinfo.actual_number_of_colors has been set with the number of
6816 colors generated, and cinfo.colormap is a two-dimensional array
6817 of color indices in the range 0..cinfo.actual_number_of_colors.
6818 No more than 255 colors will be generated. */
6822 if (cinfo
.out_color_components
> 2)
6823 ir
= 0, ig
= 1, ib
= 2;
6824 else if (cinfo
.out_color_components
> 1)
6825 ir
= 0, ig
= 1, ib
= 0;
6827 ir
= 0, ig
= 0, ib
= 0;
6829 /* Use the color table mechanism because it handles colors that
6830 cannot be allocated nicely. Such colors will be replaced with
6831 a default color, and we don't have to care about which colors
6832 can be freed safely, and which can't. */
6833 init_color_table ();
6834 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6837 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6839 /* Multiply RGB values with 255 because X expects RGB values
6840 in the range 0..0xffff. */
6841 int r
= cinfo
.colormap
[ir
][i
] << 8;
6842 int g
= cinfo
.colormap
[ig
][i
] << 8;
6843 int b
= cinfo
.colormap
[ib
][i
] << 8;
6844 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6847 #ifdef COLOR_TABLE_SUPPORT
6848 /* Remember those colors actually allocated. */
6849 img
->colors
= colors_in_color_table (&img
->ncolors
);
6850 free_color_table ();
6851 #endif /* COLOR_TABLE_SUPPORT */
6855 row_stride
= width
* cinfo
.output_components
;
6856 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6858 for (y
= 0; y
< height
; ++y
)
6860 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6861 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6862 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6866 fn_jpeg_finish_decompress (&cinfo
);
6867 fn_jpeg_destroy_decompress (&cinfo
);
6869 fclose ((FILE *) fp
);
6871 /* Maybe fill in the background field while we have ximg handy. */
6872 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6873 /* Casting avoids a GCC warning. */
6874 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6876 /* Put the image into the pixmap. */
6877 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6878 x_destroy_x_image (ximg
);
6883 #else /* HAVE_JPEG */
6887 jpeg_load (struct frame
*f
, struct image
*img
)
6889 return ns_load_image(f
, img
,
6890 image_spec_value (img
->spec
, QCfile
, NULL
),
6891 image_spec_value (img
->spec
, QCdata
, NULL
));
6893 #endif /* HAVE_NS */
6895 #endif /* !HAVE_JPEG */
6899 /***********************************************************************
6901 ***********************************************************************/
6903 #if defined (HAVE_TIFF) || defined (HAVE_NS)
6905 static int tiff_image_p
P_ ((Lisp_Object object
));
6906 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6908 /* The symbol `tiff' identifying images of this type. */
6912 /* Indices of image specification fields in tiff_format, below. */
6914 enum tiff_keyword_index
6923 TIFF_HEURISTIC_MASK
,
6930 /* Vector of image_keyword structures describing the format
6931 of valid user-defined image specifications. */
6933 static struct image_keyword tiff_format
[TIFF_LAST
] =
6935 {":type", IMAGE_SYMBOL_VALUE
, 1},
6936 {":data", IMAGE_STRING_VALUE
, 0},
6937 {":file", IMAGE_STRING_VALUE
, 0},
6938 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6939 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6940 {":relief", IMAGE_INTEGER_VALUE
, 0},
6941 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6942 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6943 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6944 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6945 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
6948 /* Structure describing the image type `tiff'. */
6950 static struct image_type tiff_type
=
6959 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6962 tiff_image_p (object
)
6965 struct image_keyword fmt
[TIFF_LAST
];
6966 bcopy (tiff_format
, fmt
, sizeof fmt
);
6968 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6971 /* Must specify either the :data or :file keyword. */
6972 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6975 #endif /* HAVE_TIFF || HAVE_NS */
6983 /* TIFF library details. */
6984 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6985 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6986 DEF_IMGLIB_FN (TIFFOpen
);
6987 DEF_IMGLIB_FN (TIFFClientOpen
);
6988 DEF_IMGLIB_FN (TIFFGetField
);
6989 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6990 DEF_IMGLIB_FN (TIFFClose
);
6991 DEF_IMGLIB_FN (TIFFSetDirectory
);
6994 init_tiff_functions (Lisp_Object libraries
)
6998 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7001 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7002 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7003 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7004 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7005 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7006 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7007 LOAD_IMGLIB_FN (library
, TIFFClose
);
7008 LOAD_IMGLIB_FN (library
, TIFFSetDirectory
);
7014 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7015 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7016 #define fn_TIFFOpen TIFFOpen
7017 #define fn_TIFFClientOpen TIFFClientOpen
7018 #define fn_TIFFGetField TIFFGetField
7019 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7020 #define fn_TIFFClose TIFFClose
7021 #define fn_TIFFSetDirectory TIFFSetDirectory
7022 #endif /* HAVE_NTGUI */
7025 /* Reading from a memory buffer for TIFF images Based on the PNG
7026 memory source, but we have to provide a lot of extra functions.
7029 We really only need to implement read and seek, but I am not
7030 convinced that the TIFF library is smart enough not to destroy
7031 itself if we only hand it the function pointers we need to
7036 unsigned char *bytes
;
7043 tiff_read_from_memory (data
, buf
, size
)
7048 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7050 if (size
> src
->len
- src
->index
)
7052 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7058 tiff_write_from_memory (data
, buf
, size
)
7067 tiff_seek_in_memory (data
, off
, whence
)
7072 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7077 case SEEK_SET
: /* Go from beginning of source. */
7081 case SEEK_END
: /* Go from end of source. */
7082 idx
= src
->len
+ off
;
7085 case SEEK_CUR
: /* Go from current position. */
7086 idx
= src
->index
+ off
;
7089 default: /* Invalid `whence'. */
7093 if (idx
> src
->len
|| idx
< 0)
7101 tiff_close_memory (data
)
7109 tiff_mmap_memory (data
, pbase
, psize
)
7114 /* It is already _IN_ memory. */
7119 tiff_unmap_memory (data
, base
, size
)
7124 /* We don't need to do this. */
7128 tiff_size_of_memory (data
)
7131 return ((tiff_memory_source
*) data
)->len
;
7136 tiff_error_handler (title
, format
, ap
)
7137 const char *title
, *format
;
7143 len
= sprintf (buf
, "TIFF error: %s ", title
);
7144 vsprintf (buf
+ len
, format
, ap
);
7145 add_to_log (buf
, Qnil
, Qnil
);
7150 tiff_warning_handler (title
, format
, ap
)
7151 const char *title
, *format
;
7157 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7158 vsprintf (buf
+ len
, format
, ap
);
7159 add_to_log (buf
, Qnil
, Qnil
);
7163 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7171 Lisp_Object file
, specified_file
;
7172 Lisp_Object specified_data
;
7174 int width
, height
, x
, y
, count
;
7178 struct gcpro gcpro1
;
7179 tiff_memory_source memsrc
;
7182 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7183 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7187 fn_TIFFSetErrorHandler (tiff_error_handler
);
7188 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7190 if (NILP (specified_data
))
7192 /* Read from a file */
7193 file
= x_find_image_file (specified_file
);
7194 if (!STRINGP (file
))
7196 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7201 /* Try to open the image file. Casting return value avoids a
7202 GCC warning on W32. */
7203 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7206 image_error ("Cannot open `%s'", file
, Qnil
);
7213 /* Memory source! */
7214 memsrc
.bytes
= SDATA (specified_data
);
7215 memsrc
.len
= SBYTES (specified_data
);
7218 /* Casting return value avoids a GCC warning on W32. */
7219 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7220 (TIFFReadWriteProc
) tiff_read_from_memory
,
7221 (TIFFReadWriteProc
) tiff_write_from_memory
,
7222 tiff_seek_in_memory
,
7224 tiff_size_of_memory
,
7230 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7236 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7237 if (INTEGERP (image
))
7239 int ino
= XFASTINT (image
);
7240 if (!fn_TIFFSetDirectory (tiff
, ino
))
7242 image_error ("Invalid image number `%s' in image `%s'",
7244 fn_TIFFClose (tiff
);
7250 /* Get width and height of the image, and allocate a raster buffer
7251 of width x height 32-bit values. */
7252 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7253 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7255 if (!check_image_size (f
, width
, height
))
7257 image_error ("Invalid image size", Qnil
, Qnil
);
7258 fn_TIFFClose (tiff
);
7263 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7265 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7267 /* Count the number of images in the file. */
7268 for (count
= 1, rc2
= 1; rc2
; count
++)
7269 rc2
= fn_TIFFSetDirectory (tiff
, count
);
7272 img
->data
.lisp_val
= Fcons (Qcount
,
7273 Fcons (make_number (count
),
7274 img
->data
.lisp_val
));
7276 fn_TIFFClose (tiff
);
7279 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7285 /* Create the X image and pixmap. */
7286 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7293 /* Initialize the color table. */
7294 init_color_table ();
7296 /* Process the pixel raster. Origin is in the lower-left corner. */
7297 for (y
= 0; y
< height
; ++y
)
7299 uint32
*row
= buf
+ y
* width
;
7301 for (x
= 0; x
< width
; ++x
)
7303 uint32 abgr
= row
[x
];
7304 int r
= TIFFGetR (abgr
) << 8;
7305 int g
= TIFFGetG (abgr
) << 8;
7306 int b
= TIFFGetB (abgr
) << 8;
7307 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7311 #ifdef COLOR_TABLE_SUPPORT
7312 /* Remember the colors allocated for the image. Free the color table. */
7313 img
->colors
= colors_in_color_table (&img
->ncolors
);
7314 free_color_table ();
7315 #endif /* COLOR_TABLE_SUPPORT */
7318 img
->height
= height
;
7320 /* Maybe fill in the background field while we have ximg handy. */
7321 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7322 /* Casting avoids a GCC warning on W32. */
7323 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7325 /* Put the image into the pixmap, then free the X image and its buffer. */
7326 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7327 x_destroy_x_image (ximg
);
7334 #else /* HAVE_TIFF */
7338 tiff_load (struct frame
*f
, struct image
*img
)
7340 return ns_load_image(f
, img
,
7341 image_spec_value (img
->spec
, QCfile
, NULL
),
7342 image_spec_value (img
->spec
, QCdata
, NULL
));
7344 #endif /* HAVE_NS */
7346 #endif /* !HAVE_TIFF */
7350 /***********************************************************************
7352 ***********************************************************************/
7354 #if defined (HAVE_GIF) || defined (HAVE_NS)
7356 static int gif_image_p
P_ ((Lisp_Object object
));
7357 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7358 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7360 /* The symbol `gif' identifying images of this type. */
7364 /* Indices of image specification fields in gif_format, below. */
7366 enum gif_keyword_index
7382 /* Vector of image_keyword structures describing the format
7383 of valid user-defined image specifications. */
7385 static struct image_keyword gif_format
[GIF_LAST
] =
7387 {":type", IMAGE_SYMBOL_VALUE
, 1},
7388 {":data", IMAGE_STRING_VALUE
, 0},
7389 {":file", IMAGE_STRING_VALUE
, 0},
7390 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7391 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7392 {":relief", IMAGE_INTEGER_VALUE
, 0},
7393 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7394 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7395 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7396 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7397 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7400 /* Structure describing the image type `gif'. */
7402 static struct image_type gif_type
=
7411 /* Free X resources of GIF image IMG which is used on frame F. */
7414 gif_clear_image (f
, img
)
7418 /* IMG->data.ptr_val may contain extension data. */
7419 img
->data
.lisp_val
= Qnil
;
7420 x_clear_image (f
, img
);
7423 /* Return non-zero if OBJECT is a valid GIF image specification. */
7426 gif_image_p (object
)
7429 struct image_keyword fmt
[GIF_LAST
];
7430 bcopy (gif_format
, fmt
, sizeof fmt
);
7432 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7435 /* Must specify either the :data or :file keyword. */
7436 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7439 #endif /* HAVE_GIF */
7443 #if defined (HAVE_NTGUI)
7444 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7445 Undefine before redefining to avoid a preprocessor warning. */
7449 /* avoid conflict with QuickdrawText.h */
7450 #define DrawText gif_DrawText
7451 #include <gif_lib.h>
7454 #else /* HAVE_NTGUI */
7456 #include <gif_lib.h>
7458 #endif /* HAVE_NTGUI */
7463 /* GIF library details. */
7464 DEF_IMGLIB_FN (DGifCloseFile
);
7465 DEF_IMGLIB_FN (DGifSlurp
);
7466 DEF_IMGLIB_FN (DGifOpen
);
7467 DEF_IMGLIB_FN (DGifOpenFileName
);
7470 init_gif_functions (Lisp_Object libraries
)
7474 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7477 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7478 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7479 LOAD_IMGLIB_FN (library
, DGifOpen
);
7480 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7486 #define fn_DGifCloseFile DGifCloseFile
7487 #define fn_DGifSlurp DGifSlurp
7488 #define fn_DGifOpen DGifOpen
7489 #define fn_DGifOpenFileName DGifOpenFileName
7491 #endif /* HAVE_NTGUI */
7493 /* Reading a GIF image from memory
7494 Based on the PNG memory stuff to a certain extent. */
7498 unsigned char *bytes
;
7504 /* Make the current memory source available to gif_read_from_memory.
7505 It's done this way because not all versions of libungif support
7506 a UserData field in the GifFileType structure. */
7507 static gif_memory_source
*current_gif_memory_src
;
7510 gif_read_from_memory (file
, buf
, len
)
7515 gif_memory_source
*src
= current_gif_memory_src
;
7517 if (len
> src
->len
- src
->index
)
7520 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7526 /* Load GIF image IMG for use on frame F. Value is non-zero if
7529 static int interlace_start
[] = {0, 4, 2, 1};
7530 static int interlace_increment
[] = {8, 8, 4, 2};
7537 Lisp_Object file
, specified_file
;
7538 Lisp_Object specified_data
;
7539 int rc
, width
, height
, x
, y
, i
;
7541 ColorMapObject
*gif_color_map
;
7542 unsigned long pixel_colors
[256];
7544 struct gcpro gcpro1
;
7546 int ino
, image_height
, image_width
;
7547 gif_memory_source memsrc
;
7548 unsigned char *raster
;
7550 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7551 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7555 if (NILP (specified_data
))
7557 file
= x_find_image_file (specified_file
);
7558 if (!STRINGP (file
))
7560 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7565 /* Open the GIF file. Casting return value avoids a GCC warning
7567 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7570 image_error ("Cannot open `%s'", file
, Qnil
);
7577 /* Read from memory! */
7578 current_gif_memory_src
= &memsrc
;
7579 memsrc
.bytes
= SDATA (specified_data
);
7580 memsrc
.len
= SBYTES (specified_data
);
7583 /* Casting return value avoids a GCC warning on W32. */
7584 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
7587 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7593 /* Before reading entire contents, check the declared image size. */
7594 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7596 image_error ("Invalid image size", Qnil
, Qnil
);
7597 fn_DGifCloseFile (gif
);
7602 /* Read entire contents. */
7603 rc
= fn_DGifSlurp (gif
);
7604 if (rc
== GIF_ERROR
)
7606 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7607 fn_DGifCloseFile (gif
);
7612 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7613 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7614 if (ino
>= gif
->ImageCount
)
7616 image_error ("Invalid image number `%s' in image `%s'",
7618 fn_DGifCloseFile (gif
);
7623 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7624 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7625 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7626 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7627 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7628 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7630 width
= img
->width
= max (gif
->SWidth
,
7631 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7632 img
->corners
[RIGHT_CORNER
]));
7633 height
= img
->height
= max (gif
->SHeight
,
7634 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7635 img
->corners
[BOT_CORNER
]));
7637 if (!check_image_size (f
, width
, height
))
7639 image_error ("Invalid image size", Qnil
, Qnil
);
7640 fn_DGifCloseFile (gif
);
7645 /* Create the X image and pixmap. */
7646 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7648 fn_DGifCloseFile (gif
);
7653 /* Allocate colors. */
7654 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7656 gif_color_map
= gif
->SColorMap
;
7657 init_color_table ();
7658 bzero (pixel_colors
, sizeof pixel_colors
);
7661 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7663 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7664 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7665 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7666 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7669 #ifdef COLOR_TABLE_SUPPORT
7670 img
->colors
= colors_in_color_table (&img
->ncolors
);
7671 free_color_table ();
7672 #endif /* COLOR_TABLE_SUPPORT */
7674 /* Clear the part of the screen image that are not covered by
7675 the image from the GIF file. Full animated GIF support
7676 requires more than can be done here (see the gif89 spec,
7677 disposal methods). Let's simply assume that the part
7678 not covered by a sub-image is in the frame's background color. */
7679 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7680 for (x
= 0; x
< width
; ++x
)
7681 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7683 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7684 for (x
= 0; x
< width
; ++x
)
7685 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7687 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7689 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7690 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7691 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7692 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7695 /* Read the GIF image into the X image. We use a local variable
7696 `raster' here because RasterBits below is a char *, and invites
7697 problems with bytes >= 0x80. */
7698 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7700 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7703 int row
= interlace_start
[0];
7707 for (y
= 0; y
< image_height
; y
++)
7709 if (row
>= image_height
)
7711 row
= interlace_start
[++pass
];
7712 while (row
>= image_height
)
7713 row
= interlace_start
[++pass
];
7716 for (x
= 0; x
< image_width
; x
++)
7718 int i
= raster
[(y
* image_width
) + x
];
7719 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7720 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7723 row
+= interlace_increment
[pass
];
7728 for (y
= 0; y
< image_height
; ++y
)
7729 for (x
= 0; x
< image_width
; ++x
)
7731 int i
= raster
[y
* image_width
+ x
];
7732 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7733 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7737 /* Save GIF image extension data for `image-extension-data'.
7738 Format is (count IMAGES FUNCTION "BYTES" ...). */
7739 img
->data
.lisp_val
= Qnil
;
7740 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
7742 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
7743 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
7744 /* Append (... FUNCTION "BYTES") */
7745 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
7746 Fcons (make_number (ext
->Function
),
7747 img
->data
.lisp_val
));
7748 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
7750 if (gif
->ImageCount
> 1)
7751 img
->data
.lisp_val
= Fcons (Qcount
,
7752 Fcons (make_number (gif
->ImageCount
),
7753 img
->data
.lisp_val
));
7755 fn_DGifCloseFile (gif
);
7757 /* Maybe fill in the background field while we have ximg handy. */
7758 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7759 /* Casting avoids a GCC warning. */
7760 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7762 /* Put the image into the pixmap, then free the X image and its buffer. */
7763 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7764 x_destroy_x_image (ximg
);
7770 #else /* !HAVE_GIF */
7774 gif_load (struct frame
*f
, struct image
*img
)
7776 return ns_load_image(f
, img
,
7777 image_spec_value (img
->spec
, QCfile
, NULL
),
7778 image_spec_value (img
->spec
, QCdata
, NULL
));
7780 #endif /* HAVE_NS */
7782 #endif /* HAVE_GIF */
7786 /***********************************************************************
7788 ***********************************************************************/
7790 #if defined (HAVE_RSVG)
7792 /* Function prototypes. */
7794 static int svg_image_p
P_ ((Lisp_Object object
));
7795 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
7797 static int svg_load_image
P_ ((struct frame
*, struct image
*,
7798 unsigned char *, unsigned int));
7800 /* The symbol `svg' identifying images of this type. */
7804 /* Indices of image specification fields in svg_format, below. */
7806 enum svg_keyword_index
7821 /* Vector of image_keyword structures describing the format
7822 of valid user-defined image specifications. */
7824 static struct image_keyword svg_format
[SVG_LAST
] =
7826 {":type", IMAGE_SYMBOL_VALUE
, 1},
7827 {":data", IMAGE_STRING_VALUE
, 0},
7828 {":file", IMAGE_STRING_VALUE
, 0},
7829 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7830 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7831 {":relief", IMAGE_INTEGER_VALUE
, 0},
7832 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7833 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7834 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7835 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7838 /* Structure describing the image type `svg'. Its the same type of
7839 structure defined for all image formats, handled by emacs image
7840 functions. See struct image_type in dispextern.h. */
7842 static struct image_type svg_type
=
7844 /* An identifier showing that this is an image structure for the SVG format. */
7846 /* Handle to a function that can be used to identify a SVG file. */
7848 /* Handle to function used to load a SVG file. */
7850 /* Handle to function to free sresources for SVG. */
7852 /* An internal field to link to the next image type in a list of
7853 image types, will be filled in when registering the format. */
7858 /* Return non-zero if OBJECT is a valid SVG image specification. Do
7859 this by calling parse_image_spec and supplying the keywords that
7860 identify the SVG format. */
7863 svg_image_p (object
)
7866 struct image_keyword fmt
[SVG_LAST
];
7867 bcopy (svg_format
, fmt
, sizeof fmt
);
7869 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
7872 /* Must specify either the :data or :file keyword. */
7873 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
7876 #include <librsvg/rsvg.h>
7880 /* SVG library functions. */
7881 DEF_IMGLIB_FN (rsvg_handle_new
);
7882 DEF_IMGLIB_FN (rsvg_handle_get_dimensions
);
7883 DEF_IMGLIB_FN (rsvg_handle_write
);
7884 DEF_IMGLIB_FN (rsvg_handle_close
);
7885 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
7886 DEF_IMGLIB_FN (rsvg_handle_free
);
7888 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
7889 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
7890 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
7891 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
7892 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
7893 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
7894 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
7895 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
7897 DEF_IMGLIB_FN (g_type_init
);
7898 DEF_IMGLIB_FN (g_object_unref
);
7899 DEF_IMGLIB_FN (g_error_free
);
7901 Lisp_Object Qgdk_pixbuf
, Qglib
;
7904 init_svg_functions (Lisp_Object libraries
)
7906 HMODULE library
, gdklib
, glib
;
7908 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
7909 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
7910 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
7913 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
7914 LOAD_IMGLIB_FN (library
, rsvg_handle_get_dimensions
);
7915 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
7916 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
7917 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
7918 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
7920 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
7921 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
7922 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
7923 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
7924 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
7925 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
7926 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
7927 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
7929 LOAD_IMGLIB_FN (glib
, g_type_init
);
7930 LOAD_IMGLIB_FN (glib
, g_object_unref
);
7931 LOAD_IMGLIB_FN (glib
, g_error_free
);
7936 /* The following aliases for library functions allow dynamic loading
7937 to be used on some platforms. */
7938 #define fn_rsvg_handle_new rsvg_handle_new
7939 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
7940 #define fn_rsvg_handle_write rsvg_handle_write
7941 #define fn_rsvg_handle_close rsvg_handle_close
7942 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
7943 #define fn_rsvg_handle_free rsvg_handle_free
7945 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
7946 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
7947 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
7948 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
7949 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
7950 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
7951 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
7952 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
7954 #define fn_g_type_init g_type_init
7955 #define fn_g_object_unref g_object_unref
7956 #define fn_g_error_free g_error_free
7957 #endif /* !HAVE_NTGUI */
7959 /* Load SVG image IMG for use on frame F. Value is non-zero if
7960 successful. this function will go into the svg_type structure, and
7961 the prototype thus needs to be compatible with that structure. */
7969 Lisp_Object file_name
;
7971 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7972 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7973 if (STRINGP (file_name
))
7976 unsigned char *contents
;
7978 struct gcpro gcpro1
;
7980 file
= x_find_image_file (file_name
);
7982 if (!STRINGP (file
))
7984 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7989 /* Read the entire file into memory. */
7990 contents
= slurp_file (SDATA (file
), &size
);
7991 if (contents
== NULL
)
7993 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
7997 /* If the file was slurped into memory properly, parse it. */
7998 success_p
= svg_load_image (f
, img
, contents
, size
);
8002 /* Else its not a file, its a lisp object. Load the image from a
8003 lisp object rather than a file. */
8008 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8009 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8015 /* svg_load_image is a helper function for svg_load, which does the
8016 actual loading given contents and size, apart from frame and image
8017 structures, passed from svg_load.
8019 Uses librsvg to do most of the image processing.
8021 Returns non-zero when successful. */
8023 svg_load_image (f
, img
, contents
, size
)
8024 /* Pointer to emacs frame structure. */
8026 /* Pointer to emacs image structure. */
8028 /* String containing the SVG XML data to be parsed. */
8029 unsigned char *contents
;
8030 /* Size of data in bytes. */
8033 RsvgHandle
*rsvg_handle
;
8034 RsvgDimensionData dimension_data
;
8035 GError
*error
= NULL
;
8039 const guint8
*pixels
;
8042 Lisp_Object specified_bg
;
8047 /* g_type_init is a glib function that must be called prior to using
8048 gnome type library functions. */
8050 /* Make a handle to a new rsvg object. */
8051 rsvg_handle
= fn_rsvg_handle_new ();
8053 /* Parse the contents argument and fill in the rsvg_handle. */
8054 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8055 if (error
) goto rsvg_error
;
8057 /* The parsing is complete, rsvg_handle is ready to used, close it
8058 for further writes. */
8059 fn_rsvg_handle_close (rsvg_handle
, &error
);
8060 if (error
) goto rsvg_error
;
8062 fn_rsvg_handle_get_dimensions (rsvg_handle
, &dimension_data
);
8063 if (! check_image_size (f
, dimension_data
.width
, dimension_data
.height
))
8066 /* We can now get a valid pixel buffer from the svg file, if all
8068 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8069 if (!pixbuf
) goto rsvg_error
;
8070 fn_g_object_unref (rsvg_handle
);
8072 /* Extract some meta data from the svg handle. */
8073 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8074 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8075 pixels
= fn_gdk_pixbuf_get_pixels (pixbuf
);
8076 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8078 /* Validate the svg meta data. */
8079 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8080 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8081 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8082 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8084 /* Try to create a x pixmap to hold the svg pixmap. */
8085 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8087 fn_g_object_unref (pixbuf
);
8091 init_color_table ();
8093 /* Handle alpha channel by combining the image with a background
8095 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8096 if (STRINGP (specified_bg
)
8097 && x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8099 background
.red
>>= 8;
8100 background
.green
>>= 8;
8101 background
.blue
>>= 8;
8105 #ifdef HAVE_X_WINDOWS
8106 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8107 x_query_color (f
, &background
);
8109 /* SVG pixmaps specify transparency in the last byte, so right
8110 shift 8 bits to get rid of it, since emacs doesn't support
8112 background
.red
>>= 8;
8113 background
.green
>>= 8;
8114 background
.blue
>>= 8;
8115 #elif defined (HAVE_NTGUI)
8116 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8117 #if 0 /* W32 TODO : Colormap support. */
8118 x_query_color (f
, &background
);
8121 /* SVG pixmaps specify transparency in the last byte, so right
8122 shift 8 bits to get rid of it, since emacs doesn't support
8124 background
.red
>>= 8;
8125 background
.green
>>= 8;
8126 background
.blue
>>= 8;
8127 #else /* not HAVE_X_WINDOWS*/
8132 /* This loop handles opacity values, since Emacs assumes
8133 non-transparent images. Each pixel must be "flattened" by
8134 calculating the resulting color, given the transparency of the
8135 pixel, and the image background color. */
8136 for (y
= 0; y
< height
; ++y
)
8138 for (x
= 0; x
< width
; ++x
)
8148 opacity
= *pixels
++;
8150 red
= ((red
* opacity
)
8151 + (background
.red
* ((1 << 8) - opacity
)));
8152 green
= ((green
* opacity
)
8153 + (background
.green
* ((1 << 8) - opacity
)));
8154 blue
= ((blue
* opacity
)
8155 + (background
.blue
* ((1 << 8) - opacity
)));
8157 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8160 pixels
+= rowstride
- 4 * width
;
8163 #ifdef COLOR_TABLE_SUPPORT
8164 /* Remember colors allocated for this image. */
8165 img
->colors
= colors_in_color_table (&img
->ncolors
);
8166 free_color_table ();
8167 #endif /* COLOR_TABLE_SUPPORT */
8169 fn_g_object_unref (pixbuf
);
8172 img
->height
= height
;
8174 /* Maybe fill in the background field while we have ximg handy.
8175 Casting avoids a GCC warning. */
8176 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8178 /* Put the image into the pixmap, then free the X image and its
8180 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8181 x_destroy_x_image (ximg
);
8186 fn_g_object_unref (rsvg_handle
);
8187 /* FIXME: Use error->message so the user knows what is the actual
8188 problem with the image. */
8189 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8190 fn_g_error_free (error
);
8194 #endif /* defined (HAVE_RSVG) */
8199 /***********************************************************************
8201 ***********************************************************************/
8203 #ifdef HAVE_X_WINDOWS
8204 #define HAVE_GHOSTSCRIPT 1
8205 #endif /* HAVE_X_WINDOWS */
8207 /* The symbol `postscript' identifying images of this type. */
8209 Lisp_Object Qpostscript
;
8211 #ifdef HAVE_GHOSTSCRIPT
8213 static int gs_image_p
P_ ((Lisp_Object object
));
8214 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8215 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8217 /* Keyword symbols. */
8219 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8221 /* Indices of image specification fields in gs_format, below. */
8223 enum gs_keyword_index
8241 /* Vector of image_keyword structures describing the format
8242 of valid user-defined image specifications. */
8244 static struct image_keyword gs_format
[GS_LAST
] =
8246 {":type", IMAGE_SYMBOL_VALUE
, 1},
8247 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8248 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8249 {":file", IMAGE_STRING_VALUE
, 1},
8250 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8251 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8252 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8253 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8254 {":relief", IMAGE_INTEGER_VALUE
, 0},
8255 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8256 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8257 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8258 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8261 /* Structure describing the image type `ghostscript'. */
8263 static struct image_type gs_type
=
8273 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8276 gs_clear_image (f
, img
)
8280 /* IMG->data.ptr_val may contain a recorded colormap. */
8281 xfree (img
->data
.ptr_val
);
8282 x_clear_image (f
, img
);
8286 /* Return non-zero if OBJECT is a valid Ghostscript image
8293 struct image_keyword fmt
[GS_LAST
];
8297 bcopy (gs_format
, fmt
, sizeof fmt
);
8299 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8302 /* Bounding box must be a list or vector containing 4 integers. */
8303 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8306 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8307 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8312 else if (VECTORP (tem
))
8314 if (XVECTOR (tem
)->size
!= 4)
8316 for (i
= 0; i
< 4; ++i
)
8317 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8327 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8336 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8337 struct gcpro gcpro1
, gcpro2
;
8339 double in_width
, in_height
;
8340 Lisp_Object pixel_colors
= Qnil
;
8342 /* Compute pixel size of pixmap needed from the given size in the
8343 image specification. Sizes in the specification are in pt. 1 pt
8344 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8346 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8347 in_width
= XFASTINT (pt_width
) / 72.0;
8348 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8349 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8350 in_height
= XFASTINT (pt_height
) / 72.0;
8351 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8353 if (!check_image_size (f
, img
->width
, img
->height
))
8355 image_error ("Invalid image size", Qnil
, Qnil
);
8359 /* Create the pixmap. */
8360 xassert (img
->pixmap
== NO_PIXMAP
);
8362 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8364 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8365 img
->width
, img
->height
,
8366 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8371 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8375 /* Call the loader to fill the pixmap. It returns a process object
8376 if successful. We do not record_unwind_protect here because
8377 other places in redisplay like calling window scroll functions
8378 don't either. Let the Lisp loader use `unwind-protect' instead. */
8379 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8381 sprintf (buffer
, "%lu %lu",
8382 (unsigned long) FRAME_X_WINDOW (f
),
8383 (unsigned long) img
->pixmap
);
8384 window_and_pixmap_id
= build_string (buffer
);
8386 sprintf (buffer
, "%lu %lu",
8387 FRAME_FOREGROUND_PIXEL (f
),
8388 FRAME_BACKGROUND_PIXEL (f
));
8389 pixel_colors
= build_string (buffer
);
8391 XSETFRAME (frame
, f
);
8392 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8394 loader
= intern ("gs-load-image");
8396 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8397 make_number (img
->width
),
8398 make_number (img
->height
),
8399 window_and_pixmap_id
,
8402 return PROCESSP (img
->data
.lisp_val
);
8406 /* Kill the Ghostscript process that was started to fill PIXMAP on
8407 frame F. Called from XTread_socket when receiving an event
8408 telling Emacs that Ghostscript has finished drawing. */
8411 x_kill_gs_process (pixmap
, f
)
8415 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
8419 /* Find the image containing PIXMAP. */
8420 for (i
= 0; i
< c
->used
; ++i
)
8421 if (c
->images
[i
]->pixmap
== pixmap
)
8424 /* Should someone in between have cleared the image cache, for
8425 instance, give up. */
8429 /* Kill the GS process. We should have found PIXMAP in the image
8430 cache and its image should contain a process object. */
8432 xassert (PROCESSP (img
->data
.lisp_val
));
8433 Fkill_process (img
->data
.lisp_val
, Qnil
);
8434 img
->data
.lisp_val
= Qnil
;
8436 #if defined (HAVE_X_WINDOWS)
8438 /* On displays with a mutable colormap, figure out the colors
8439 allocated for the image by looking at the pixels of an XImage for
8441 class = FRAME_X_VISUAL (f
)->class;
8442 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8448 /* Try to get an XImage for img->pixmep. */
8449 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8450 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8455 /* Initialize the color table. */
8456 init_color_table ();
8458 /* For each pixel of the image, look its color up in the
8459 color table. After having done so, the color table will
8460 contain an entry for each color used by the image. */
8461 for (y
= 0; y
< img
->height
; ++y
)
8462 for (x
= 0; x
< img
->width
; ++x
)
8464 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8465 lookup_pixel_color (f
, pixel
);
8468 /* Record colors in the image. Free color table and XImage. */
8469 #ifdef COLOR_TABLE_SUPPORT
8470 img
->colors
= colors_in_color_table (&img
->ncolors
);
8471 free_color_table ();
8473 XDestroyImage (ximg
);
8475 #if 0 /* This doesn't seem to be the case. If we free the colors
8476 here, we get a BadAccess later in x_clear_image when
8477 freeing the colors. */
8478 /* We have allocated colors once, but Ghostscript has also
8479 allocated colors on behalf of us. So, to get the
8480 reference counts right, free them once. */
8482 x_free_colors (f
, img
->colors
, img
->ncolors
);
8486 image_error ("Cannot get X image of `%s'; colors will not be freed",
8491 #endif /* HAVE_X_WINDOWS */
8493 /* Now that we have the pixmap, compute mask and transform the
8494 image if requested. */
8496 postprocess_image (f
, img
);
8500 #endif /* HAVE_GHOSTSCRIPT */
8503 /***********************************************************************
8505 ***********************************************************************/
8509 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8510 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8514 return valid_image_p (spec
) ? Qt
: Qnil
;
8518 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8524 if (valid_image_p (spec
))
8525 id
= lookup_image (SELECTED_FRAME (), spec
);
8528 return make_number (id
);
8531 #endif /* GLYPH_DEBUG != 0 */
8534 /***********************************************************************
8536 ***********************************************************************/
8539 /* Image types that rely on external libraries are loaded dynamically
8540 if the library is available. */
8541 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8542 define_image_type (image_type, init_lib_fn (libraries))
8544 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8545 define_image_type (image_type, 1)
8546 #endif /* HAVE_NTGUI */
8548 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8549 doc
: /* Initialize image library implementing image type TYPE.
8550 Return non-nil if TYPE is a supported image type.
8552 Image types pbm and xbm are prebuilt; other types are loaded here.
8553 Libraries to load are specified in alist LIBRARIES (usually, the value
8554 of `image-library-alist', which see). */)
8556 Lisp_Object type
, libraries
;
8560 /* Don't try to reload the library. */
8561 tested
= Fassq (type
, Vimage_type_cache
);
8563 return XCDR (tested
);
8565 #if defined (HAVE_XPM) || defined (HAVE_NS)
8566 if (EQ (type
, Qxpm
))
8567 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8570 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8571 if (EQ (type
, Qjpeg
))
8572 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8575 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8576 if (EQ (type
, Qtiff
))
8577 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8580 #if defined (HAVE_GIF) || defined (HAVE_NS)
8581 if (EQ (type
, Qgif
))
8582 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8585 #if defined (HAVE_PNG) || defined (HAVE_NS)
8586 if (EQ (type
, Qpng
))
8587 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8590 #if defined (HAVE_RSVG)
8591 if (EQ (type
, Qsvg
))
8592 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
8595 #ifdef HAVE_GHOSTSCRIPT
8596 if (EQ (type
, Qpostscript
))
8597 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8600 /* If the type is not recognized, avoid testing it ever again. */
8601 CACHE_IMAGE_TYPE (type
, Qnil
);
8608 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8610 /* Initialize this only once, since that's what we do with Vimage_types
8611 and they are supposed to be in sync. Initializing here gives correct
8612 operation on GNU/Linux of calling dump-emacs after loading some images. */
8615 /* Must be defined now becase we're going to update it below, while
8616 defining the supported image types. */
8617 DEFVAR_LISP ("image-types", &Vimage_types
,
8618 doc
: /* List of potentially supported image types.
8619 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8620 To check whether it is really supported, use `image-type-available-p'. */);
8621 Vimage_types
= Qnil
;
8623 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8624 doc
: /* Alist of image types vs external libraries needed to display them.
8626 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8627 representing a supported image type, and the rest are strings giving
8628 alternate filenames for the corresponding external libraries.
8630 Emacs tries to load the libraries in the order they appear on the
8631 list; if none is loaded, the running session of Emacs won't
8632 support the image type. Types 'pbm and 'xbm don't need to be
8633 listed; they are always supported. */);
8634 Vimage_library_alist
= Qnil
;
8635 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8637 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8638 doc
: /* Maximum size of images.
8639 Emacs will not load an image into memory if its pixel width or
8640 pixel height exceeds this limit.
8642 If the value is an integer, it directly specifies the maximum
8643 image height and width, measured in pixels. If it is a floating
8644 point number, it specifies the maximum image height and width
8645 as a ratio to the frame height and width. If the value is
8646 non-numeric, there is no explicit limit on the size of images. */);
8647 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
8649 Vimage_type_cache
= Qnil
;
8650 staticpro (&Vimage_type_cache
);
8652 Qpbm
= intern ("pbm");
8654 ADD_IMAGE_TYPE (Qpbm
);
8656 Qxbm
= intern ("xbm");
8658 ADD_IMAGE_TYPE (Qxbm
);
8660 define_image_type (&xbm_type
, 1);
8661 define_image_type (&pbm_type
, 1);
8663 Qcount
= intern ("count");
8664 staticpro (&Qcount
);
8666 QCascent
= intern (":ascent");
8667 staticpro (&QCascent
);
8668 QCmargin
= intern (":margin");
8669 staticpro (&QCmargin
);
8670 QCrelief
= intern (":relief");
8671 staticpro (&QCrelief
);
8672 QCconversion
= intern (":conversion");
8673 staticpro (&QCconversion
);
8674 QCcolor_symbols
= intern (":color-symbols");
8675 staticpro (&QCcolor_symbols
);
8676 QCheuristic_mask
= intern (":heuristic-mask");
8677 staticpro (&QCheuristic_mask
);
8678 QCindex
= intern (":index");
8679 staticpro (&QCindex
);
8680 QCmatrix
= intern (":matrix");
8681 staticpro (&QCmatrix
);
8682 QCcolor_adjustment
= intern (":color-adjustment");
8683 staticpro (&QCcolor_adjustment
);
8684 QCmask
= intern (":mask");
8685 staticpro (&QCmask
);
8687 Qlaplace
= intern ("laplace");
8688 staticpro (&Qlaplace
);
8689 Qemboss
= intern ("emboss");
8690 staticpro (&Qemboss
);
8691 Qedge_detection
= intern ("edge-detection");
8692 staticpro (&Qedge_detection
);
8693 Qheuristic
= intern ("heuristic");
8694 staticpro (&Qheuristic
);
8696 Qpostscript
= intern ("postscript");
8697 staticpro (&Qpostscript
);
8698 #ifdef HAVE_GHOSTSCRIPT
8699 ADD_IMAGE_TYPE (Qpostscript
);
8700 QCloader
= intern (":loader");
8701 staticpro (&QCloader
);
8702 QCbounding_box
= intern (":bounding-box");
8703 staticpro (&QCbounding_box
);
8704 QCpt_width
= intern (":pt-width");
8705 staticpro (&QCpt_width
);
8706 QCpt_height
= intern (":pt-height");
8707 staticpro (&QCpt_height
);
8708 #endif /* HAVE_GHOSTSCRIPT */
8710 #if defined (HAVE_XPM) || defined (HAVE_NS)
8711 Qxpm
= intern ("xpm");
8713 ADD_IMAGE_TYPE (Qxpm
);
8716 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8717 Qjpeg
= intern ("jpeg");
8719 ADD_IMAGE_TYPE (Qjpeg
);
8722 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8723 Qtiff
= intern ("tiff");
8725 ADD_IMAGE_TYPE (Qtiff
);
8728 #if defined (HAVE_GIF) || defined (HAVE_NS)
8729 Qgif
= intern ("gif");
8731 ADD_IMAGE_TYPE (Qgif
);
8734 #if defined (HAVE_PNG) || defined (HAVE_NS)
8735 Qpng
= intern ("png");
8737 ADD_IMAGE_TYPE (Qpng
);
8740 #if defined (HAVE_RSVG)
8741 Qsvg
= intern ("svg");
8743 ADD_IMAGE_TYPE (Qsvg
);
8745 Qgdk_pixbuf
= intern ("gdk-pixbuf");
8746 staticpro (&Qgdk_pixbuf
);
8747 Qglib
= intern ("glib");
8749 #endif /* HAVE_NTGUI */
8750 #endif /* HAVE_RSVG */
8752 defsubr (&Sinit_image_library
);
8753 defsubr (&Sclear_image_cache
);
8754 defsubr (&Simage_refresh
);
8755 defsubr (&Simage_size
);
8756 defsubr (&Simage_mask_p
);
8757 defsubr (&Simage_extension_data
);
8761 defsubr (&Slookup_image
);
8764 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8765 doc
: /* Non-nil means always draw a cross over disabled images.
8766 Disabled images are those having a `:conversion disabled' property.
8767 A cross is always drawn on black & white displays. */);
8768 cross_disabled_images
= 0;
8770 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8771 doc
: /* List of directories to search for window system bitmap files. */);
8772 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8774 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8775 doc
: /* Time after which cached images are removed from the cache.
8776 When an image has not been displayed this many seconds, remove it
8777 from the image cache. Value must be an integer or nil with nil
8778 meaning don't clear the cache. */);
8779 Vimage_cache_eviction_delay
= make_number (30 * 60);
8787 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8788 (do not change this comment) */