merge trunk
[bpt/emacs.git] / src / image.c
1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
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.
12
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.
17
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/>. */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <ctype.h>
25
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29
30 #ifdef HAVE_PNG
31 #if defined HAVE_LIBPNG_PNG_H
32 # include <libpng/png.h>
33 #else
34 # include <png.h>
35 #endif
36 #endif
37
38 #include <setjmp.h>
39
40 /* This makes the fields of a Display accessible, in Xlib header files. */
41
42 #define XLIB_ILLEGAL_ACCESS
43
44 #include "lisp.h"
45 #include "frame.h"
46 #include "window.h"
47 #include "dispextern.h"
48 #include "blockinput.h"
49 #include "systime.h"
50 #include <epaths.h>
51 #include "character.h"
52 #include "coding.h"
53 #include "termhooks.h"
54 #include "font.h"
55
56 #ifdef HAVE_X_WINDOWS
57 #include "xterm.h"
58 #include <sys/types.h>
59 #include <sys/stat.h>
60
61 #define COLOR_TABLE_SUPPORT 1
62
63 typedef struct x_bitmap_record Bitmap_Record;
64 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
65 #define NO_PIXMAP None
66
67 #define RGB_PIXEL_COLOR unsigned long
68
69 #define PIX_MASK_RETAIN 0
70 #define PIX_MASK_DRAW 1
71 #endif /* HAVE_X_WINDOWS */
72
73
74 #ifdef HAVE_NTGUI
75 #include "w32term.h"
76
77 /* W32_TODO : Color tables on W32. */
78 #undef COLOR_TABLE_SUPPORT
79
80 typedef struct w32_bitmap_record Bitmap_Record;
81 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
82 #define NO_PIXMAP 0
83
84 #define RGB_PIXEL_COLOR COLORREF
85
86 #define PIX_MASK_RETAIN 0
87 #define PIX_MASK_DRAW 1
88
89 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
90 #define x_defined_color w32_defined_color
91 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
92
93 /* Functions from w32term.c that depend on XColor (so can't go in w32term.h
94 without modifying lots of files). */
95 extern void x_query_colors (struct frame *f, XColor *colors, int ncolors);
96 extern void x_query_color (struct frame *f, XColor *color);
97 #endif /* HAVE_NTGUI */
98
99 #ifdef HAVE_NS
100 #include "nsterm.h"
101 #include <sys/types.h>
102 #include <sys/stat.h>
103
104 #undef COLOR_TABLE_SUPPORT
105
106 typedef struct ns_bitmap_record Bitmap_Record;
107
108 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
109 #define NO_PIXMAP 0
110
111 #define RGB_PIXEL_COLOR unsigned long
112 #define ZPixmap 0
113
114 #define PIX_MASK_RETAIN 0
115 #define PIX_MASK_DRAW 1
116
117 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
118 #define x_defined_color(f, name, color_def, alloc) \
119 ns_defined_color (f, name, color_def, alloc, 0)
120 #define FRAME_X_SCREEN(f) 0
121 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
122 #endif /* HAVE_NS */
123
124
125 /* Search path for bitmap files. */
126
127 Lisp_Object Vx_bitmap_file_path;
128
129
130 static void x_disable_image (struct frame *, struct image *);
131 static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
132 Lisp_Object);
133
134 static void init_color_table (void);
135 static unsigned long lookup_rgb_color (struct frame *f, int r, int g, int b);
136 #ifdef COLOR_TABLE_SUPPORT
137 static void free_color_table (void);
138 static unsigned long *colors_in_color_table (int *n);
139 static unsigned long lookup_pixel_color (struct frame *f, unsigned long p);
140 #endif
141
142 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
143 id, which is just an int that this section returns. Bitmaps are
144 reference counted so they can be shared among frames.
145
146 Bitmap indices are guaranteed to be > 0, so a negative number can
147 be used to indicate no bitmap.
148
149 If you use x_create_bitmap_from_data, then you must keep track of
150 the bitmaps yourself. That is, creating a bitmap from the same
151 data more than once will not be caught. */
152
153 #ifdef HAVE_NS
154 XImagePtr
155 XGetImage (Display *display, Pixmap pixmap, int x, int y,
156 unsigned int width, unsigned int height,
157 unsigned long plane_mask, int format)
158 {
159 /* TODO: not sure what this function is supposed to do.. */
160 ns_retain_object (pixmap);
161 return pixmap;
162 }
163
164 /* use with imgs created by ns_image_for_XPM */
165 unsigned long
166 XGetPixel (XImagePtr ximage, int x, int y)
167 {
168 return ns_get_pixel (ximage, x, y);
169 }
170
171 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
172 pixel is assumed to be in form RGB */
173 void
174 XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
175 {
176 ns_put_pixel (ximage, x, y, pixel);
177 }
178 #endif /* HAVE_NS */
179
180
181 /* Functions to access the contents of a bitmap, given an id. */
182
183 int
184 x_bitmap_height (FRAME_PTR f, int id)
185 {
186 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
187 }
188
189 int
190 x_bitmap_width (FRAME_PTR f, int id)
191 {
192 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
193 }
194
195 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
196 int
197 x_bitmap_pixmap (FRAME_PTR f, int id)
198 {
199 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
200 }
201 #endif
202
203 #ifdef HAVE_X_WINDOWS
204 int
205 x_bitmap_mask (FRAME_PTR f, int id)
206 {
207 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
208 }
209 #endif
210
211 /* Allocate a new bitmap record. Returns index of new record. */
212
213 static int
214 x_allocate_bitmap_record (FRAME_PTR f)
215 {
216 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
217 int i;
218
219 if (dpyinfo->bitmaps == NULL)
220 {
221 dpyinfo->bitmaps_size = 10;
222 dpyinfo->bitmaps
223 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
224 dpyinfo->bitmaps_last = 1;
225 return 1;
226 }
227
228 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
229 return ++dpyinfo->bitmaps_last;
230
231 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
232 if (dpyinfo->bitmaps[i].refcount == 0)
233 return i + 1;
234
235 dpyinfo->bitmaps_size *= 2;
236 dpyinfo->bitmaps
237 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
238 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
239 return ++dpyinfo->bitmaps_last;
240 }
241
242 /* Add one reference to the reference count of the bitmap with id ID. */
243
244 void
245 x_reference_bitmap (FRAME_PTR f, int id)
246 {
247 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
248 }
249
250 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
251
252 int
253 x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsigned int height)
254 {
255 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
256 int id;
257
258 #ifdef HAVE_X_WINDOWS
259 Pixmap bitmap;
260 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
261 bits, width, height);
262 if (! bitmap)
263 return -1;
264 #endif /* HAVE_X_WINDOWS */
265
266 #ifdef HAVE_NTGUI
267 Pixmap bitmap;
268 bitmap = CreateBitmap (width, height,
269 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
270 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
271 bits);
272 if (! bitmap)
273 return -1;
274 #endif /* HAVE_NTGUI */
275
276 #ifdef HAVE_NS
277 void *bitmap = ns_image_from_XBM (bits, width, height);
278 if (!bitmap)
279 return -1;
280 #endif
281
282 id = x_allocate_bitmap_record (f);
283
284 #ifdef HAVE_NS
285 dpyinfo->bitmaps[id - 1].img = bitmap;
286 dpyinfo->bitmaps[id - 1].depth = 1;
287 #endif
288
289 dpyinfo->bitmaps[id - 1].file = NULL;
290 dpyinfo->bitmaps[id - 1].height = height;
291 dpyinfo->bitmaps[id - 1].width = width;
292 dpyinfo->bitmaps[id - 1].refcount = 1;
293
294 #ifdef HAVE_X_WINDOWS
295 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
296 dpyinfo->bitmaps[id - 1].have_mask = 0;
297 dpyinfo->bitmaps[id - 1].depth = 1;
298 #endif /* HAVE_X_WINDOWS */
299
300 #ifdef HAVE_NTGUI
301 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
302 dpyinfo->bitmaps[id - 1].hinst = NULL;
303 dpyinfo->bitmaps[id - 1].depth = 1;
304 #endif /* HAVE_NTGUI */
305
306 return id;
307 }
308
309 /* Create bitmap from file FILE for frame F. */
310
311 int
312 x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
313 {
314 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
315
316 #ifdef HAVE_NTGUI
317 return -1; /* W32_TODO : bitmap support */
318 #endif /* HAVE_NTGUI */
319
320 #ifdef HAVE_NS
321 int id;
322 void *bitmap = ns_image_from_file (file);
323
324 if (!bitmap)
325 return -1;
326
327
328 id = x_allocate_bitmap_record (f);
329 dpyinfo->bitmaps[id - 1].img = bitmap;
330 dpyinfo->bitmaps[id - 1].refcount = 1;
331 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
332 dpyinfo->bitmaps[id - 1].depth = 1;
333 dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap);
334 dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap);
335 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
336 return id;
337 #endif
338
339 #ifdef HAVE_X_WINDOWS
340 unsigned int width, height;
341 Pixmap bitmap;
342 int xhot, yhot, result, id;
343 Lisp_Object found;
344 int fd;
345 char *filename;
346
347 /* Look for an existing bitmap with the same name. */
348 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
349 {
350 if (dpyinfo->bitmaps[id].refcount
351 && dpyinfo->bitmaps[id].file
352 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
353 {
354 ++dpyinfo->bitmaps[id].refcount;
355 return id + 1;
356 }
357 }
358
359 /* Search bitmap-file-path for the file, if appropriate. */
360 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
361 if (fd < 0)
362 return -1;
363 emacs_close (fd);
364
365 filename = (char *) SDATA (found);
366
367 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
368 filename, &width, &height, &bitmap, &xhot, &yhot);
369 if (result != BitmapSuccess)
370 return -1;
371
372 id = x_allocate_bitmap_record (f);
373 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
374 dpyinfo->bitmaps[id - 1].have_mask = 0;
375 dpyinfo->bitmaps[id - 1].refcount = 1;
376 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
377 dpyinfo->bitmaps[id - 1].depth = 1;
378 dpyinfo->bitmaps[id - 1].height = height;
379 dpyinfo->bitmaps[id - 1].width = width;
380 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
381
382 return id;
383 #endif /* HAVE_X_WINDOWS */
384 }
385
386 /* Free bitmap B. */
387
388 static void
389 free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
390 {
391 #ifdef HAVE_X_WINDOWS
392 XFreePixmap (dpyinfo->display, bm->pixmap);
393 if (bm->have_mask)
394 XFreePixmap (dpyinfo->display, bm->mask);
395 #endif /* HAVE_X_WINDOWS */
396
397 #ifdef HAVE_NTGUI
398 DeleteObject (bm->pixmap);
399 #endif /* HAVE_NTGUI */
400
401 #ifdef HAVE_NS
402 ns_release_object (bm->img);
403 #endif
404
405 if (bm->file)
406 {
407 xfree (bm->file);
408 bm->file = NULL;
409 }
410 }
411
412 /* Remove reference to bitmap with id number ID. */
413
414 void
415 x_destroy_bitmap (FRAME_PTR f, int id)
416 {
417 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
418
419 if (id > 0)
420 {
421 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
422
423 if (--bm->refcount == 0)
424 {
425 BLOCK_INPUT;
426 free_bitmap_record (dpyinfo, bm);
427 UNBLOCK_INPUT;
428 }
429 }
430 }
431
432 /* Free all the bitmaps for the display specified by DPYINFO. */
433
434 void
435 x_destroy_all_bitmaps (Display_Info *dpyinfo)
436 {
437 int i;
438 Bitmap_Record *bm = dpyinfo->bitmaps;
439
440 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
441 if (bm->refcount > 0)
442 free_bitmap_record (dpyinfo, bm);
443
444 dpyinfo->bitmaps_last = 0;
445 }
446
447
448 #ifdef HAVE_X_WINDOWS
449
450 /* Useful functions defined in the section
451 `Image type independent image structures' below. */
452
453 static unsigned long four_corners_best (XImagePtr ximg,
454 int *corners,
455 unsigned long width,
456 unsigned long height);
457
458 static int x_create_x_image_and_pixmap (struct frame *f, int width, int height,
459 int depth, XImagePtr *ximg,
460 Pixmap *pixmap);
461
462 static void x_destroy_x_image (XImagePtr ximg);
463
464
465 /* Create a mask of a bitmap. Note is this not a perfect mask.
466 It's nicer with some borders in this context */
467
468 int
469 x_create_bitmap_mask (struct frame *f, int id)
470 {
471 Pixmap pixmap, mask;
472 XImagePtr ximg, mask_img;
473 unsigned long width, height;
474 int result;
475 unsigned long bg;
476 unsigned long x, y, xp, xm, yp, ym;
477 GC gc;
478
479 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
480
481 if (!(id > 0))
482 return -1;
483
484 pixmap = x_bitmap_pixmap (f, id);
485 width = x_bitmap_width (f, id);
486 height = x_bitmap_height (f, id);
487
488 BLOCK_INPUT;
489 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
490 ~0, ZPixmap);
491
492 if (!ximg)
493 {
494 UNBLOCK_INPUT;
495 return -1;
496 }
497
498 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
499
500 UNBLOCK_INPUT;
501 if (!result)
502 {
503 XDestroyImage (ximg);
504 return -1;
505 }
506
507 bg = four_corners_best (ximg, NULL, width, height);
508
509 for (y = 0; y < ximg->height; ++y)
510 {
511 for (x = 0; x < ximg->width; ++x)
512 {
513 xp = x != ximg->width - 1 ? x + 1 : 0;
514 xm = x != 0 ? x - 1 : ximg->width - 1;
515 yp = y != ximg->height - 1 ? y + 1 : 0;
516 ym = y != 0 ? y - 1 : ximg->height - 1;
517 if (XGetPixel (ximg, x, y) == bg
518 && XGetPixel (ximg, x, yp) == bg
519 && XGetPixel (ximg, x, ym) == bg
520 && XGetPixel (ximg, xp, y) == bg
521 && XGetPixel (ximg, xp, yp) == bg
522 && XGetPixel (ximg, xp, ym) == bg
523 && XGetPixel (ximg, xm, y) == bg
524 && XGetPixel (ximg, xm, yp) == bg
525 && XGetPixel (ximg, xm, ym) == bg)
526 XPutPixel (mask_img, x, y, 0);
527 else
528 XPutPixel (mask_img, x, y, 1);
529 }
530 }
531
532 xassert (interrupt_input_blocked);
533 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
534 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
535 width, height);
536 XFreeGC (FRAME_X_DISPLAY (f), gc);
537
538 dpyinfo->bitmaps[id - 1].have_mask = 1;
539 dpyinfo->bitmaps[id - 1].mask = mask;
540
541 XDestroyImage (ximg);
542 x_destroy_x_image (mask_img);
543
544 return 0;
545 }
546
547 #endif /* HAVE_X_WINDOWS */
548
549
550 /***********************************************************************
551 Image types
552 ***********************************************************************/
553
554 /* Value is the number of elements of vector VECTOR. */
555
556 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
557
558 /* List of supported image types. Use define_image_type to add new
559 types. Use lookup_image_type to find a type for a given symbol. */
560
561 static struct image_type *image_types;
562
563 /* A list of symbols, one for each supported image type. */
564
565 Lisp_Object Vimage_types;
566
567 /* An alist of image types and libraries that implement the type. */
568
569 Lisp_Object Vimage_library_alist;
570
571 /* Cache for delayed-loading image types. */
572
573 static Lisp_Object Vimage_type_cache;
574
575 /* The symbol `xbm' which is used as the type symbol for XBM images. */
576
577 Lisp_Object Qxbm;
578
579 /* Keywords. */
580
581 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
582 extern Lisp_Object QCdata, QCtype;
583 extern Lisp_Object Qcenter;
584 Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data;
585 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
586 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
587
588 /* Other symbols. */
589
590 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
591
592 /* Time in seconds after which images should be removed from the cache
593 if not displayed. */
594
595 Lisp_Object Vimage_cache_eviction_delay;
596
597 /* Function prototypes. */
598
599 static Lisp_Object define_image_type (struct image_type *type, int loaded);
600 static struct image_type *lookup_image_type (Lisp_Object symbol);
601 static void image_error (char *format, Lisp_Object, Lisp_Object);
602 static void x_laplace (struct frame *, struct image *);
603 static void x_emboss (struct frame *, struct image *);
604 static int x_build_heuristic_mask (struct frame *, struct image *,
605 Lisp_Object);
606
607 #define CACHE_IMAGE_TYPE(type, status) \
608 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
609
610 #define ADD_IMAGE_TYPE(type) \
611 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
612
613 /* Define a new image type from TYPE. This adds a copy of TYPE to
614 image_types and caches the loading status of TYPE. */
615
616 static Lisp_Object
617 define_image_type (struct image_type *type, int loaded)
618 {
619 Lisp_Object success;
620
621 if (!loaded)
622 success = Qnil;
623 else
624 {
625 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
626 The initialized data segment is read-only. */
627 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
628 memcpy (p, type, sizeof *p);
629 p->next = image_types;
630 image_types = p;
631 success = Qt;
632 }
633
634 CACHE_IMAGE_TYPE (*type->type, success);
635 return success;
636 }
637
638
639 /* Look up image type SYMBOL, and return a pointer to its image_type
640 structure. Value is null if SYMBOL is not a known image type. */
641
642 static INLINE struct image_type *
643 lookup_image_type (Lisp_Object symbol)
644 {
645 struct image_type *type;
646
647 /* We must initialize the image-type if it hasn't been already. */
648 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
649 return 0; /* unimplemented */
650
651 for (type = image_types; type; type = type->next)
652 if (EQ (symbol, *type->type))
653 break;
654
655 return type;
656 }
657
658
659 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
660 valid image specification is a list whose car is the symbol
661 `image', and whose rest is a property list. The property list must
662 contain a value for key `:type'. That value must be the name of a
663 supported image type. The rest of the property list depends on the
664 image type. */
665
666 int
667 valid_image_p (Lisp_Object object)
668 {
669 int valid_p = 0;
670
671 if (IMAGEP (object))
672 {
673 Lisp_Object tem;
674
675 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
676 if (EQ (XCAR (tem), QCtype))
677 {
678 tem = XCDR (tem);
679 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
680 {
681 struct image_type *type;
682 type = lookup_image_type (XCAR (tem));
683 if (type)
684 valid_p = type->valid_p (object);
685 }
686
687 break;
688 }
689 }
690
691 return valid_p;
692 }
693
694
695 /* Log error message with format string FORMAT and argument ARG.
696 Signaling an error, e.g. when an image cannot be loaded, is not a
697 good idea because this would interrupt redisplay, and the error
698 message display would lead to another redisplay. This function
699 therefore simply displays a message. */
700
701 static void
702 image_error (char *format, Lisp_Object arg1, Lisp_Object arg2)
703 {
704 add_to_log (format, arg1, arg2);
705 }
706
707
708 \f
709 /***********************************************************************
710 Image specifications
711 ***********************************************************************/
712
713 enum image_value_type
714 {
715 IMAGE_DONT_CHECK_VALUE_TYPE,
716 IMAGE_STRING_VALUE,
717 IMAGE_STRING_OR_NIL_VALUE,
718 IMAGE_SYMBOL_VALUE,
719 IMAGE_POSITIVE_INTEGER_VALUE,
720 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
721 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
722 IMAGE_ASCENT_VALUE,
723 IMAGE_INTEGER_VALUE,
724 IMAGE_FUNCTION_VALUE,
725 IMAGE_NUMBER_VALUE,
726 IMAGE_BOOL_VALUE
727 };
728
729 /* Structure used when parsing image specifications. */
730
731 struct image_keyword
732 {
733 /* Name of keyword. */
734 char *name;
735
736 /* The type of value allowed. */
737 enum image_value_type type;
738
739 /* Non-zero means key must be present. */
740 int mandatory_p;
741
742 /* Used to recognize duplicate keywords in a property list. */
743 int count;
744
745 /* The value that was found. */
746 Lisp_Object value;
747 };
748
749
750 static int parse_image_spec (Lisp_Object, struct image_keyword *,
751 int, Lisp_Object);
752 static Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, int *);
753
754
755 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
756 has the format (image KEYWORD VALUE ...). One of the keyword/
757 value pairs must be `:type TYPE'. KEYWORDS is a vector of
758 image_keywords structures of size NKEYWORDS describing other
759 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
760
761 static int
762 parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
763 int nkeywords, Lisp_Object type)
764 {
765 int i;
766 Lisp_Object plist;
767
768 if (!IMAGEP (spec))
769 return 0;
770
771 plist = XCDR (spec);
772 while (CONSP (plist))
773 {
774 Lisp_Object key, value;
775
776 /* First element of a pair must be a symbol. */
777 key = XCAR (plist);
778 plist = XCDR (plist);
779 if (!SYMBOLP (key))
780 return 0;
781
782 /* There must follow a value. */
783 if (!CONSP (plist))
784 return 0;
785 value = XCAR (plist);
786 plist = XCDR (plist);
787
788 /* Find key in KEYWORDS. Error if not found. */
789 for (i = 0; i < nkeywords; ++i)
790 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
791 break;
792
793 if (i == nkeywords)
794 continue;
795
796 /* Record that we recognized the keyword. If a keywords
797 was found more than once, it's an error. */
798 keywords[i].value = value;
799 ++keywords[i].count;
800
801 if (keywords[i].count > 1)
802 return 0;
803
804 /* Check type of value against allowed type. */
805 switch (keywords[i].type)
806 {
807 case IMAGE_STRING_VALUE:
808 if (!STRINGP (value))
809 return 0;
810 break;
811
812 case IMAGE_STRING_OR_NIL_VALUE:
813 if (!STRINGP (value) && !NILP (value))
814 return 0;
815 break;
816
817 case IMAGE_SYMBOL_VALUE:
818 if (!SYMBOLP (value))
819 return 0;
820 break;
821
822 case IMAGE_POSITIVE_INTEGER_VALUE:
823 if (!INTEGERP (value) || XINT (value) <= 0)
824 return 0;
825 break;
826
827 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
828 if (INTEGERP (value) && XINT (value) >= 0)
829 break;
830 if (CONSP (value)
831 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
832 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
833 break;
834 return 0;
835
836 case IMAGE_ASCENT_VALUE:
837 if (SYMBOLP (value) && EQ (value, Qcenter))
838 break;
839 else if (INTEGERP (value)
840 && XINT (value) >= 0
841 && XINT (value) <= 100)
842 break;
843 return 0;
844
845 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
846 if (!INTEGERP (value) || XINT (value) < 0)
847 return 0;
848 break;
849
850 case IMAGE_DONT_CHECK_VALUE_TYPE:
851 break;
852
853 case IMAGE_FUNCTION_VALUE:
854 value = indirect_function (value);
855 if (SUBRP (value)
856 || COMPILEDP (value)
857 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
858 break;
859 return 0;
860
861 case IMAGE_NUMBER_VALUE:
862 if (!INTEGERP (value) && !FLOATP (value))
863 return 0;
864 break;
865
866 case IMAGE_INTEGER_VALUE:
867 if (!INTEGERP (value))
868 return 0;
869 break;
870
871 case IMAGE_BOOL_VALUE:
872 if (!NILP (value) && !EQ (value, Qt))
873 return 0;
874 break;
875
876 default:
877 abort ();
878 break;
879 }
880
881 if (EQ (key, QCtype) && !EQ (type, value))
882 return 0;
883 }
884
885 /* Check that all mandatory fields are present. */
886 for (i = 0; i < nkeywords; ++i)
887 if (keywords[i].mandatory_p && keywords[i].count == 0)
888 return 0;
889
890 return NILP (plist);
891 }
892
893
894 /* Return the value of KEY in image specification SPEC. Value is nil
895 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
896 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
897
898 static Lisp_Object
899 image_spec_value (Lisp_Object spec, Lisp_Object key, int *found)
900 {
901 Lisp_Object tail;
902
903 xassert (valid_image_p (spec));
904
905 for (tail = XCDR (spec);
906 CONSP (tail) && CONSP (XCDR (tail));
907 tail = XCDR (XCDR (tail)))
908 {
909 if (EQ (XCAR (tail), key))
910 {
911 if (found)
912 *found = 1;
913 return XCAR (XCDR (tail));
914 }
915 }
916
917 if (found)
918 *found = 0;
919 return Qnil;
920 }
921
922
923 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
924 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
925 PIXELS non-nil means return the size in pixels, otherwise return the
926 size in canonical character units.
927 FRAME is the frame on which the image will be displayed. FRAME nil
928 or omitted means use the selected frame. */)
929 (Lisp_Object spec, Lisp_Object pixels, Lisp_Object frame)
930 {
931 Lisp_Object size;
932
933 size = Qnil;
934 if (valid_image_p (spec))
935 {
936 struct frame *f = check_x_frame (frame);
937 int id = lookup_image (f, spec);
938 struct image *img = IMAGE_FROM_ID (f, id);
939 int width = img->width + 2 * img->hmargin;
940 int height = img->height + 2 * img->vmargin;
941
942 if (NILP (pixels))
943 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
944 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
945 else
946 size = Fcons (make_number (width), make_number (height));
947 }
948 else
949 error ("Invalid image specification");
950
951 return size;
952 }
953
954
955 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
956 doc: /* Return t if image SPEC has a mask bitmap.
957 FRAME is the frame on which the image will be displayed. FRAME nil
958 or omitted means use the selected frame. */)
959 (Lisp_Object spec, Lisp_Object frame)
960 {
961 Lisp_Object mask;
962
963 mask = Qnil;
964 if (valid_image_p (spec))
965 {
966 struct frame *f = check_x_frame (frame);
967 int id = lookup_image (f, spec);
968 struct image *img = IMAGE_FROM_ID (f, id);
969 if (img->mask)
970 mask = Qt;
971 }
972 else
973 error ("Invalid image specification");
974
975 return mask;
976 }
977
978 DEFUN ("image-metadata", Fimage_metadata, Simage_metadata, 1, 2, 0,
979 doc: /* Return metadata for image SPEC.
980 FRAME is the frame on which the image will be displayed. FRAME nil
981 or omitted means use the selected frame. */)
982 (Lisp_Object spec, Lisp_Object frame)
983 {
984 Lisp_Object ext;
985
986 ext = Qnil;
987 if (valid_image_p (spec))
988 {
989 struct frame *f = check_x_frame (frame);
990 int id = lookup_image (f, spec);
991 struct image *img = IMAGE_FROM_ID (f, id);
992 ext = img->data.lisp_val;
993 }
994
995 return ext;
996 }
997
998 \f
999 /***********************************************************************
1000 Image type independent image structures
1001 ***********************************************************************/
1002
1003 static struct image *make_image (Lisp_Object spec, unsigned hash);
1004 static void free_image (struct frame *f, struct image *img);
1005 static int check_image_size (struct frame *f, int width, int height);
1006
1007 #define MAX_IMAGE_SIZE 6.0
1008 Lisp_Object Vmax_image_size;
1009
1010 /* Allocate and return a new image structure for image specification
1011 SPEC. SPEC has a hash value of HASH. */
1012
1013 static struct image *
1014 make_image (Lisp_Object spec, unsigned int hash)
1015 {
1016 struct image *img = (struct image *) xmalloc (sizeof *img);
1017 Lisp_Object file = image_spec_value (spec, QCfile, NULL);
1018
1019 xassert (valid_image_p (spec));
1020 memset (img, 0, sizeof *img);
1021 img->dependencies = NILP (file) ? Qnil : list1 (file);
1022 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1023 xassert (img->type != NULL);
1024 img->spec = spec;
1025 img->data.lisp_val = Qnil;
1026 img->ascent = DEFAULT_IMAGE_ASCENT;
1027 img->hash = hash;
1028 img->corners[BOT_CORNER] = -1; /* Full image */
1029 return img;
1030 }
1031
1032
1033 /* Free image IMG which was used on frame F, including its resources. */
1034
1035 static void
1036 free_image (struct frame *f, struct image *img)
1037 {
1038 if (img)
1039 {
1040 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1041
1042 /* Remove IMG from the hash table of its cache. */
1043 if (img->prev)
1044 img->prev->next = img->next;
1045 else
1046 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1047
1048 if (img->next)
1049 img->next->prev = img->prev;
1050
1051 c->images[img->id] = NULL;
1052
1053 /* Free resources, then free IMG. */
1054 img->type->free (f, img);
1055 xfree (img);
1056 }
1057 }
1058
1059 /* Return 1 if the given widths and heights are valid for display;
1060 otherwise, return 0. */
1061
1062 int
1063 check_image_size (struct frame *f, int width, int height)
1064 {
1065 int w, h;
1066
1067 if (width <= 0 || height <= 0)
1068 return 0;
1069
1070 if (INTEGERP (Vmax_image_size))
1071 w = h = XINT (Vmax_image_size);
1072 else if (FLOATP (Vmax_image_size))
1073 {
1074 if (f != NULL)
1075 {
1076 w = FRAME_PIXEL_WIDTH (f);
1077 h = FRAME_PIXEL_HEIGHT (f);
1078 }
1079 else
1080 w = h = 1024; /* Arbitrary size for unknown frame. */
1081 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1082 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1083 }
1084 else
1085 return 1;
1086
1087 return (width <= w && height <= h);
1088 }
1089
1090 /* Prepare image IMG for display on frame F. Must be called before
1091 drawing an image. */
1092
1093 void
1094 prepare_image_for_display (struct frame *f, struct image *img)
1095 {
1096 EMACS_TIME t;
1097
1098 /* We're about to display IMG, so set its timestamp to `now'. */
1099 EMACS_GET_TIME (t);
1100 img->timestamp = EMACS_SECS (t);
1101
1102 /* If IMG doesn't have a pixmap yet, load it now, using the image
1103 type dependent loader function. */
1104 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1105 img->load_failed_p = img->type->load (f, img) == 0;
1106
1107 }
1108
1109
1110 /* Value is the number of pixels for the ascent of image IMG when
1111 drawn in face FACE. */
1112
1113 int
1114 image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
1115 {
1116 int height;
1117 int ascent;
1118
1119 if (slice->height == img->height)
1120 height = img->height + img->vmargin;
1121 else if (slice->y == 0)
1122 height = slice->height + img->vmargin;
1123 else
1124 height = slice->height;
1125
1126 if (img->ascent == CENTERED_IMAGE_ASCENT)
1127 {
1128 if (face->font)
1129 {
1130 #ifdef HAVE_NTGUI
1131 /* W32 specific version. Why?. ++kfs */
1132 ascent = height / 2 - (FONT_DESCENT (face->font)
1133 - FONT_BASE (face->font)) / 2;
1134 #else
1135 /* This expression is arranged so that if the image can't be
1136 exactly centered, it will be moved slightly up. This is
1137 because a typical font is `top-heavy' (due to the presence
1138 uppercase letters), so the image placement should err towards
1139 being top-heavy too. It also just generally looks better. */
1140 ascent = (height + FONT_BASE(face->font)
1141 - FONT_DESCENT(face->font) + 1) / 2;
1142 #endif /* HAVE_NTGUI */
1143 }
1144 else
1145 ascent = height / 2;
1146 }
1147 else
1148 ascent = (int) (height * img->ascent / 100.0);
1149
1150 return ascent;
1151 }
1152
1153 \f
1154 /* Image background colors. */
1155
1156 /* Find the "best" corner color of a bitmap.
1157 On W32, XIMG is assumed to a device context with the bitmap selected. */
1158
1159 static RGB_PIXEL_COLOR
1160 four_corners_best (XImagePtr_or_DC ximg, int *corners,
1161 unsigned long width, unsigned long height)
1162 {
1163 RGB_PIXEL_COLOR corner_pixels[4], best;
1164 int i, best_count;
1165
1166 if (corners && corners[BOT_CORNER] >= 0)
1167 {
1168 /* Get the colors at the corner_pixels of ximg. */
1169 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1170 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1171 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1172 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1173 }
1174 else
1175 {
1176 /* Get the colors at the corner_pixels of ximg. */
1177 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1178 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1179 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1180 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1181 }
1182 /* Choose the most frequently found color as background. */
1183 for (i = best_count = 0; i < 4; ++i)
1184 {
1185 int j, n;
1186
1187 for (j = n = 0; j < 4; ++j)
1188 if (corner_pixels[i] == corner_pixels[j])
1189 ++n;
1190
1191 if (n > best_count)
1192 best = corner_pixels[i], best_count = n;
1193 }
1194
1195 return best;
1196 }
1197
1198 /* Portability macros */
1199
1200 #ifdef HAVE_NTGUI
1201
1202 #define Destroy_Image(img_dc, prev) \
1203 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1204
1205 #define Free_Pixmap(display, pixmap) \
1206 DeleteObject (pixmap)
1207
1208 #elif defined (HAVE_NS)
1209
1210 #define Destroy_Image(ximg, dummy) \
1211 ns_release_object (ximg)
1212
1213 #define Free_Pixmap(display, pixmap) \
1214 ns_release_object (pixmap)
1215
1216 #else
1217
1218 #define Destroy_Image(ximg, dummy) \
1219 XDestroyImage (ximg)
1220
1221 #define Free_Pixmap(display, pixmap) \
1222 XFreePixmap (display, pixmap)
1223
1224 #endif /* !HAVE_NTGUI && !HAVE_NS */
1225
1226
1227 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1228 it is guessed heuristically. If non-zero, XIMG is an existing
1229 XImage object (or device context with the image selected on W32) to
1230 use for the heuristic. */
1231
1232 RGB_PIXEL_COLOR
1233 image_background (struct image *img, struct frame *f, XImagePtr_or_DC ximg)
1234 {
1235 if (! img->background_valid)
1236 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1237 {
1238 int free_ximg = !ximg;
1239 #ifdef HAVE_NTGUI
1240 HGDIOBJ prev;
1241 #endif /* HAVE_NTGUI */
1242
1243 if (free_ximg)
1244 {
1245 #ifndef HAVE_NTGUI
1246 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1247 0, 0, img->width, img->height, ~0, ZPixmap);
1248 #else
1249 HDC frame_dc = get_frame_dc (f);
1250 ximg = CreateCompatibleDC (frame_dc);
1251 release_frame_dc (f, frame_dc);
1252 prev = SelectObject (ximg, img->pixmap);
1253 #endif /* !HAVE_NTGUI */
1254 }
1255
1256 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1257
1258 if (free_ximg)
1259 Destroy_Image (ximg, prev);
1260
1261 img->background_valid = 1;
1262 }
1263
1264 return img->background;
1265 }
1266
1267 /* Return the `background_transparent' field of IMG. If IMG doesn't
1268 have one yet, it is guessed heuristically. If non-zero, MASK is an
1269 existing XImage object to use for the heuristic. */
1270
1271 int
1272 image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_DC mask)
1273 {
1274 if (! img->background_transparent_valid)
1275 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1276 {
1277 if (img->mask)
1278 {
1279 int free_mask = !mask;
1280 #ifdef HAVE_NTGUI
1281 HGDIOBJ prev;
1282 #endif /* HAVE_NTGUI */
1283
1284 if (free_mask)
1285 {
1286 #ifndef HAVE_NTGUI
1287 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1288 0, 0, img->width, img->height, ~0, ZPixmap);
1289 #else
1290 HDC frame_dc = get_frame_dc (f);
1291 mask = CreateCompatibleDC (frame_dc);
1292 release_frame_dc (f, frame_dc);
1293 prev = SelectObject (mask, img->mask);
1294 #endif /* HAVE_NTGUI */
1295 }
1296
1297 img->background_transparent
1298 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1299
1300 if (free_mask)
1301 Destroy_Image (mask, prev);
1302 }
1303 else
1304 img->background_transparent = 0;
1305
1306 img->background_transparent_valid = 1;
1307 }
1308
1309 return img->background_transparent;
1310 }
1311
1312 \f
1313 /***********************************************************************
1314 Helper functions for X image types
1315 ***********************************************************************/
1316
1317 static void x_clear_image_1 (struct frame *, struct image *, int,
1318 int, int);
1319 static void x_clear_image (struct frame *f, struct image *img);
1320 static unsigned long x_alloc_image_color (struct frame *f,
1321 struct image *img,
1322 Lisp_Object color_name,
1323 unsigned long dflt);
1324
1325
1326 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1327 free the pixmap if any. MASK_P non-zero means clear the mask
1328 pixmap if any. COLORS_P non-zero means free colors allocated for
1329 the image, if any. */
1330
1331 static void
1332 x_clear_image_1 (struct frame *f, struct image *img, int pixmap_p, int mask_p,
1333 int colors_p)
1334 {
1335 if (pixmap_p && img->pixmap)
1336 {
1337 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1338 img->pixmap = NO_PIXMAP;
1339 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1340 img->background_valid = 0;
1341 }
1342
1343 if (mask_p && img->mask)
1344 {
1345 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1346 img->mask = NO_PIXMAP;
1347 img->background_transparent_valid = 0;
1348 }
1349
1350 if (colors_p && img->ncolors)
1351 {
1352 /* W32_TODO: color table support. */
1353 #ifdef HAVE_X_WINDOWS
1354 x_free_colors (f, img->colors, img->ncolors);
1355 #endif /* HAVE_X_WINDOWS */
1356 xfree (img->colors);
1357 img->colors = NULL;
1358 img->ncolors = 0;
1359 }
1360
1361 }
1362
1363 /* Free X resources of image IMG which is used on frame F. */
1364
1365 static void
1366 x_clear_image (struct frame *f, struct image *img)
1367 {
1368 BLOCK_INPUT;
1369 x_clear_image_1 (f, img, 1, 1, 1);
1370 UNBLOCK_INPUT;
1371 }
1372
1373
1374 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1375 cannot be allocated, use DFLT. Add a newly allocated color to
1376 IMG->colors, so that it can be freed again. Value is the pixel
1377 color. */
1378
1379 static unsigned long
1380 x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
1381 unsigned long dflt)
1382 {
1383 XColor color;
1384 unsigned long result;
1385
1386 xassert (STRINGP (color_name));
1387
1388 if (x_defined_color (f, SDATA (color_name), &color, 1))
1389 {
1390 /* This isn't called frequently so we get away with simply
1391 reallocating the color vector to the needed size, here. */
1392 ++img->ncolors;
1393 img->colors =
1394 (unsigned long *) xrealloc (img->colors,
1395 img->ncolors * sizeof *img->colors);
1396 img->colors[img->ncolors - 1] = color.pixel;
1397 result = color.pixel;
1398 }
1399 else
1400 result = dflt;
1401
1402 return result;
1403 }
1404
1405
1406 \f
1407 /***********************************************************************
1408 Image Cache
1409 ***********************************************************************/
1410
1411 static struct image *search_image_cache (struct frame *, Lisp_Object, unsigned);
1412 static void cache_image (struct frame *f, struct image *img);
1413 static void postprocess_image (struct frame *, struct image *);
1414
1415 /* Return a new, initialized image cache that is allocated from the
1416 heap. Call free_image_cache to free an image cache. */
1417
1418 struct image_cache *
1419 make_image_cache (void)
1420 {
1421 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1422 int size;
1423
1424 memset (c, 0, sizeof *c);
1425 c->size = 50;
1426 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1427 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1428 c->buckets = (struct image **) xmalloc (size);
1429 memset (c->buckets, 0, size);
1430 return c;
1431 }
1432
1433
1434 /* Find an image matching SPEC in the cache, and return it. If no
1435 image is found, return NULL. */
1436 static struct image *
1437 search_image_cache (struct frame *f, Lisp_Object spec, unsigned int hash)
1438 {
1439 struct image *img;
1440 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1441 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1442
1443 if (!c) return NULL;
1444
1445 /* If the image spec does not specify a background color, the cached
1446 image must have the same background color as the current frame.
1447 The foreground color must also match, for the sake of monochrome
1448 images.
1449
1450 In fact, we could ignore the foreground color matching condition
1451 for color images, or if the image spec specifies :foreground;
1452 similarly we could ignore the background color matching condition
1453 for formats that don't use transparency (such as jpeg), or if the
1454 image spec specifies :background. However, the extra memory
1455 usage is probably negligible in practice, so we don't bother. */
1456
1457 for (img = c->buckets[i]; img; img = img->next)
1458 if (img->hash == hash
1459 && !NILP (Fequal (img->spec, spec))
1460 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1461 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
1462 break;
1463 return img;
1464 }
1465
1466
1467 /* Search frame F for an image with spec SPEC, and free it. */
1468
1469 static void
1470 uncache_image (struct frame *f, Lisp_Object spec)
1471 {
1472 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1473 if (img)
1474 free_image (f, img);
1475 }
1476
1477
1478 /* Free image cache of frame F. Be aware that X frames share images
1479 caches. */
1480
1481 void
1482 free_image_cache (struct frame *f)
1483 {
1484 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1485 if (c)
1486 {
1487 int i;
1488
1489 /* Cache should not be referenced by any frame when freed. */
1490 xassert (c->refcount == 0);
1491
1492 for (i = 0; i < c->used; ++i)
1493 free_image (f, c->images[i]);
1494 xfree (c->images);
1495 xfree (c->buckets);
1496 xfree (c);
1497 FRAME_IMAGE_CACHE (f) = NULL;
1498 }
1499 }
1500
1501
1502 /* Clear image cache of frame F. FILTER=t means free all images.
1503 FILTER=nil means clear only images that haven't been
1504 displayed for some time.
1505 Else, only free the images which have FILTER in their `dependencies'.
1506 Should be called from time to time to reduce the number of loaded images.
1507 If image-cache-eviction-delay is non-nil, this frees images in the cache
1508 which weren't displayed for at least that many seconds. */
1509
1510 void
1511 clear_image_cache (struct frame *f, Lisp_Object filter)
1512 {
1513 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1514
1515 if (c)
1516 {
1517 int i, nfreed = 0;
1518
1519 /* Block input so that we won't be interrupted by a SIGIO
1520 while being in an inconsistent state. */
1521 BLOCK_INPUT;
1522
1523 if (!NILP (filter))
1524 {
1525 /* Filter image cache. */
1526 for (i = 0; i < c->used; ++i)
1527 {
1528 struct image *img = c->images[i];
1529 if (img && (EQ (Qt, filter)
1530 || !NILP (Fmember (filter, img->dependencies))))
1531 {
1532 free_image (f, img);
1533 ++nfreed;
1534 }
1535 }
1536 }
1537 else if (INTEGERP (Vimage_cache_eviction_delay))
1538 {
1539 /* Free cache based on timestamp. */
1540 EMACS_TIME t;
1541 unsigned long old;
1542 int delay, nimages = 0;
1543
1544 for (i = 0; i < c->used; ++i)
1545 if (c->images[i])
1546 nimages++;
1547
1548 /* If the number of cached images has grown unusually large,
1549 decrease the cache eviction delay (Bug#6230). */
1550 delay = XFASTINT (Vimage_cache_eviction_delay);
1551 if (nimages > 40)
1552 delay = max (1, 1600 * delay / (nimages*nimages));
1553
1554 EMACS_GET_TIME (t);
1555 old = EMACS_SECS (t) - delay;
1556
1557 for (i = 0; i < c->used; ++i)
1558 {
1559 struct image *img = c->images[i];
1560 if (img && img->timestamp < old)
1561 {
1562 free_image (f, img);
1563 ++nfreed;
1564 }
1565 }
1566 }
1567
1568 /* We may be clearing the image cache because, for example,
1569 Emacs was iconified for a longer period of time. In that
1570 case, current matrices may still contain references to
1571 images freed above. So, clear these matrices. */
1572 if (nfreed)
1573 {
1574 Lisp_Object tail, frame;
1575
1576 FOR_EACH_FRAME (tail, frame)
1577 {
1578 struct frame *f = XFRAME (frame);
1579 if (FRAME_IMAGE_CACHE (f) == c)
1580 clear_current_matrices (f);
1581 }
1582
1583 ++windows_or_buffers_changed;
1584 }
1585
1586 UNBLOCK_INPUT;
1587 }
1588 }
1589
1590 void
1591 clear_image_caches (Lisp_Object filter)
1592 {
1593 /* FIXME: We want to do
1594 * struct terminal *t;
1595 * for (t = terminal_list; t; t = t->next_terminal)
1596 * clear_image_cache (t, filter); */
1597 Lisp_Object tail, frame;
1598 FOR_EACH_FRAME (tail, frame)
1599 if (FRAME_WINDOW_P (XFRAME (frame)))
1600 clear_image_cache (XFRAME (frame), filter);
1601 }
1602
1603 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1604 0, 1, 0,
1605 doc: /* Clear the image cache.
1606 FILTER nil or a frame means clear all images in the selected frame.
1607 FILTER t means clear the image caches of all frames.
1608 Anything else, means only clear those images which refer to FILTER,
1609 which is then usually a filename. */)
1610 (Lisp_Object filter)
1611 {
1612 if (!(EQ (filter, Qnil) || FRAMEP (filter)))
1613 clear_image_caches (filter);
1614 else
1615 clear_image_cache (check_x_frame (filter), Qt);
1616
1617 return Qnil;
1618 }
1619
1620
1621 DEFUN ("image-flush", Fimage_flush, Simage_flush,
1622 1, 2, 0,
1623 doc: /* Fush the image with specification SPEC on frame FRAME.
1624 This removes the image from the Emacs image cache. If SPEC specifies
1625 an image file, the next redisplay of this image will read from the
1626 current contents of that file.
1627
1628 FRAME nil or omitted means use the selected frame.
1629 FRAME t means refresh the image on all frames. */)
1630 (Lisp_Object spec, Lisp_Object frame)
1631 {
1632 if (!valid_image_p (spec))
1633 error ("Invalid image specification");
1634
1635 if (EQ (frame, Qt))
1636 {
1637 Lisp_Object tail;
1638 FOR_EACH_FRAME (tail, frame)
1639 {
1640 struct frame *f = XFRAME (frame);
1641 if (FRAME_WINDOW_P (f))
1642 uncache_image (f, spec);
1643 }
1644 }
1645 else
1646 uncache_image (check_x_frame (frame), spec);
1647
1648 return Qnil;
1649 }
1650
1651
1652 /* Compute masks and transform image IMG on frame F, as specified
1653 by the image's specification, */
1654
1655 static void
1656 postprocess_image (struct frame *f, struct image *img)
1657 {
1658 /* Manipulation of the image's mask. */
1659 if (img->pixmap)
1660 {
1661 Lisp_Object conversion, spec;
1662 Lisp_Object mask;
1663
1664 spec = img->spec;
1665
1666 /* `:heuristic-mask t'
1667 `:mask heuristic'
1668 means build a mask heuristically.
1669 `:heuristic-mask (R G B)'
1670 `:mask (heuristic (R G B))'
1671 means build a mask from color (R G B) in the
1672 image.
1673 `:mask nil'
1674 means remove a mask, if any. */
1675
1676 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1677 if (!NILP (mask))
1678 x_build_heuristic_mask (f, img, mask);
1679 else
1680 {
1681 int found_p;
1682
1683 mask = image_spec_value (spec, QCmask, &found_p);
1684
1685 if (EQ (mask, Qheuristic))
1686 x_build_heuristic_mask (f, img, Qt);
1687 else if (CONSP (mask)
1688 && EQ (XCAR (mask), Qheuristic))
1689 {
1690 if (CONSP (XCDR (mask)))
1691 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1692 else
1693 x_build_heuristic_mask (f, img, XCDR (mask));
1694 }
1695 else if (NILP (mask) && found_p && img->mask)
1696 {
1697 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1698 img->mask = NO_PIXMAP;
1699 }
1700 }
1701
1702
1703 /* Should we apply an image transformation algorithm? */
1704 conversion = image_spec_value (spec, QCconversion, NULL);
1705 if (EQ (conversion, Qdisabled))
1706 x_disable_image (f, img);
1707 else if (EQ (conversion, Qlaplace))
1708 x_laplace (f, img);
1709 else if (EQ (conversion, Qemboss))
1710 x_emboss (f, img);
1711 else if (CONSP (conversion)
1712 && EQ (XCAR (conversion), Qedge_detection))
1713 {
1714 Lisp_Object tem;
1715 tem = XCDR (conversion);
1716 if (CONSP (tem))
1717 x_edge_detection (f, img,
1718 Fplist_get (tem, QCmatrix),
1719 Fplist_get (tem, QCcolor_adjustment));
1720 }
1721 }
1722 }
1723
1724
1725 /* Return the id of image with Lisp specification SPEC on frame F.
1726 SPEC must be a valid Lisp image specification (see valid_image_p). */
1727
1728 int
1729 lookup_image (struct frame *f, Lisp_Object spec)
1730 {
1731 struct image_cache *c;
1732 struct image *img;
1733 unsigned hash;
1734 struct gcpro gcpro1;
1735 EMACS_TIME now;
1736
1737 /* F must be a window-system frame, and SPEC must be a valid image
1738 specification. */
1739 xassert (FRAME_WINDOW_P (f));
1740 xassert (valid_image_p (spec));
1741
1742 c = FRAME_IMAGE_CACHE (f);
1743
1744 GCPRO1 (spec);
1745
1746 /* Look up SPEC in the hash table of the image cache. */
1747 hash = sxhash (spec, 0);
1748 img = search_image_cache (f, spec, hash);
1749 if (img && img->load_failed_p)
1750 {
1751 free_image (f, img);
1752 img = NULL;
1753 }
1754
1755 /* If not found, create a new image and cache it. */
1756 if (img == NULL)
1757 {
1758 extern Lisp_Object Qpostscript;
1759
1760 BLOCK_INPUT;
1761 img = make_image (spec, hash);
1762 cache_image (f, img);
1763 img->load_failed_p = img->type->load (f, img) == 0;
1764 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
1765 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
1766
1767 /* If we can't load the image, and we don't have a width and
1768 height, use some arbitrary width and height so that we can
1769 draw a rectangle for it. */
1770 if (img->load_failed_p)
1771 {
1772 Lisp_Object value;
1773
1774 value = image_spec_value (spec, QCwidth, NULL);
1775 img->width = (INTEGERP (value)
1776 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
1777 value = image_spec_value (spec, QCheight, NULL);
1778 img->height = (INTEGERP (value)
1779 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
1780 }
1781 else
1782 {
1783 /* Handle image type independent image attributes
1784 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1785 `:background COLOR'. */
1786 Lisp_Object ascent, margin, relief, bg;
1787
1788 ascent = image_spec_value (spec, QCascent, NULL);
1789 if (INTEGERP (ascent))
1790 img->ascent = XFASTINT (ascent);
1791 else if (EQ (ascent, Qcenter))
1792 img->ascent = CENTERED_IMAGE_ASCENT;
1793
1794 margin = image_spec_value (spec, QCmargin, NULL);
1795 if (INTEGERP (margin) && XINT (margin) >= 0)
1796 img->vmargin = img->hmargin = XFASTINT (margin);
1797 else if (CONSP (margin) && INTEGERP (XCAR (margin))
1798 && INTEGERP (XCDR (margin)))
1799 {
1800 if (XINT (XCAR (margin)) > 0)
1801 img->hmargin = XFASTINT (XCAR (margin));
1802 if (XINT (XCDR (margin)) > 0)
1803 img->vmargin = XFASTINT (XCDR (margin));
1804 }
1805
1806 relief = image_spec_value (spec, QCrelief, NULL);
1807 if (INTEGERP (relief))
1808 {
1809 img->relief = XINT (relief);
1810 img->hmargin += eabs (img->relief);
1811 img->vmargin += eabs (img->relief);
1812 }
1813
1814 if (! img->background_valid)
1815 {
1816 bg = image_spec_value (img->spec, QCbackground, NULL);
1817 if (!NILP (bg))
1818 {
1819 img->background
1820 = x_alloc_image_color (f, img, bg,
1821 FRAME_BACKGROUND_PIXEL (f));
1822 img->background_valid = 1;
1823 }
1824 }
1825
1826 /* Do image transformations and compute masks, unless we
1827 don't have the image yet. */
1828 if (!EQ (*img->type->type, Qpostscript))
1829 postprocess_image (f, img);
1830 }
1831
1832 UNBLOCK_INPUT;
1833 }
1834
1835 /* We're using IMG, so set its timestamp to `now'. */
1836 EMACS_GET_TIME (now);
1837 img->timestamp = EMACS_SECS (now);
1838
1839 UNGCPRO;
1840
1841 /* Value is the image id. */
1842 return img->id;
1843 }
1844
1845
1846 /* Cache image IMG in the image cache of frame F. */
1847
1848 static void
1849 cache_image (struct frame *f, struct image *img)
1850 {
1851 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1852 int i;
1853
1854 /* Find a free slot in c->images. */
1855 for (i = 0; i < c->used; ++i)
1856 if (c->images[i] == NULL)
1857 break;
1858
1859 /* If no free slot found, maybe enlarge c->images. */
1860 if (i == c->used && c->used == c->size)
1861 {
1862 c->size *= 2;
1863 c->images = (struct image **) xrealloc (c->images,
1864 c->size * sizeof *c->images);
1865 }
1866
1867 /* Add IMG to c->images, and assign IMG an id. */
1868 c->images[i] = img;
1869 img->id = i;
1870 if (i == c->used)
1871 ++c->used;
1872
1873 /* Add IMG to the cache's hash table. */
1874 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
1875 img->next = c->buckets[i];
1876 if (img->next)
1877 img->next->prev = img;
1878 img->prev = NULL;
1879 c->buckets[i] = img;
1880 }
1881
1882
1883 /* Call FN on every image in the image cache of frame F. Used to mark
1884 Lisp Objects in the image cache. */
1885
1886 /* Mark Lisp objects in image IMG. */
1887
1888 static void
1889 mark_image (struct image *img)
1890 {
1891 mark_object (img->spec);
1892 mark_object (img->dependencies);
1893
1894 if (!NILP (img->data.lisp_val))
1895 mark_object (img->data.lisp_val);
1896 }
1897
1898
1899 void
1900 mark_image_cache (struct image_cache *c)
1901 {
1902 if (c)
1903 {
1904 int i;
1905 for (i = 0; i < c->used; ++i)
1906 if (c->images[i])
1907 mark_image (c->images[i]);
1908 }
1909 }
1910
1911
1912 \f
1913 /***********************************************************************
1914 X / NS / W32 support code
1915 ***********************************************************************/
1916
1917 #ifdef HAVE_NTGUI
1918
1919 /* Macro for defining functions that will be loaded from image DLLs. */
1920 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
1921
1922 /* Macro for loading those image functions from the library. */
1923 #define LOAD_IMGLIB_FN(lib,func) { \
1924 fn_##func = (void *) GetProcAddress (lib, #func); \
1925 if (!fn_##func) return 0; \
1926 }
1927
1928 /* Load a DLL implementing an image type.
1929 The `image-library-alist' variable associates a symbol,
1930 identifying an image type, to a list of possible filenames.
1931 The function returns NULL if no library could be loaded for
1932 the given image type, or if the library was previously loaded;
1933 else the handle of the DLL. */
1934 static HMODULE
1935 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
1936 {
1937 HMODULE library = NULL;
1938
1939 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
1940 {
1941 Lisp_Object dlls = Fassq (type, libraries);
1942
1943 if (CONSP (dlls))
1944 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
1945 {
1946 CHECK_STRING_CAR (dlls);
1947 if (library = LoadLibrary (SDATA (XCAR (dlls))))
1948 break;
1949 }
1950 }
1951
1952 return library;
1953 }
1954
1955 #endif /* HAVE_NTGUI */
1956
1957 static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
1958 XImagePtr *, Pixmap *);
1959 static void x_destroy_x_image (XImagePtr);
1960 static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int);
1961
1962
1963 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1964 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1965 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1966 via xmalloc. Print error messages via image_error if an error
1967 occurs. Value is non-zero if successful.
1968
1969 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1970 should indicate the bit depth of the image. */
1971
1972 static int
1973 x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
1974 XImagePtr *ximg, Pixmap *pixmap)
1975 {
1976 #ifdef HAVE_X_WINDOWS
1977 Display *display = FRAME_X_DISPLAY (f);
1978 Window window = FRAME_X_WINDOW (f);
1979 Screen *screen = FRAME_X_SCREEN (f);
1980
1981 xassert (interrupt_input_blocked);
1982
1983 if (depth <= 0)
1984 depth = DefaultDepthOfScreen (screen);
1985 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
1986 depth, ZPixmap, 0, NULL, width, height,
1987 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
1988 if (*ximg == NULL)
1989 {
1990 image_error ("Unable to allocate X image", Qnil, Qnil);
1991 return 0;
1992 }
1993
1994 /* Allocate image raster. */
1995 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
1996
1997 /* Allocate a pixmap of the same size. */
1998 *pixmap = XCreatePixmap (display, window, width, height, depth);
1999 if (*pixmap == NO_PIXMAP)
2000 {
2001 x_destroy_x_image (*ximg);
2002 *ximg = NULL;
2003 image_error ("Unable to create X pixmap", Qnil, Qnil);
2004 return 0;
2005 }
2006
2007 return 1;
2008 #endif /* HAVE_X_WINDOWS */
2009
2010 #ifdef HAVE_NTGUI
2011
2012 BITMAPINFOHEADER *header;
2013 HDC hdc;
2014 int scanline_width_bits;
2015 int remainder;
2016 int palette_colors = 0;
2017
2018 if (depth == 0)
2019 depth = 24;
2020
2021 if (depth != 1 && depth != 4 && depth != 8
2022 && depth != 16 && depth != 24 && depth != 32)
2023 {
2024 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2025 return 0;
2026 }
2027
2028 scanline_width_bits = width * depth;
2029 remainder = scanline_width_bits % 32;
2030
2031 if (remainder)
2032 scanline_width_bits += 32 - remainder;
2033
2034 /* Bitmaps with a depth less than 16 need a palette. */
2035 /* BITMAPINFO structure already contains the first RGBQUAD. */
2036 if (depth < 16)
2037 palette_colors = 1 << depth - 1;
2038
2039 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2040 if (*ximg == NULL)
2041 {
2042 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2043 return 0;
2044 }
2045
2046 header = &(*ximg)->info.bmiHeader;
2047 memset (&(*ximg)->info, 0, sizeof (BITMAPINFO));
2048 header->biSize = sizeof (*header);
2049 header->biWidth = width;
2050 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2051 header->biPlanes = 1;
2052 header->biBitCount = depth;
2053 header->biCompression = BI_RGB;
2054 header->biClrUsed = palette_colors;
2055
2056 /* TODO: fill in palette. */
2057 if (depth == 1)
2058 {
2059 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2060 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2061 (*ximg)->info.bmiColors[0].rgbRed = 0;
2062 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2063 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2064 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2065 (*ximg)->info.bmiColors[1].rgbRed = 255;
2066 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2067 }
2068
2069 hdc = get_frame_dc (f);
2070
2071 /* Create a DIBSection and raster array for the bitmap,
2072 and store its handle in *pixmap. */
2073 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2074 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2075 /* casting avoids a GCC warning */
2076 (void **)&((*ximg)->data), NULL, 0);
2077
2078 /* Realize display palette and garbage all frames. */
2079 release_frame_dc (f, hdc);
2080
2081 if (*pixmap == NULL)
2082 {
2083 DWORD err = GetLastError ();
2084 Lisp_Object errcode;
2085 /* All system errors are < 10000, so the following is safe. */
2086 XSETINT (errcode, (int) err);
2087 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2088 x_destroy_x_image (*ximg);
2089 return 0;
2090 }
2091
2092 return 1;
2093
2094 #endif /* HAVE_NTGUI */
2095
2096 #ifdef HAVE_NS
2097 *pixmap = ns_image_for_XPM (width, height, depth);
2098 if (*pixmap == 0)
2099 {
2100 *ximg = NULL;
2101 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
2102 return 0;
2103 }
2104 *ximg = *pixmap;
2105 return 1;
2106 #endif
2107 }
2108
2109
2110 /* Destroy XImage XIMG. Free XIMG->data. */
2111
2112 static void
2113 x_destroy_x_image (XImagePtr ximg)
2114 {
2115 xassert (interrupt_input_blocked);
2116 if (ximg)
2117 {
2118 #ifdef HAVE_X_WINDOWS
2119 xfree (ximg->data);
2120 ximg->data = NULL;
2121 XDestroyImage (ximg);
2122 #endif /* HAVE_X_WINDOWS */
2123 #ifdef HAVE_NTGUI
2124 /* Data will be freed by DestroyObject. */
2125 ximg->data = NULL;
2126 xfree (ximg);
2127 #endif /* HAVE_NTGUI */
2128 #ifdef HAVE_NS
2129 ns_release_object (ximg);
2130 #endif /* HAVE_NS */
2131 }
2132 }
2133
2134
2135 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2136 are width and height of both the image and pixmap. */
2137
2138 static void
2139 x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int height)
2140 {
2141 #ifdef HAVE_X_WINDOWS
2142 GC gc;
2143
2144 xassert (interrupt_input_blocked);
2145 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2146 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2147 XFreeGC (FRAME_X_DISPLAY (f), gc);
2148 #endif /* HAVE_X_WINDOWS */
2149
2150 #ifdef HAVE_NTGUI
2151 #if 0 /* I don't think this is necessary looking at where it is used. */
2152 HDC hdc = get_frame_dc (f);
2153 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2154 release_frame_dc (f, hdc);
2155 #endif
2156 #endif /* HAVE_NTGUI */
2157
2158 #ifdef HAVE_NS
2159 xassert (ximg == pixmap);
2160 ns_retain_object (ximg);
2161 #endif
2162 }
2163
2164 \f
2165 /***********************************************************************
2166 File Handling
2167 ***********************************************************************/
2168
2169 static unsigned char *slurp_file (char *, int *);
2170
2171
2172 /* Find image file FILE. Look in data-directory/images, then
2173 x-bitmap-file-path. Value is the encoded full name of the file
2174 found, or nil if not found. */
2175
2176 Lisp_Object
2177 x_find_image_file (Lisp_Object file)
2178 {
2179 Lisp_Object file_found, search_path;
2180 struct gcpro gcpro1, gcpro2;
2181 int fd;
2182
2183 file_found = Qnil;
2184 /* TODO I think this should use something like image-load-path
2185 instead. Unfortunately, that can contain non-string elements. */
2186 search_path = Fcons (Fexpand_file_name (build_string ("images"),
2187 Vdata_directory),
2188 Vx_bitmap_file_path);
2189 GCPRO2 (file_found, search_path);
2190
2191 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2192 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2193
2194 if (fd == -1)
2195 file_found = Qnil;
2196 else
2197 {
2198 file_found = ENCODE_FILE (file_found);
2199 close (fd);
2200 }
2201
2202 UNGCPRO;
2203 return file_found;
2204 }
2205
2206
2207 /* Read FILE into memory. Value is a pointer to a buffer allocated
2208 with xmalloc holding FILE's contents. Value is null if an error
2209 occurred. *SIZE is set to the size of the file. */
2210
2211 static unsigned char *
2212 slurp_file (char *file, int *size)
2213 {
2214 FILE *fp = NULL;
2215 unsigned char *buf = NULL;
2216 struct stat st;
2217
2218 if (stat (file, &st) == 0
2219 && (fp = fopen (file, "rb")) != NULL
2220 && (buf = (unsigned char *) xmalloc (st.st_size),
2221 fread (buf, 1, st.st_size, fp) == st.st_size))
2222 {
2223 *size = st.st_size;
2224 fclose (fp);
2225 }
2226 else
2227 {
2228 if (fp)
2229 fclose (fp);
2230 if (buf)
2231 {
2232 xfree (buf);
2233 buf = NULL;
2234 }
2235 }
2236
2237 return buf;
2238 }
2239
2240
2241 \f
2242 /***********************************************************************
2243 XBM images
2244 ***********************************************************************/
2245
2246 static int xbm_scan (unsigned char **, unsigned char *, char *, int *);
2247 static int xbm_load (struct frame *f, struct image *img);
2248 static int xbm_load_image (struct frame *f, struct image *img,
2249 unsigned char *, unsigned char *);
2250 static int xbm_image_p (Lisp_Object object);
2251 static int xbm_read_bitmap_data (struct frame *f,
2252 unsigned char *, unsigned char *,
2253 int *, int *, unsigned char **, int);
2254 static int xbm_file_p (Lisp_Object);
2255
2256
2257 /* Indices of image specification fields in xbm_format, below. */
2258
2259 enum xbm_keyword_index
2260 {
2261 XBM_TYPE,
2262 XBM_FILE,
2263 XBM_WIDTH,
2264 XBM_HEIGHT,
2265 XBM_DATA,
2266 XBM_FOREGROUND,
2267 XBM_BACKGROUND,
2268 XBM_ASCENT,
2269 XBM_MARGIN,
2270 XBM_RELIEF,
2271 XBM_ALGORITHM,
2272 XBM_HEURISTIC_MASK,
2273 XBM_MASK,
2274 XBM_LAST
2275 };
2276
2277 /* Vector of image_keyword structures describing the format
2278 of valid XBM image specifications. */
2279
2280 static const struct image_keyword xbm_format[XBM_LAST] =
2281 {
2282 {":type", IMAGE_SYMBOL_VALUE, 1},
2283 {":file", IMAGE_STRING_VALUE, 0},
2284 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2285 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2286 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2287 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2288 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2289 {":ascent", IMAGE_ASCENT_VALUE, 0},
2290 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
2291 {":relief", IMAGE_INTEGER_VALUE, 0},
2292 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2293 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2294 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2295 };
2296
2297 /* Structure describing the image type XBM. */
2298
2299 static struct image_type xbm_type =
2300 {
2301 &Qxbm,
2302 xbm_image_p,
2303 xbm_load,
2304 x_clear_image,
2305 NULL
2306 };
2307
2308 /* Tokens returned from xbm_scan. */
2309
2310 enum xbm_token
2311 {
2312 XBM_TK_IDENT = 256,
2313 XBM_TK_NUMBER
2314 };
2315
2316
2317 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2318 A valid specification is a list starting with the symbol `image'
2319 The rest of the list is a property list which must contain an
2320 entry `:type xbm..
2321
2322 If the specification specifies a file to load, it must contain
2323 an entry `:file FILENAME' where FILENAME is a string.
2324
2325 If the specification is for a bitmap loaded from memory it must
2326 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2327 WIDTH and HEIGHT are integers > 0. DATA may be:
2328
2329 1. a string large enough to hold the bitmap data, i.e. it must
2330 have a size >= (WIDTH + 7) / 8 * HEIGHT
2331
2332 2. a bool-vector of size >= WIDTH * HEIGHT
2333
2334 3. a vector of strings or bool-vectors, one for each line of the
2335 bitmap.
2336
2337 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2338 may not be specified in this case because they are defined in the
2339 XBM file.
2340
2341 Both the file and data forms may contain the additional entries
2342 `:background COLOR' and `:foreground COLOR'. If not present,
2343 foreground and background of the frame on which the image is
2344 displayed is used. */
2345
2346 static int
2347 xbm_image_p (Lisp_Object object)
2348 {
2349 struct image_keyword kw[XBM_LAST];
2350
2351 memcpy (kw, xbm_format, sizeof kw);
2352 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2353 return 0;
2354
2355 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
2356
2357 if (kw[XBM_FILE].count)
2358 {
2359 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2360 return 0;
2361 }
2362 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2363 {
2364 /* In-memory XBM file. */
2365 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2366 return 0;
2367 }
2368 else
2369 {
2370 Lisp_Object data;
2371 int width, height;
2372
2373 /* Entries for `:width', `:height' and `:data' must be present. */
2374 if (!kw[XBM_WIDTH].count
2375 || !kw[XBM_HEIGHT].count
2376 || !kw[XBM_DATA].count)
2377 return 0;
2378
2379 data = kw[XBM_DATA].value;
2380 width = XFASTINT (kw[XBM_WIDTH].value);
2381 height = XFASTINT (kw[XBM_HEIGHT].value);
2382
2383 /* Check type of data, and width and height against contents of
2384 data. */
2385 if (VECTORP (data))
2386 {
2387 int i;
2388
2389 /* Number of elements of the vector must be >= height. */
2390 if (XVECTOR (data)->size < height)
2391 return 0;
2392
2393 /* Each string or bool-vector in data must be large enough
2394 for one line of the image. */
2395 for (i = 0; i < height; ++i)
2396 {
2397 Lisp_Object elt = XVECTOR (data)->contents[i];
2398
2399 if (STRINGP (elt))
2400 {
2401 if (SCHARS (elt)
2402 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2403 return 0;
2404 }
2405 else if (BOOL_VECTOR_P (elt))
2406 {
2407 if (XBOOL_VECTOR (elt)->size < width)
2408 return 0;
2409 }
2410 else
2411 return 0;
2412 }
2413 }
2414 else if (STRINGP (data))
2415 {
2416 if (SCHARS (data)
2417 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2418 return 0;
2419 }
2420 else if (BOOL_VECTOR_P (data))
2421 {
2422 if (XBOOL_VECTOR (data)->size < width * height)
2423 return 0;
2424 }
2425 else
2426 return 0;
2427 }
2428
2429 return 1;
2430 }
2431
2432
2433 /* Scan a bitmap file. FP is the stream to read from. Value is
2434 either an enumerator from enum xbm_token, or a character for a
2435 single-character token, or 0 at end of file. If scanning an
2436 identifier, store the lexeme of the identifier in SVAL. If
2437 scanning a number, store its value in *IVAL. */
2438
2439 static int
2440 xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival)
2441 {
2442 unsigned int c;
2443
2444 loop:
2445
2446 /* Skip white space. */
2447 while (*s < end && (c = *(*s)++, isspace (c)))
2448 ;
2449
2450 if (*s >= end)
2451 c = 0;
2452 else if (isdigit (c))
2453 {
2454 int value = 0, digit;
2455
2456 if (c == '0' && *s < end)
2457 {
2458 c = *(*s)++;
2459 if (c == 'x' || c == 'X')
2460 {
2461 while (*s < end)
2462 {
2463 c = *(*s)++;
2464 if (isdigit (c))
2465 digit = c - '0';
2466 else if (c >= 'a' && c <= 'f')
2467 digit = c - 'a' + 10;
2468 else if (c >= 'A' && c <= 'F')
2469 digit = c - 'A' + 10;
2470 else
2471 break;
2472 value = 16 * value + digit;
2473 }
2474 }
2475 else if (isdigit (c))
2476 {
2477 value = c - '0';
2478 while (*s < end
2479 && (c = *(*s)++, isdigit (c)))
2480 value = 8 * value + c - '0';
2481 }
2482 }
2483 else
2484 {
2485 value = c - '0';
2486 while (*s < end
2487 && (c = *(*s)++, isdigit (c)))
2488 value = 10 * value + c - '0';
2489 }
2490
2491 if (*s < end)
2492 *s = *s - 1;
2493 *ival = value;
2494 c = XBM_TK_NUMBER;
2495 }
2496 else if (isalpha (c) || c == '_')
2497 {
2498 *sval++ = c;
2499 while (*s < end
2500 && (c = *(*s)++, (isalnum (c) || c == '_')))
2501 *sval++ = c;
2502 *sval = 0;
2503 if (*s < end)
2504 *s = *s - 1;
2505 c = XBM_TK_IDENT;
2506 }
2507 else if (c == '/' && **s == '*')
2508 {
2509 /* C-style comment. */
2510 ++*s;
2511 while (**s && (**s != '*' || *(*s + 1) != '/'))
2512 ++*s;
2513 if (**s)
2514 {
2515 *s += 2;
2516 goto loop;
2517 }
2518 }
2519
2520 return c;
2521 }
2522
2523 #ifdef HAVE_NTGUI
2524
2525 /* Create a Windows bitmap from X bitmap data. */
2526 static HBITMAP
2527 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
2528 {
2529 static unsigned char swap_nibble[16]
2530 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2531 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2532 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2533 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2534 int i, j, w1, w2;
2535 unsigned char *bits, *p;
2536 HBITMAP bmp;
2537
2538 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
2539 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2540 bits = (unsigned char *) alloca (height * w2);
2541 memset (bits, 0, height * w2);
2542 for (i = 0; i < height; i++)
2543 {
2544 p = bits + i*w2;
2545 for (j = 0; j < w1; j++)
2546 {
2547 /* Bitswap XBM bytes to match how Windows does things. */
2548 unsigned char c = *data++;
2549 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
2550 | (swap_nibble[(c>>4) & 0xf]));
2551 }
2552 }
2553 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
2554
2555 return bmp;
2556 }
2557
2558 static void
2559 convert_mono_to_color_image (f, img, foreground, background)
2560 struct frame *f;
2561 struct image *img;
2562 COLORREF foreground, background;
2563 {
2564 HDC hdc, old_img_dc, new_img_dc;
2565 HGDIOBJ old_prev, new_prev;
2566 HBITMAP new_pixmap;
2567
2568 hdc = get_frame_dc (f);
2569 old_img_dc = CreateCompatibleDC (hdc);
2570 new_img_dc = CreateCompatibleDC (hdc);
2571 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
2572 release_frame_dc (f, hdc);
2573 old_prev = SelectObject (old_img_dc, img->pixmap);
2574 new_prev = SelectObject (new_img_dc, new_pixmap);
2575 /* Windows convention for mono bitmaps is black = background,
2576 white = foreground. */
2577 SetTextColor (new_img_dc, background);
2578 SetBkColor (new_img_dc, foreground);
2579
2580 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
2581 0, 0, SRCCOPY);
2582
2583 SelectObject (old_img_dc, old_prev);
2584 SelectObject (new_img_dc, new_prev);
2585 DeleteDC (old_img_dc);
2586 DeleteDC (new_img_dc);
2587 DeleteObject (img->pixmap);
2588 if (new_pixmap == 0)
2589 fprintf (stderr, "Failed to convert image to color.\n");
2590 else
2591 img->pixmap = new_pixmap;
2592 }
2593
2594 #define XBM_BIT_SHUFFLE(b) (~(b))
2595
2596 #else
2597
2598 #define XBM_BIT_SHUFFLE(b) (b)
2599
2600 #endif /* HAVE_NTGUI */
2601
2602
2603 static void
2604 Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
2605 RGB_PIXEL_COLOR fg, RGB_PIXEL_COLOR bg,
2606 int non_default_colors)
2607 {
2608 #ifdef HAVE_NTGUI
2609 img->pixmap
2610 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
2611
2612 /* If colors were specified, transfer the bitmap to a color one. */
2613 if (non_default_colors)
2614 convert_mono_to_color_image (f, img, fg, bg);
2615
2616 #elif defined (HAVE_NS)
2617 img->pixmap = ns_image_from_XBM (data, img->width, img->height);
2618
2619 #else
2620 img->pixmap
2621 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
2622 FRAME_X_WINDOW (f),
2623 data,
2624 img->width, img->height,
2625 fg, bg,
2626 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
2627 #endif /* !HAVE_NTGUI && !HAVE_NS */
2628 }
2629
2630
2631
2632 /* Replacement for XReadBitmapFileData which isn't available under old
2633 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2634 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2635 the image. Return in *DATA the bitmap data allocated with xmalloc.
2636 Value is non-zero if successful. DATA null means just test if
2637 CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR
2638 is non-zero, inhibit the call to image_error when the image size is
2639 invalid (the bitmap remains unread). */
2640
2641 static int
2642 xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *end,
2643 int *width, int *height, unsigned char **data,
2644 int inhibit_image_error)
2645 {
2646 unsigned char *s = contents;
2647 char buffer[BUFSIZ];
2648 int padding_p = 0;
2649 int v10 = 0;
2650 int bytes_per_line, i, nbytes;
2651 unsigned char *p;
2652 int value;
2653 int LA1;
2654
2655 #define match() \
2656 LA1 = xbm_scan (&s, end, buffer, &value)
2657
2658 #define expect(TOKEN) \
2659 if (LA1 != (TOKEN)) \
2660 goto failure; \
2661 else \
2662 match ()
2663
2664 #define expect_ident(IDENT) \
2665 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2666 match (); \
2667 else \
2668 goto failure
2669
2670 *width = *height = -1;
2671 if (data)
2672 *data = NULL;
2673 LA1 = xbm_scan (&s, end, buffer, &value);
2674
2675 /* Parse defines for width, height and hot-spots. */
2676 while (LA1 == '#')
2677 {
2678 match ();
2679 expect_ident ("define");
2680 expect (XBM_TK_IDENT);
2681
2682 if (LA1 == XBM_TK_NUMBER)
2683 {
2684 char *p = strrchr (buffer, '_');
2685 p = p ? p + 1 : buffer;
2686 if (strcmp (p, "width") == 0)
2687 *width = value;
2688 else if (strcmp (p, "height") == 0)
2689 *height = value;
2690 }
2691 expect (XBM_TK_NUMBER);
2692 }
2693
2694 if (!check_image_size (f, *width, *height))
2695 {
2696 if (!inhibit_image_error)
2697 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
2698 goto failure;
2699 }
2700 else if (data == NULL)
2701 goto success;
2702
2703 /* Parse bits. Must start with `static'. */
2704 expect_ident ("static");
2705 if (LA1 == XBM_TK_IDENT)
2706 {
2707 if (strcmp (buffer, "unsigned") == 0)
2708 {
2709 match ();
2710 expect_ident ("char");
2711 }
2712 else if (strcmp (buffer, "short") == 0)
2713 {
2714 match ();
2715 v10 = 1;
2716 if (*width % 16 && *width % 16 < 9)
2717 padding_p = 1;
2718 }
2719 else if (strcmp (buffer, "char") == 0)
2720 match ();
2721 else
2722 goto failure;
2723 }
2724 else
2725 goto failure;
2726
2727 expect (XBM_TK_IDENT);
2728 expect ('[');
2729 expect (']');
2730 expect ('=');
2731 expect ('{');
2732
2733 bytes_per_line = (*width + 7) / 8 + padding_p;
2734 nbytes = bytes_per_line * *height;
2735 p = *data = (unsigned char *) xmalloc (nbytes);
2736
2737 if (v10)
2738 {
2739 for (i = 0; i < nbytes; i += 2)
2740 {
2741 int val = value;
2742 expect (XBM_TK_NUMBER);
2743
2744 *p++ = XBM_BIT_SHUFFLE (val);
2745 if (!padding_p || ((i + 2) % bytes_per_line))
2746 *p++ = XBM_BIT_SHUFFLE (value >> 8);
2747
2748 if (LA1 == ',' || LA1 == '}')
2749 match ();
2750 else
2751 goto failure;
2752 }
2753 }
2754 else
2755 {
2756 for (i = 0; i < nbytes; ++i)
2757 {
2758 int val = value;
2759 expect (XBM_TK_NUMBER);
2760
2761 *p++ = XBM_BIT_SHUFFLE (val);
2762
2763 if (LA1 == ',' || LA1 == '}')
2764 match ();
2765 else
2766 goto failure;
2767 }
2768 }
2769
2770 success:
2771 return 1;
2772
2773 failure:
2774
2775 if (data && *data)
2776 {
2777 xfree (*data);
2778 *data = NULL;
2779 }
2780 return 0;
2781
2782 #undef match
2783 #undef expect
2784 #undef expect_ident
2785 }
2786
2787
2788 /* Load XBM image IMG which will be displayed on frame F from buffer
2789 CONTENTS. END is the end of the buffer. Value is non-zero if
2790 successful. */
2791
2792 static int
2793 xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
2794 unsigned char *end)
2795 {
2796 int rc;
2797 unsigned char *data;
2798 int success_p = 0;
2799
2800 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
2801 &data, 0);
2802 if (rc)
2803 {
2804 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2805 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
2806 int non_default_colors = 0;
2807 Lisp_Object value;
2808
2809 xassert (img->width > 0 && img->height > 0);
2810
2811 /* Get foreground and background colors, maybe allocate colors. */
2812 value = image_spec_value (img->spec, QCforeground, NULL);
2813 if (!NILP (value))
2814 {
2815 foreground = x_alloc_image_color (f, img, value, foreground);
2816 non_default_colors = 1;
2817 }
2818 value = image_spec_value (img->spec, QCbackground, NULL);
2819 if (!NILP (value))
2820 {
2821 background = x_alloc_image_color (f, img, value, background);
2822 img->background = background;
2823 img->background_valid = 1;
2824 non_default_colors = 1;
2825 }
2826
2827 Create_Pixmap_From_Bitmap_Data (f, img, data,
2828 foreground, background,
2829 non_default_colors);
2830 xfree (data);
2831
2832 if (img->pixmap == NO_PIXMAP)
2833 {
2834 x_clear_image (f, img);
2835 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
2836 }
2837 else
2838 success_p = 1;
2839 }
2840 else
2841 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
2842
2843 return success_p;
2844 }
2845
2846
2847 /* Value is non-zero if DATA looks like an in-memory XBM file. */
2848
2849 static int
2850 xbm_file_p (Lisp_Object data)
2851 {
2852 int w, h;
2853 return (STRINGP (data)
2854 && xbm_read_bitmap_data (NULL, SDATA (data),
2855 (SDATA (data) + SBYTES (data)),
2856 &w, &h, NULL, 1));
2857 }
2858
2859
2860 /* Fill image IMG which is used on frame F with pixmap data. Value is
2861 non-zero if successful. */
2862
2863 static int
2864 xbm_load (struct frame *f, struct image *img)
2865 {
2866 int success_p = 0;
2867 Lisp_Object file_name;
2868
2869 xassert (xbm_image_p (img->spec));
2870
2871 /* If IMG->spec specifies a file name, create a non-file spec from it. */
2872 file_name = image_spec_value (img->spec, QCfile, NULL);
2873 if (STRINGP (file_name))
2874 {
2875 Lisp_Object file;
2876 unsigned char *contents;
2877 int size;
2878 struct gcpro gcpro1;
2879
2880 file = x_find_image_file (file_name);
2881 GCPRO1 (file);
2882 if (!STRINGP (file))
2883 {
2884 image_error ("Cannot find image file `%s'", file_name, Qnil);
2885 UNGCPRO;
2886 return 0;
2887 }
2888
2889 contents = slurp_file (SDATA (file), &size);
2890 if (contents == NULL)
2891 {
2892 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
2893 UNGCPRO;
2894 return 0;
2895 }
2896
2897 success_p = xbm_load_image (f, img, contents, contents + size);
2898 UNGCPRO;
2899 }
2900 else
2901 {
2902 struct image_keyword fmt[XBM_LAST];
2903 Lisp_Object data;
2904 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2905 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
2906 int non_default_colors = 0;
2907 char *bits;
2908 int parsed_p;
2909 int in_memory_file_p = 0;
2910
2911 /* See if data looks like an in-memory XBM file. */
2912 data = image_spec_value (img->spec, QCdata, NULL);
2913 in_memory_file_p = xbm_file_p (data);
2914
2915 /* Parse the image specification. */
2916 memcpy (fmt, xbm_format, sizeof fmt);
2917 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
2918 xassert (parsed_p);
2919
2920 /* Get specified width, and height. */
2921 if (!in_memory_file_p)
2922 {
2923 img->width = XFASTINT (fmt[XBM_WIDTH].value);
2924 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
2925 xassert (img->width > 0 && img->height > 0);
2926 }
2927
2928 /* Get foreground and background colors, maybe allocate colors. */
2929 if (fmt[XBM_FOREGROUND].count
2930 && STRINGP (fmt[XBM_FOREGROUND].value))
2931 {
2932 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
2933 foreground);
2934 non_default_colors = 1;
2935 }
2936
2937 if (fmt[XBM_BACKGROUND].count
2938 && STRINGP (fmt[XBM_BACKGROUND].value))
2939 {
2940 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
2941 background);
2942 non_default_colors = 1;
2943 }
2944
2945 if (in_memory_file_p)
2946 success_p = xbm_load_image (f, img, SDATA (data),
2947 (SDATA (data)
2948 + SBYTES (data)));
2949 else
2950 {
2951 if (VECTORP (data))
2952 {
2953 int i;
2954 char *p;
2955 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
2956
2957 p = bits = (char *) alloca (nbytes * img->height);
2958 for (i = 0; i < img->height; ++i, p += nbytes)
2959 {
2960 Lisp_Object line = XVECTOR (data)->contents[i];
2961 if (STRINGP (line))
2962 memcpy (p, SDATA (line), nbytes);
2963 else
2964 memcpy (p, XBOOL_VECTOR (line)->data, nbytes);
2965 }
2966 }
2967 else if (STRINGP (data))
2968 bits = SDATA (data);
2969 else
2970 bits = XBOOL_VECTOR (data)->data;
2971
2972 #ifdef WINDOWSNT
2973 {
2974 char *invertedBits;
2975 int nbytes, i;
2976 /* Windows mono bitmaps are reversed compared with X. */
2977 invertedBits = bits;
2978 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
2979 * img->height;
2980 bits = (char *) alloca (nbytes);
2981 for (i = 0; i < nbytes; i++)
2982 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
2983 }
2984 #endif
2985 /* Create the pixmap. */
2986
2987 Create_Pixmap_From_Bitmap_Data (f, img, bits,
2988 foreground, background,
2989 non_default_colors);
2990 if (img->pixmap)
2991 success_p = 1;
2992 else
2993 {
2994 image_error ("Unable to create pixmap for XBM image `%s'",
2995 img->spec, Qnil);
2996 x_clear_image (f, img);
2997 }
2998 }
2999 }
3000
3001 return success_p;
3002 }
3003
3004
3005 \f
3006 /***********************************************************************
3007 XPM images
3008 ***********************************************************************/
3009
3010 #if defined (HAVE_XPM) || defined (HAVE_NS)
3011
3012 static int xpm_image_p (Lisp_Object object);
3013 static int xpm_load (struct frame *f, struct image *img);
3014 static int xpm_valid_color_symbols_p (Lisp_Object);
3015
3016 #endif /* HAVE_XPM || HAVE_NS */
3017
3018 #ifdef HAVE_XPM
3019 #ifdef HAVE_NTGUI
3020 /* Indicate to xpm.h that we don't have Xlib. */
3021 #define FOR_MSW
3022 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3023 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3024 #define XColor xpm_XColor
3025 #define XImage xpm_XImage
3026 #define Display xpm_Display
3027 #define PIXEL_ALREADY_TYPEDEFED
3028 #include "X11/xpm.h"
3029 #undef FOR_MSW
3030 #undef XColor
3031 #undef XImage
3032 #undef Display
3033 #undef PIXEL_ALREADY_TYPEDEFED
3034 #else
3035 #include "X11/xpm.h"
3036 #endif /* HAVE_NTGUI */
3037 #endif /* HAVE_XPM */
3038
3039 #if defined (HAVE_XPM) || defined (HAVE_NS)
3040 /* The symbol `xpm' identifying XPM-format images. */
3041
3042 Lisp_Object Qxpm;
3043
3044 /* Indices of image specification fields in xpm_format, below. */
3045
3046 enum xpm_keyword_index
3047 {
3048 XPM_TYPE,
3049 XPM_FILE,
3050 XPM_DATA,
3051 XPM_ASCENT,
3052 XPM_MARGIN,
3053 XPM_RELIEF,
3054 XPM_ALGORITHM,
3055 XPM_HEURISTIC_MASK,
3056 XPM_MASK,
3057 XPM_COLOR_SYMBOLS,
3058 XPM_BACKGROUND,
3059 XPM_LAST
3060 };
3061
3062 /* Vector of image_keyword structures describing the format
3063 of valid XPM image specifications. */
3064
3065 static const struct image_keyword xpm_format[XPM_LAST] =
3066 {
3067 {":type", IMAGE_SYMBOL_VALUE, 1},
3068 {":file", IMAGE_STRING_VALUE, 0},
3069 {":data", IMAGE_STRING_VALUE, 0},
3070 {":ascent", IMAGE_ASCENT_VALUE, 0},
3071 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3072 {":relief", IMAGE_INTEGER_VALUE, 0},
3073 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3074 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3075 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3076 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3077 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3078 };
3079
3080 /* Structure describing the image type XPM. */
3081
3082 static struct image_type xpm_type =
3083 {
3084 &Qxpm,
3085 xpm_image_p,
3086 xpm_load,
3087 x_clear_image,
3088 NULL
3089 };
3090
3091 #ifdef HAVE_X_WINDOWS
3092
3093 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3094 functions for allocating image colors. Our own functions handle
3095 color allocation failures more gracefully than the ones on the XPM
3096 lib. */
3097
3098 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3099 #define ALLOC_XPM_COLORS
3100 #endif
3101 #endif /* HAVE_X_WINDOWS */
3102
3103 #ifdef ALLOC_XPM_COLORS
3104
3105 static void xpm_init_color_cache (struct frame *, XpmAttributes *);
3106 static void xpm_free_color_cache (void);
3107 static int xpm_lookup_color (struct frame *, char *, XColor *);
3108 static int xpm_color_bucket (char *);
3109 static struct xpm_cached_color *xpm_cache_color (struct frame *, char *,
3110 XColor *, int);
3111
3112 /* An entry in a hash table used to cache color definitions of named
3113 colors. This cache is necessary to speed up XPM image loading in
3114 case we do color allocations ourselves. Without it, we would need
3115 a call to XParseColor per pixel in the image. */
3116
3117 struct xpm_cached_color
3118 {
3119 /* Next in collision chain. */
3120 struct xpm_cached_color *next;
3121
3122 /* Color definition (RGB and pixel color). */
3123 XColor color;
3124
3125 /* Color name. */
3126 char name[1];
3127 };
3128
3129 /* The hash table used for the color cache, and its bucket vector
3130 size. */
3131
3132 #define XPM_COLOR_CACHE_BUCKETS 1001
3133 struct xpm_cached_color **xpm_color_cache;
3134
3135 /* Initialize the color cache. */
3136
3137 static void
3138 xpm_init_color_cache (struct frame *f, XpmAttributes *attrs)
3139 {
3140 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3141 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3142 memset (xpm_color_cache, 0, nbytes);
3143 init_color_table ();
3144
3145 if (attrs->valuemask & XpmColorSymbols)
3146 {
3147 int i;
3148 XColor color;
3149
3150 for (i = 0; i < attrs->numsymbols; ++i)
3151 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3152 attrs->colorsymbols[i].value, &color))
3153 {
3154 color.pixel = lookup_rgb_color (f, color.red, color.green,
3155 color.blue);
3156 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3157 }
3158 }
3159 }
3160
3161 /* Free the color cache. */
3162
3163 static void
3164 xpm_free_color_cache (void)
3165 {
3166 struct xpm_cached_color *p, *next;
3167 int i;
3168
3169 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3170 for (p = xpm_color_cache[i]; p; p = next)
3171 {
3172 next = p->next;
3173 xfree (p);
3174 }
3175
3176 xfree (xpm_color_cache);
3177 xpm_color_cache = NULL;
3178 free_color_table ();
3179 }
3180
3181 /* Return the bucket index for color named COLOR_NAME in the color
3182 cache. */
3183
3184 static int
3185 xpm_color_bucket (char *color_name)
3186 {
3187 unsigned h = 0;
3188 char *s;
3189
3190 for (s = color_name; *s; ++s)
3191 h = (h << 2) ^ *s;
3192 return h %= XPM_COLOR_CACHE_BUCKETS;
3193 }
3194
3195
3196 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3197 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3198 entry added. */
3199
3200 static struct xpm_cached_color *
3201 xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket)
3202 {
3203 size_t nbytes;
3204 struct xpm_cached_color *p;
3205
3206 if (bucket < 0)
3207 bucket = xpm_color_bucket (color_name);
3208
3209 nbytes = sizeof *p + strlen (color_name);
3210 p = (struct xpm_cached_color *) xmalloc (nbytes);
3211 strcpy (p->name, color_name);
3212 p->color = *color;
3213 p->next = xpm_color_cache[bucket];
3214 xpm_color_cache[bucket] = p;
3215 return p;
3216 }
3217
3218 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3219 return the cached definition in *COLOR. Otherwise, make a new
3220 entry in the cache and allocate the color. Value is zero if color
3221 allocation failed. */
3222
3223 static int
3224 xpm_lookup_color (struct frame *f, char *color_name, XColor *color)
3225 {
3226 struct xpm_cached_color *p;
3227 int h = xpm_color_bucket (color_name);
3228
3229 for (p = xpm_color_cache[h]; p; p = p->next)
3230 if (strcmp (p->name, color_name) == 0)
3231 break;
3232
3233 if (p != NULL)
3234 *color = p->color;
3235 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3236 color_name, color))
3237 {
3238 color->pixel = lookup_rgb_color (f, color->red, color->green,
3239 color->blue);
3240 p = xpm_cache_color (f, color_name, color, h);
3241 }
3242 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3243 with transparency, and it's useful. */
3244 else if (strcmp ("opaque", color_name) == 0)
3245 {
3246 memset (color, 0, sizeof (XColor)); /* Is this necessary/correct? */
3247 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3248 p = xpm_cache_color (f, color_name, color, h);
3249 }
3250
3251 return p != NULL;
3252 }
3253
3254
3255 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3256 CLOSURE is a pointer to the frame on which we allocate the
3257 color. Return in *COLOR the allocated color. Value is non-zero
3258 if successful. */
3259
3260 static int
3261 xpm_alloc_color (Display *dpy, Colormap cmap, char *color_name, XColor *color,
3262 void *closure)
3263 {
3264 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3265 }
3266
3267
3268 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3269 is a pointer to the frame on which we allocate the color. Value is
3270 non-zero if successful. */
3271
3272 static int
3273 xpm_free_colors (Display *dpy, Colormap cmap, Pixel *pixels, int npixels, void *closure)
3274 {
3275 return 1;
3276 }
3277
3278 #endif /* ALLOC_XPM_COLORS */
3279
3280
3281 #ifdef HAVE_NTGUI
3282
3283 /* XPM library details. */
3284
3285 DEF_IMGLIB_FN (XpmFreeAttributes);
3286 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
3287 DEF_IMGLIB_FN (XpmReadFileToImage);
3288 DEF_IMGLIB_FN (XImageFree);
3289
3290 static int
3291 init_xpm_functions (Lisp_Object libraries)
3292 {
3293 HMODULE library;
3294
3295 if (!(library = w32_delayed_load (libraries, Qxpm)))
3296 return 0;
3297
3298 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3299 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3300 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3301 LOAD_IMGLIB_FN (library, XImageFree);
3302 return 1;
3303 }
3304
3305 #endif /* HAVE_NTGUI */
3306
3307
3308 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3309 for XPM images. Such a list must consist of conses whose car and
3310 cdr are strings. */
3311
3312 static int
3313 xpm_valid_color_symbols_p (Lisp_Object color_symbols)
3314 {
3315 while (CONSP (color_symbols))
3316 {
3317 Lisp_Object sym = XCAR (color_symbols);
3318 if (!CONSP (sym)
3319 || !STRINGP (XCAR (sym))
3320 || !STRINGP (XCDR (sym)))
3321 break;
3322 color_symbols = XCDR (color_symbols);
3323 }
3324
3325 return NILP (color_symbols);
3326 }
3327
3328
3329 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3330
3331 static int
3332 xpm_image_p (Lisp_Object object)
3333 {
3334 struct image_keyword fmt[XPM_LAST];
3335 memcpy (fmt, xpm_format, sizeof fmt);
3336 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3337 /* Either `:file' or `:data' must be present. */
3338 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3339 /* Either no `:color-symbols' or it's a list of conses
3340 whose car and cdr are strings. */
3341 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3342 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3343 }
3344
3345 #endif /* HAVE_XPM || HAVE_NS */
3346
3347 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3348 int
3349 x_create_bitmap_from_xpm_data (struct frame *f, char **bits)
3350 {
3351 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3352 int id, rc;
3353 XpmAttributes attrs;
3354 Pixmap bitmap, mask;
3355
3356 memset (&attrs, 0, sizeof attrs);
3357
3358 attrs.visual = FRAME_X_VISUAL (f);
3359 attrs.colormap = FRAME_X_COLORMAP (f);
3360 attrs.valuemask |= XpmVisual;
3361 attrs.valuemask |= XpmColormap;
3362
3363 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3364 bits, &bitmap, &mask, &attrs);
3365 if (rc != XpmSuccess)
3366 {
3367 XpmFreeAttributes (&attrs);
3368 return -1;
3369 }
3370
3371 id = x_allocate_bitmap_record (f);
3372 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
3373 dpyinfo->bitmaps[id - 1].have_mask = 1;
3374 dpyinfo->bitmaps[id - 1].mask = mask;
3375 dpyinfo->bitmaps[id - 1].file = NULL;
3376 dpyinfo->bitmaps[id - 1].height = attrs.height;
3377 dpyinfo->bitmaps[id - 1].width = attrs.width;
3378 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
3379 dpyinfo->bitmaps[id - 1].refcount = 1;
3380
3381 XpmFreeAttributes (&attrs);
3382 return id;
3383 }
3384 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3385
3386 /* Load image IMG which will be displayed on frame F. Value is
3387 non-zero if successful. */
3388
3389 #ifdef HAVE_XPM
3390
3391 static int
3392 xpm_load (struct frame *f, struct image *img)
3393 {
3394 int rc;
3395 XpmAttributes attrs;
3396 Lisp_Object specified_file, color_symbols;
3397 #ifdef HAVE_NTGUI
3398 HDC hdc;
3399 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3400 #endif /* HAVE_NTGUI */
3401
3402 /* Configure the XPM lib. Use the visual of frame F. Allocate
3403 close colors. Return colors allocated. */
3404 memset (&attrs, 0, sizeof attrs);
3405
3406 #ifndef HAVE_NTGUI
3407 attrs.visual = FRAME_X_VISUAL (f);
3408 attrs.colormap = FRAME_X_COLORMAP (f);
3409 attrs.valuemask |= XpmVisual;
3410 attrs.valuemask |= XpmColormap;
3411 #endif /* HAVE_NTGUI */
3412
3413 #ifdef ALLOC_XPM_COLORS
3414 /* Allocate colors with our own functions which handle
3415 failing color allocation more gracefully. */
3416 attrs.color_closure = f;
3417 attrs.alloc_color = xpm_alloc_color;
3418 attrs.free_colors = xpm_free_colors;
3419 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3420 #else /* not ALLOC_XPM_COLORS */
3421 /* Let the XPM lib allocate colors. */
3422 attrs.valuemask |= XpmReturnAllocPixels;
3423 #ifdef XpmAllocCloseColors
3424 attrs.alloc_close_colors = 1;
3425 attrs.valuemask |= XpmAllocCloseColors;
3426 #else /* not XpmAllocCloseColors */
3427 attrs.closeness = 600;
3428 attrs.valuemask |= XpmCloseness;
3429 #endif /* not XpmAllocCloseColors */
3430 #endif /* ALLOC_XPM_COLORS */
3431
3432 /* If image specification contains symbolic color definitions, add
3433 these to `attrs'. */
3434 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3435 if (CONSP (color_symbols))
3436 {
3437 Lisp_Object tail;
3438 XpmColorSymbol *xpm_syms;
3439 int i, size;
3440
3441 attrs.valuemask |= XpmColorSymbols;
3442
3443 /* Count number of symbols. */
3444 attrs.numsymbols = 0;
3445 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3446 ++attrs.numsymbols;
3447
3448 /* Allocate an XpmColorSymbol array. */
3449 size = attrs.numsymbols * sizeof *xpm_syms;
3450 xpm_syms = (XpmColorSymbol *) alloca (size);
3451 memset (xpm_syms, 0, size);
3452 attrs.colorsymbols = xpm_syms;
3453
3454 /* Fill the color symbol array. */
3455 for (tail = color_symbols, i = 0;
3456 CONSP (tail);
3457 ++i, tail = XCDR (tail))
3458 {
3459 Lisp_Object name = XCAR (XCAR (tail));
3460 Lisp_Object color = XCDR (XCAR (tail));
3461 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
3462 strcpy (xpm_syms[i].name, SDATA (name));
3463 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
3464 strcpy (xpm_syms[i].value, SDATA (color));
3465 }
3466 }
3467
3468 /* Create a pixmap for the image, either from a file, or from a
3469 string buffer containing data in the same format as an XPM file. */
3470 #ifdef ALLOC_XPM_COLORS
3471 xpm_init_color_cache (f, &attrs);
3472 #endif
3473
3474 specified_file = image_spec_value (img->spec, QCfile, NULL);
3475
3476 #ifdef HAVE_NTGUI
3477 {
3478 HDC frame_dc = get_frame_dc (f);
3479 hdc = CreateCompatibleDC (frame_dc);
3480 release_frame_dc (f, frame_dc);
3481 }
3482 #endif /* HAVE_NTGUI */
3483
3484 if (STRINGP (specified_file))
3485 {
3486 Lisp_Object file = x_find_image_file (specified_file);
3487 if (!STRINGP (file))
3488 {
3489 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3490 return 0;
3491 }
3492
3493 #ifdef HAVE_NTGUI
3494 /* XpmReadFileToPixmap is not available in the Windows port of
3495 libxpm. But XpmReadFileToImage almost does what we want. */
3496 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3497 &xpm_image, &xpm_mask,
3498 &attrs);
3499 #else
3500 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3501 SDATA (file), &img->pixmap, &img->mask,
3502 &attrs);
3503 #endif /* HAVE_NTGUI */
3504 }
3505 else
3506 {
3507 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
3508 #ifdef HAVE_NTGUI
3509 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3510 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3511 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
3512 &xpm_image, &xpm_mask,
3513 &attrs);
3514 #else
3515 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3516 SDATA (buffer),
3517 &img->pixmap, &img->mask,
3518 &attrs);
3519 #endif /* HAVE_NTGUI */
3520 }
3521
3522 if (rc == XpmSuccess)
3523 {
3524 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3525 img->colors = colors_in_color_table (&img->ncolors);
3526 #else /* not ALLOC_XPM_COLORS */
3527 int i;
3528
3529 #ifdef HAVE_NTGUI
3530 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3531 plus some duplicate attributes. */
3532 if (xpm_image && xpm_image->bitmap)
3533 {
3534 img->pixmap = xpm_image->bitmap;
3535 /* XImageFree in libXpm frees XImage struct without destroying
3536 the bitmap, which is what we want. */
3537 fn_XImageFree (xpm_image);
3538 }
3539 if (xpm_mask && xpm_mask->bitmap)
3540 {
3541 /* The mask appears to be inverted compared with what we expect.
3542 TODO: invert our expectations. See other places where we
3543 have to invert bits because our idea of masks is backwards. */
3544 HGDIOBJ old_obj;
3545 old_obj = SelectObject (hdc, xpm_mask->bitmap);
3546
3547 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
3548 SelectObject (hdc, old_obj);
3549
3550 img->mask = xpm_mask->bitmap;
3551 fn_XImageFree (xpm_mask);
3552 DeleteDC (hdc);
3553 }
3554
3555 DeleteDC (hdc);
3556 #endif /* HAVE_NTGUI */
3557
3558 /* Remember allocated colors. */
3559 img->ncolors = attrs.nalloc_pixels;
3560 img->colors = (unsigned long *) xmalloc (img->ncolors
3561 * sizeof *img->colors);
3562 for (i = 0; i < attrs.nalloc_pixels; ++i)
3563 {
3564 img->colors[i] = attrs.alloc_pixels[i];
3565 #ifdef DEBUG_X_COLORS
3566 register_color (img->colors[i]);
3567 #endif
3568 }
3569 #endif /* not ALLOC_XPM_COLORS */
3570
3571 img->width = attrs.width;
3572 img->height = attrs.height;
3573 xassert (img->width > 0 && img->height > 0);
3574
3575 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3576 #ifdef HAVE_NTGUI
3577 fn_XpmFreeAttributes (&attrs);
3578 #else
3579 XpmFreeAttributes (&attrs);
3580 #endif /* HAVE_NTGUI */
3581 }
3582 else
3583 {
3584 #ifdef HAVE_NTGUI
3585 DeleteDC (hdc);
3586 #endif /* HAVE_NTGUI */
3587
3588 switch (rc)
3589 {
3590 case XpmOpenFailed:
3591 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
3592 break;
3593
3594 case XpmFileInvalid:
3595 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
3596 break;
3597
3598 case XpmNoMemory:
3599 image_error ("Out of memory (%s)", img->spec, Qnil);
3600 break;
3601
3602 case XpmColorFailed:
3603 image_error ("Color allocation error (%s)", img->spec, Qnil);
3604 break;
3605
3606 default:
3607 image_error ("Unknown error (%s)", img->spec, Qnil);
3608 break;
3609 }
3610 }
3611
3612 #ifdef ALLOC_XPM_COLORS
3613 xpm_free_color_cache ();
3614 #endif
3615 return rc == XpmSuccess;
3616 }
3617
3618 #endif /* HAVE_XPM */
3619
3620 #if defined (HAVE_NS) && !defined (HAVE_XPM)
3621
3622 /* XPM support functions for NS where libxpm is not available.
3623 Only XPM version 3 (without any extensions) is supported. */
3624
3625 static int xpm_scan (const unsigned char **, const unsigned char *,
3626 const unsigned char **, int *);
3627 static Lisp_Object xpm_make_color_table_v
3628 (void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
3629 Lisp_Object (**) (Lisp_Object, const unsigned char *, int));
3630 static void xpm_put_color_table_v (Lisp_Object, const unsigned char *,
3631 int, Lisp_Object);
3632 static Lisp_Object xpm_get_color_table_v (Lisp_Object,
3633 const unsigned char *, int);
3634 static Lisp_Object xpm_make_color_table_h
3635 (void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
3636 Lisp_Object (**) (Lisp_Object, const unsigned char *, int));
3637 static void xpm_put_color_table_h (Lisp_Object, const unsigned char *,
3638 int, Lisp_Object);
3639 static Lisp_Object xpm_get_color_table_h (Lisp_Object,
3640 const unsigned char *, int);
3641 static int xpm_str_to_color_key (const char *);
3642 static int xpm_load_image (struct frame *, struct image *,
3643 const unsigned char *, const unsigned char *);
3644
3645 /* Tokens returned from xpm_scan. */
3646
3647 enum xpm_token
3648 {
3649 XPM_TK_IDENT = 256,
3650 XPM_TK_STRING,
3651 XPM_TK_EOF
3652 };
3653
3654 /* Scan an XPM data and return a character (< 256) or a token defined
3655 by enum xpm_token above. *S and END are the start (inclusive) and
3656 the end (exclusive) addresses of the data, respectively. Advance
3657 *S while scanning. If token is either XPM_TK_IDENT or
3658 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3659 length of the corresponding token, respectively. */
3660
3661 static int
3662 xpm_scan (s, end, beg, len)
3663 const unsigned char **s, *end, **beg;
3664 int *len;
3665 {
3666 int c;
3667
3668 while (*s < end)
3669 {
3670 /* Skip white-space. */
3671 while (*s < end && (c = *(*s)++, isspace (c)))
3672 ;
3673
3674 /* gnus-pointer.xpm uses '-' in its identifier.
3675 sb-dir-plus.xpm uses '+' in its identifier. */
3676 if (isalpha (c) || c == '_' || c == '-' || c == '+')
3677 {
3678 *beg = *s - 1;
3679 while (*s < end
3680 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
3681 ++*s;
3682 *len = *s - *beg;
3683 return XPM_TK_IDENT;
3684 }
3685 else if (c == '"')
3686 {
3687 *beg = *s;
3688 while (*s < end && **s != '"')
3689 ++*s;
3690 *len = *s - *beg;
3691 if (*s < end)
3692 ++*s;
3693 return XPM_TK_STRING;
3694 }
3695 else if (c == '/')
3696 {
3697 if (*s < end && **s == '*')
3698 {
3699 /* C-style comment. */
3700 ++*s;
3701 do
3702 {
3703 while (*s < end && *(*s)++ != '*')
3704 ;
3705 }
3706 while (*s < end && **s != '/');
3707 if (*s < end)
3708 ++*s;
3709 }
3710 else
3711 return c;
3712 }
3713 else
3714 return c;
3715 }
3716
3717 return XPM_TK_EOF;
3718 }
3719
3720 /* Functions for color table lookup in XPM data. A key is a string
3721 specifying the color of each pixel in XPM data. A value is either
3722 an integer that specifies a pixel color, Qt that specifies
3723 transparency, or Qnil for the unspecified color. If the length of
3724 the key string is one, a vector is used as a table. Otherwise, a
3725 hash table is used. */
3726
3727 static Lisp_Object
3728 xpm_make_color_table_v (put_func, get_func)
3729 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3730 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
3731 {
3732 *put_func = xpm_put_color_table_v;
3733 *get_func = xpm_get_color_table_v;
3734 return Fmake_vector (make_number (256), Qnil);
3735 }
3736
3737 static void
3738 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
3739 Lisp_Object color_table;
3740 const unsigned char *chars_start;
3741 int chars_len;
3742 Lisp_Object color;
3743 {
3744 XVECTOR (color_table)->contents[*chars_start] = color;
3745 }
3746
3747 static Lisp_Object
3748 xpm_get_color_table_v (color_table, chars_start, chars_len)
3749 Lisp_Object color_table;
3750 const unsigned char *chars_start;
3751 int chars_len;
3752 {
3753 return XVECTOR (color_table)->contents[*chars_start];
3754 }
3755
3756 static Lisp_Object
3757 xpm_make_color_table_h (put_func, get_func)
3758 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3759 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
3760 {
3761 *put_func = xpm_put_color_table_h;
3762 *get_func = xpm_get_color_table_h;
3763 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
3764 make_float (DEFAULT_REHASH_SIZE),
3765 make_float (DEFAULT_REHASH_THRESHOLD),
3766 Qnil, Qnil, Qnil);
3767 }
3768
3769 static void
3770 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
3771 Lisp_Object color_table;
3772 const unsigned char *chars_start;
3773 int chars_len;
3774 Lisp_Object color;
3775 {
3776 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3777 unsigned hash_code;
3778 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
3779
3780 hash_lookup (table, chars, &hash_code);
3781 hash_put (table, chars, color, hash_code);
3782 }
3783
3784 static Lisp_Object
3785 xpm_get_color_table_h (color_table, chars_start, chars_len)
3786 Lisp_Object color_table;
3787 const unsigned char *chars_start;
3788 int chars_len;
3789 {
3790 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3791 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
3792 NULL);
3793
3794 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
3795 }
3796
3797 enum xpm_color_key {
3798 XPM_COLOR_KEY_S,
3799 XPM_COLOR_KEY_M,
3800 XPM_COLOR_KEY_G4,
3801 XPM_COLOR_KEY_G,
3802 XPM_COLOR_KEY_C
3803 };
3804
3805 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
3806
3807 static int
3808 xpm_str_to_color_key (s)
3809 const char *s;
3810 {
3811 int i;
3812
3813 for (i = 0;
3814 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
3815 i++)
3816 if (strcmp (xpm_color_key_strings[i], s) == 0)
3817 return i;
3818 return -1;
3819 }
3820
3821 static int
3822 xpm_load_image (f, img, contents, end)
3823 struct frame *f;
3824 struct image *img;
3825 const unsigned char *contents, *end;
3826 {
3827 const unsigned char *s = contents, *beg, *str;
3828 unsigned char buffer[BUFSIZ];
3829 int width, height, x, y;
3830 int num_colors, chars_per_pixel;
3831 int len, LA1;
3832 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3833 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
3834 Lisp_Object frame, color_symbols, color_table;
3835 int best_key, have_mask = 0;
3836 XImagePtr ximg = NULL, mask_img = NULL;
3837
3838 #define match() \
3839 LA1 = xpm_scan (&s, end, &beg, &len)
3840
3841 #define expect(TOKEN) \
3842 if (LA1 != (TOKEN)) \
3843 goto failure; \
3844 else \
3845 match ()
3846
3847 #define expect_ident(IDENT) \
3848 if (LA1 == XPM_TK_IDENT \
3849 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
3850 match (); \
3851 else \
3852 goto failure
3853
3854 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
3855 goto failure;
3856 s += 9;
3857 match ();
3858 expect_ident ("static");
3859 expect_ident ("char");
3860 expect ('*');
3861 expect (XPM_TK_IDENT);
3862 expect ('[');
3863 expect (']');
3864 expect ('=');
3865 expect ('{');
3866 expect (XPM_TK_STRING);
3867 if (len >= BUFSIZ)
3868 goto failure;
3869 memcpy (buffer, beg, len);
3870 buffer[len] = '\0';
3871 if (sscanf (buffer, "%d %d %d %d", &width, &height,
3872 &num_colors, &chars_per_pixel) != 4
3873 || width <= 0 || height <= 0
3874 || num_colors <= 0 || chars_per_pixel <= 0)
3875 goto failure;
3876
3877 if (!check_image_size (f, width, height))
3878 {
3879 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
3880 goto failure;
3881 }
3882
3883 expect (',');
3884
3885 XSETFRAME (frame, f);
3886 if (!NILP (Fxw_display_color_p (frame)))
3887 best_key = XPM_COLOR_KEY_C;
3888 else if (!NILP (Fx_display_grayscale_p (frame)))
3889 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
3890 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
3891 else
3892 best_key = XPM_COLOR_KEY_M;
3893
3894 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3895 if (chars_per_pixel == 1)
3896 color_table = xpm_make_color_table_v (&put_color_table,
3897 &get_color_table);
3898 else
3899 color_table = xpm_make_color_table_h (&put_color_table,
3900 &get_color_table);
3901
3902 while (num_colors-- > 0)
3903 {
3904 unsigned char *color, *max_color;
3905 int key, next_key, max_key = 0;
3906 Lisp_Object symbol_color = Qnil, color_val;
3907 XColor cdef;
3908
3909 expect (XPM_TK_STRING);
3910 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
3911 goto failure;
3912 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
3913 buffer[len - chars_per_pixel] = '\0';
3914
3915 str = strtok (buffer, " \t");
3916 if (str == NULL)
3917 goto failure;
3918 key = xpm_str_to_color_key (str);
3919 if (key < 0)
3920 goto failure;
3921 do
3922 {
3923 color = strtok (NULL, " \t");
3924 if (color == NULL)
3925 goto failure;
3926
3927 while ((str = strtok (NULL, " \t")) != NULL)
3928 {
3929 next_key = xpm_str_to_color_key (str);
3930 if (next_key >= 0)
3931 break;
3932 color[strlen (color)] = ' ';
3933 }
3934
3935 if (key == XPM_COLOR_KEY_S)
3936 {
3937 if (NILP (symbol_color))
3938 symbol_color = build_string (color);
3939 }
3940 else if (max_key < key && key <= best_key)
3941 {
3942 max_key = key;
3943 max_color = color;
3944 }
3945 key = next_key;
3946 }
3947 while (str);
3948
3949 color_val = Qnil;
3950 if (!NILP (color_symbols) && !NILP (symbol_color))
3951 {
3952 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
3953
3954 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
3955 {
3956 if (xstrcasecmp (SDATA (XCDR (specified_color)), "None") == 0)
3957 color_val = Qt;
3958 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
3959 &cdef, 0))
3960 color_val = make_number (cdef.pixel);
3961 }
3962 }
3963 if (NILP (color_val) && max_key > 0)
3964 {
3965 if (xstrcasecmp (max_color, "None") == 0)
3966 color_val = Qt;
3967 else if (x_defined_color (f, max_color, &cdef, 0))
3968 color_val = make_number (cdef.pixel);
3969 }
3970 if (!NILP (color_val))
3971 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
3972
3973 expect (',');
3974 }
3975
3976 if (!x_create_x_image_and_pixmap (f, width, height, 0,
3977 &ximg, &img->pixmap)
3978 #ifndef HAVE_NS
3979 || !x_create_x_image_and_pixmap (f, width, height, 1,
3980 &mask_img, &img->mask)
3981 #endif
3982 )
3983 {
3984 image_error ("Out of memory (%s)", img->spec, Qnil);
3985 goto error;
3986 }
3987
3988 for (y = 0; y < height; y++)
3989 {
3990 expect (XPM_TK_STRING);
3991 str = beg;
3992 if (len < width * chars_per_pixel)
3993 goto failure;
3994 for (x = 0; x < width; x++, str += chars_per_pixel)
3995 {
3996 Lisp_Object color_val =
3997 (*get_color_table) (color_table, str, chars_per_pixel);
3998
3999 XPutPixel (ximg, x, y,
4000 (INTEGERP (color_val) ? XINT (color_val)
4001 : FRAME_FOREGROUND_PIXEL (f)));
4002 #ifndef HAVE_NS
4003 XPutPixel (mask_img, x, y,
4004 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4005 : (have_mask = 1, PIX_MASK_RETAIN)));
4006 #else
4007 if (EQ (color_val, Qt))
4008 ns_set_alpha (ximg, x, y, 0);
4009 #endif
4010 }
4011 if (y + 1 < height)
4012 expect (',');
4013 }
4014
4015 img->width = width;
4016 img->height = height;
4017
4018 /* Maybe fill in the background field while we have ximg handy. */
4019 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4020 IMAGE_BACKGROUND (img, f, ximg);
4021
4022 x_put_x_image (f, ximg, img->pixmap, width, height);
4023 x_destroy_x_image (ximg);
4024 #ifndef HAVE_NS
4025 if (have_mask)
4026 {
4027 /* Fill in the background_transparent field while we have the
4028 mask handy. */
4029 image_background_transparent (img, f, mask_img);
4030
4031 x_put_x_image (f, mask_img, img->mask, width, height);
4032 x_destroy_x_image (mask_img);
4033 }
4034 else
4035 {
4036 x_destroy_x_image (mask_img);
4037 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4038 img->mask = NO_PIXMAP;
4039 }
4040 #endif
4041 return 1;
4042
4043 failure:
4044 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4045 error:
4046 x_destroy_x_image (ximg);
4047 x_destroy_x_image (mask_img);
4048 x_clear_image (f, img);
4049 return 0;
4050
4051 #undef match
4052 #undef expect
4053 #undef expect_ident
4054 }
4055
4056 static int
4057 xpm_load (f, img)
4058 struct frame *f;
4059 struct image *img;
4060 {
4061 int success_p = 0;
4062 Lisp_Object file_name;
4063
4064 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4065 file_name = image_spec_value (img->spec, QCfile, NULL);
4066 if (STRINGP (file_name))
4067 {
4068 Lisp_Object file;
4069 unsigned char *contents;
4070 int size;
4071 struct gcpro gcpro1;
4072
4073 file = x_find_image_file (file_name);
4074 GCPRO1 (file);
4075 if (!STRINGP (file))
4076 {
4077 image_error ("Cannot find image file `%s'", file_name, Qnil);
4078 UNGCPRO;
4079 return 0;
4080 }
4081
4082 contents = slurp_file (SDATA (file), &size);
4083 if (contents == NULL)
4084 {
4085 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4086 UNGCPRO;
4087 return 0;
4088 }
4089
4090 success_p = xpm_load_image (f, img, contents, contents + size);
4091 xfree (contents);
4092 UNGCPRO;
4093 }
4094 else
4095 {
4096 Lisp_Object data;
4097
4098 data = image_spec_value (img->spec, QCdata, NULL);
4099 success_p = xpm_load_image (f, img, SDATA (data),
4100 SDATA (data) + SBYTES (data));
4101 }
4102
4103 return success_p;
4104 }
4105
4106 #endif /* HAVE_NS && !HAVE_XPM */
4107
4108
4109 \f
4110 /***********************************************************************
4111 Color table
4112 ***********************************************************************/
4113
4114 #ifdef COLOR_TABLE_SUPPORT
4115
4116 /* An entry in the color table mapping an RGB color to a pixel color. */
4117
4118 struct ct_color
4119 {
4120 int r, g, b;
4121 unsigned long pixel;
4122
4123 /* Next in color table collision list. */
4124 struct ct_color *next;
4125 };
4126
4127 /* The bucket vector size to use. Must be prime. */
4128
4129 #define CT_SIZE 101
4130
4131 /* Value is a hash of the RGB color given by R, G, and B. */
4132
4133 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4134
4135 /* The color hash table. */
4136
4137 struct ct_color **ct_table;
4138
4139 /* Number of entries in the color table. */
4140
4141 int ct_colors_allocated;
4142
4143 /* Initialize the color table. */
4144
4145 static void
4146 init_color_table (void)
4147 {
4148 int size = CT_SIZE * sizeof (*ct_table);
4149 ct_table = (struct ct_color **) xmalloc (size);
4150 memset (ct_table, 0, size);
4151 ct_colors_allocated = 0;
4152 }
4153
4154
4155 /* Free memory associated with the color table. */
4156
4157 static void
4158 free_color_table (void)
4159 {
4160 int i;
4161 struct ct_color *p, *next;
4162
4163 for (i = 0; i < CT_SIZE; ++i)
4164 for (p = ct_table[i]; p; p = next)
4165 {
4166 next = p->next;
4167 xfree (p);
4168 }
4169
4170 xfree (ct_table);
4171 ct_table = NULL;
4172 }
4173
4174
4175 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4176 entry for that color already is in the color table, return the
4177 pixel color of that entry. Otherwise, allocate a new color for R,
4178 G, B, and make an entry in the color table. */
4179
4180 static unsigned long
4181 lookup_rgb_color (struct frame *f, int r, int g, int b)
4182 {
4183 unsigned hash = CT_HASH_RGB (r, g, b);
4184 int i = hash % CT_SIZE;
4185 struct ct_color *p;
4186 Display_Info *dpyinfo;
4187
4188 /* Handle TrueColor visuals specially, which improves performance by
4189 two orders of magnitude. Freeing colors on TrueColor visuals is
4190 a nop, and pixel colors specify RGB values directly. See also
4191 the Xlib spec, chapter 3.1. */
4192 dpyinfo = FRAME_X_DISPLAY_INFO (f);
4193 if (dpyinfo->red_bits > 0)
4194 {
4195 unsigned long pr, pg, pb;
4196
4197 /* Apply gamma-correction like normal color allocation does. */
4198 if (f->gamma)
4199 {
4200 XColor color;
4201 color.red = r, color.green = g, color.blue = b;
4202 gamma_correct (f, &color);
4203 r = color.red, g = color.green, b = color.blue;
4204 }
4205
4206 /* Scale down RGB values to the visual's bits per RGB, and shift
4207 them to the right position in the pixel color. Note that the
4208 original RGB values are 16-bit values, as usual in X. */
4209 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
4210 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
4211 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
4212
4213 /* Assemble the pixel color. */
4214 return pr | pg | pb;
4215 }
4216
4217 for (p = ct_table[i]; p; p = p->next)
4218 if (p->r == r && p->g == g && p->b == b)
4219 break;
4220
4221 if (p == NULL)
4222 {
4223
4224 #ifdef HAVE_X_WINDOWS
4225 XColor color;
4226 Colormap cmap;
4227 int rc;
4228
4229 color.red = r;
4230 color.green = g;
4231 color.blue = b;
4232
4233 cmap = FRAME_X_COLORMAP (f);
4234 rc = x_alloc_nearest_color (f, cmap, &color);
4235 if (rc)
4236 {
4237 ++ct_colors_allocated;
4238 p = (struct ct_color *) xmalloc (sizeof *p);
4239 p->r = r;
4240 p->g = g;
4241 p->b = b;
4242 p->pixel = color.pixel;
4243 p->next = ct_table[i];
4244 ct_table[i] = p;
4245 }
4246 else
4247 return FRAME_FOREGROUND_PIXEL (f);
4248
4249 #else
4250 COLORREF color;
4251 #ifdef HAVE_NTGUI
4252 color = PALETTERGB (r, g, b);
4253 #else
4254 color = RGB_TO_ULONG (r, g, b);
4255 #endif /* HAVE_NTGUI */
4256 ++ct_colors_allocated;
4257 p = (struct ct_color *) xmalloc (sizeof *p);
4258 p->r = r;
4259 p->g = g;
4260 p->b = b;
4261 p->pixel = color;
4262 p->next = ct_table[i];
4263 ct_table[i] = p;
4264 #endif /* HAVE_X_WINDOWS */
4265
4266 }
4267
4268 return p->pixel;
4269 }
4270
4271
4272 /* Look up pixel color PIXEL which is used on frame F in the color
4273 table. If not already present, allocate it. Value is PIXEL. */
4274
4275 static unsigned long
4276 lookup_pixel_color (struct frame *f, unsigned long pixel)
4277 {
4278 int i = pixel % CT_SIZE;
4279 struct ct_color *p;
4280
4281 for (p = ct_table[i]; p; p = p->next)
4282 if (p->pixel == pixel)
4283 break;
4284
4285 if (p == NULL)
4286 {
4287 XColor color;
4288 Colormap cmap;
4289 int rc;
4290
4291 #ifdef HAVE_X_WINDOWS
4292 cmap = FRAME_X_COLORMAP (f);
4293 color.pixel = pixel;
4294 x_query_color (f, &color);
4295 rc = x_alloc_nearest_color (f, cmap, &color);
4296 #else
4297 BLOCK_INPUT;
4298 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
4299 color.pixel = pixel;
4300 XQueryColor (NULL, cmap, &color);
4301 rc = x_alloc_nearest_color (f, cmap, &color);
4302 UNBLOCK_INPUT;
4303 #endif /* HAVE_X_WINDOWS */
4304
4305 if (rc)
4306 {
4307 ++ct_colors_allocated;
4308
4309 p = (struct ct_color *) xmalloc (sizeof *p);
4310 p->r = color.red;
4311 p->g = color.green;
4312 p->b = color.blue;
4313 p->pixel = pixel;
4314 p->next = ct_table[i];
4315 ct_table[i] = p;
4316 }
4317 else
4318 return FRAME_FOREGROUND_PIXEL (f);
4319 }
4320 return p->pixel;
4321 }
4322
4323
4324 /* Value is a vector of all pixel colors contained in the color table,
4325 allocated via xmalloc. Set *N to the number of colors. */
4326
4327 static unsigned long *
4328 colors_in_color_table (int *n)
4329 {
4330 int i, j;
4331 struct ct_color *p;
4332 unsigned long *colors;
4333
4334 if (ct_colors_allocated == 0)
4335 {
4336 *n = 0;
4337 colors = NULL;
4338 }
4339 else
4340 {
4341 colors = (unsigned long *) xmalloc (ct_colors_allocated
4342 * sizeof *colors);
4343 *n = ct_colors_allocated;
4344
4345 for (i = j = 0; i < CT_SIZE; ++i)
4346 for (p = ct_table[i]; p; p = p->next)
4347 colors[j++] = p->pixel;
4348 }
4349
4350 return colors;
4351 }
4352
4353 #else /* COLOR_TABLE_SUPPORT */
4354
4355 static unsigned long
4356 lookup_rgb_color (f, r, g, b)
4357 struct frame *f;
4358 int r, g, b;
4359 {
4360 unsigned long pixel;
4361
4362 #ifdef HAVE_NTGUI
4363 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4364 #endif /* HAVE_NTGUI */
4365
4366 #ifdef HAVE_NS
4367 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4368 #endif /* HAVE_NS */
4369 return pixel;
4370 }
4371
4372 static void
4373 init_color_table ()
4374 {
4375 }
4376 #endif /* COLOR_TABLE_SUPPORT */
4377
4378 \f
4379 /***********************************************************************
4380 Algorithms
4381 ***********************************************************************/
4382
4383 static XColor *x_to_xcolors (struct frame *, struct image *, int);
4384 static void x_from_xcolors (struct frame *, struct image *, XColor *);
4385 static void x_detect_edges (struct frame *, struct image *, int[9], int);
4386
4387 #ifdef HAVE_NTGUI
4388 static void XPutPixel (XImagePtr , int, int, COLORREF);
4389 #endif /* HAVE_NTGUI */
4390
4391 /* Non-zero means draw a cross on images having `:conversion
4392 disabled'. */
4393
4394 int cross_disabled_images;
4395
4396 /* Edge detection matrices for different edge-detection
4397 strategies. */
4398
4399 static int emboss_matrix[9] = {
4400 /* x - 1 x x + 1 */
4401 2, -1, 0, /* y - 1 */
4402 -1, 0, 1, /* y */
4403 0, 1, -2 /* y + 1 */
4404 };
4405
4406 static int laplace_matrix[9] = {
4407 /* x - 1 x x + 1 */
4408 1, 0, 0, /* y - 1 */
4409 0, 0, 0, /* y */
4410 0, 0, -1 /* y + 1 */
4411 };
4412
4413 /* Value is the intensity of the color whose red/green/blue values
4414 are R, G, and B. */
4415
4416 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4417
4418
4419 /* On frame F, return an array of XColor structures describing image
4420 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4421 non-zero means also fill the red/green/blue members of the XColor
4422 structures. Value is a pointer to the array of XColors structures,
4423 allocated with xmalloc; it must be freed by the caller. */
4424
4425 static XColor *
4426 x_to_xcolors (struct frame *f, struct image *img, int rgb_p)
4427 {
4428 int x, y;
4429 XColor *colors, *p;
4430 XImagePtr_or_DC ximg;
4431 #ifdef HAVE_NTGUI
4432 HDC hdc;
4433 HGDIOBJ prev;
4434 #endif /* HAVE_NTGUI */
4435
4436 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
4437
4438 #ifndef HAVE_NTGUI
4439 /* Get the X image IMG->pixmap. */
4440 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4441 0, 0, img->width, img->height, ~0, ZPixmap);
4442 #else
4443 /* Load the image into a memory device context. */
4444 hdc = get_frame_dc (f);
4445 ximg = CreateCompatibleDC (hdc);
4446 release_frame_dc (f, hdc);
4447 prev = SelectObject (ximg, img->pixmap);
4448 #endif /* HAVE_NTGUI */
4449
4450 /* Fill the `pixel' members of the XColor array. I wished there
4451 were an easy and portable way to circumvent XGetPixel. */
4452 p = colors;
4453 for (y = 0; y < img->height; ++y)
4454 {
4455 XColor *row = p;
4456
4457 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4458 for (x = 0; x < img->width; ++x, ++p)
4459 p->pixel = GET_PIXEL (ximg, x, y);
4460 if (rgb_p)
4461 x_query_colors (f, row, img->width);
4462
4463 #else
4464
4465 for (x = 0; x < img->width; ++x, ++p)
4466 {
4467 /* W32_TODO: palette support needed here? */
4468 p->pixel = GET_PIXEL (ximg, x, y);
4469 if (rgb_p)
4470 {
4471 p->red = RED16_FROM_ULONG (p->pixel);
4472 p->green = GREEN16_FROM_ULONG (p->pixel);
4473 p->blue = BLUE16_FROM_ULONG (p->pixel);
4474 }
4475 }
4476 #endif /* HAVE_X_WINDOWS */
4477 }
4478
4479 Destroy_Image (ximg, prev);
4480
4481 return colors;
4482 }
4483
4484 #ifdef HAVE_NTGUI
4485
4486 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4487 created with CreateDIBSection, with the pointer to the bit values
4488 stored in ximg->data. */
4489
4490 static void
4491 XPutPixel (ximg, x, y, color)
4492 XImagePtr ximg;
4493 int x, y;
4494 COLORREF color;
4495 {
4496 int width = ximg->info.bmiHeader.biWidth;
4497 int height = ximg->info.bmiHeader.biHeight;
4498 unsigned char * pixel;
4499
4500 /* True color images. */
4501 if (ximg->info.bmiHeader.biBitCount == 24)
4502 {
4503 int rowbytes = width * 3;
4504 /* Ensure scanlines are aligned on 4 byte boundaries. */
4505 if (rowbytes % 4)
4506 rowbytes += 4 - (rowbytes % 4);
4507
4508 pixel = ximg->data + y * rowbytes + x * 3;
4509 /* Windows bitmaps are in BGR order. */
4510 *pixel = GetBValue (color);
4511 *(pixel + 1) = GetGValue (color);
4512 *(pixel + 2) = GetRValue (color);
4513 }
4514 /* Monochrome images. */
4515 else if (ximg->info.bmiHeader.biBitCount == 1)
4516 {
4517 int rowbytes = width / 8;
4518 /* Ensure scanlines are aligned on 4 byte boundaries. */
4519 if (rowbytes % 4)
4520 rowbytes += 4 - (rowbytes % 4);
4521 pixel = ximg->data + y * rowbytes + x / 8;
4522 /* Filter out palette info. */
4523 if (color & 0x00ffffff)
4524 *pixel = *pixel | (1 << x % 8);
4525 else
4526 *pixel = *pixel & ~(1 << x % 8);
4527 }
4528 else
4529 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
4530 }
4531
4532 #endif /* HAVE_NTGUI */
4533
4534 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4535 RGB members are set. F is the frame on which this all happens.
4536 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4537
4538 static void
4539 x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
4540 {
4541 int x, y;
4542 XImagePtr oimg = NULL;
4543 Pixmap pixmap;
4544 XColor *p;
4545
4546 init_color_table ();
4547
4548 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
4549 &oimg, &pixmap);
4550 p = colors;
4551 for (y = 0; y < img->height; ++y)
4552 for (x = 0; x < img->width; ++x, ++p)
4553 {
4554 unsigned long pixel;
4555 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
4556 XPutPixel (oimg, x, y, pixel);
4557 }
4558
4559 xfree (colors);
4560 x_clear_image_1 (f, img, 1, 0, 1);
4561
4562 x_put_x_image (f, oimg, pixmap, img->width, img->height);
4563 x_destroy_x_image (oimg);
4564 img->pixmap = pixmap;
4565 #ifdef COLOR_TABLE_SUPPORT
4566 img->colors = colors_in_color_table (&img->ncolors);
4567 free_color_table ();
4568 #endif /* COLOR_TABLE_SUPPORT */
4569 }
4570
4571
4572 /* On frame F, perform edge-detection on image IMG.
4573
4574 MATRIX is a nine-element array specifying the transformation
4575 matrix. See emboss_matrix for an example.
4576
4577 COLOR_ADJUST is a color adjustment added to each pixel of the
4578 outgoing image. */
4579
4580 static void
4581 x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjust)
4582 {
4583 XColor *colors = x_to_xcolors (f, img, 1);
4584 XColor *new, *p;
4585 int x, y, i, sum;
4586
4587 for (i = sum = 0; i < 9; ++i)
4588 sum += eabs (matrix[i]);
4589
4590 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4591
4592 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
4593
4594 for (y = 0; y < img->height; ++y)
4595 {
4596 p = COLOR (new, 0, y);
4597 p->red = p->green = p->blue = 0xffff/2;
4598 p = COLOR (new, img->width - 1, y);
4599 p->red = p->green = p->blue = 0xffff/2;
4600 }
4601
4602 for (x = 1; x < img->width - 1; ++x)
4603 {
4604 p = COLOR (new, x, 0);
4605 p->red = p->green = p->blue = 0xffff/2;
4606 p = COLOR (new, x, img->height - 1);
4607 p->red = p->green = p->blue = 0xffff/2;
4608 }
4609
4610 for (y = 1; y < img->height - 1; ++y)
4611 {
4612 p = COLOR (new, 1, y);
4613
4614 for (x = 1; x < img->width - 1; ++x, ++p)
4615 {
4616 int r, g, b, y1, x1;
4617
4618 r = g = b = i = 0;
4619 for (y1 = y - 1; y1 < y + 2; ++y1)
4620 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
4621 if (matrix[i])
4622 {
4623 XColor *t = COLOR (colors, x1, y1);
4624 r += matrix[i] * t->red;
4625 g += matrix[i] * t->green;
4626 b += matrix[i] * t->blue;
4627 }
4628
4629 r = (r / sum + color_adjust) & 0xffff;
4630 g = (g / sum + color_adjust) & 0xffff;
4631 b = (b / sum + color_adjust) & 0xffff;
4632 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
4633 }
4634 }
4635
4636 xfree (colors);
4637 x_from_xcolors (f, img, new);
4638
4639 #undef COLOR
4640 }
4641
4642
4643 /* Perform the pre-defined `emboss' edge-detection on image IMG
4644 on frame F. */
4645
4646 static void
4647 x_emboss (struct frame *f, struct image *img)
4648 {
4649 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
4650 }
4651
4652
4653 /* Transform image IMG which is used on frame F with a Laplace
4654 edge-detection algorithm. The result is an image that can be used
4655 to draw disabled buttons, for example. */
4656
4657 static void
4658 x_laplace (struct frame *f, struct image *img)
4659 {
4660 x_detect_edges (f, img, laplace_matrix, 45000);
4661 }
4662
4663
4664 /* Perform edge-detection on image IMG on frame F, with specified
4665 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4666
4667 MATRIX must be either
4668
4669 - a list of at least 9 numbers in row-major form
4670 - a vector of at least 9 numbers
4671
4672 COLOR_ADJUST nil means use a default; otherwise it must be a
4673 number. */
4674
4675 static void
4676 x_edge_detection (struct frame *f, struct image *img, Lisp_Object matrix,
4677 Lisp_Object color_adjust)
4678 {
4679 int i = 0;
4680 int trans[9];
4681
4682 if (CONSP (matrix))
4683 {
4684 for (i = 0;
4685 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
4686 ++i, matrix = XCDR (matrix))
4687 trans[i] = XFLOATINT (XCAR (matrix));
4688 }
4689 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
4690 {
4691 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
4692 trans[i] = XFLOATINT (AREF (matrix, i));
4693 }
4694
4695 if (NILP (color_adjust))
4696 color_adjust = make_number (0xffff / 2);
4697
4698 if (i == 9 && NUMBERP (color_adjust))
4699 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
4700 }
4701
4702
4703 /* Transform image IMG on frame F so that it looks disabled. */
4704
4705 static void
4706 x_disable_image (struct frame *f, struct image *img)
4707 {
4708 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4709 #ifdef HAVE_NTGUI
4710 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
4711 #else
4712 int n_planes = dpyinfo->n_planes;
4713 #endif /* HAVE_NTGUI */
4714
4715 if (n_planes >= 2)
4716 {
4717 /* Color (or grayscale). Convert to gray, and equalize. Just
4718 drawing such images with a stipple can look very odd, so
4719 we're using this method instead. */
4720 XColor *colors = x_to_xcolors (f, img, 1);
4721 XColor *p, *end;
4722 const int h = 15000;
4723 const int l = 30000;
4724
4725 for (p = colors, end = colors + img->width * img->height;
4726 p < end;
4727 ++p)
4728 {
4729 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
4730 int i2 = (0xffff - h - l) * i / 0xffff + l;
4731 p->red = p->green = p->blue = i2;
4732 }
4733
4734 x_from_xcolors (f, img, colors);
4735 }
4736
4737 /* Draw a cross over the disabled image, if we must or if we
4738 should. */
4739 if (n_planes < 2 || cross_disabled_images)
4740 {
4741 #ifndef HAVE_NTGUI
4742 Display *dpy = FRAME_X_DISPLAY (f);
4743 GC gc;
4744
4745 #ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
4746
4747 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4748
4749 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
4750 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
4751 XDrawLine (dpy, img->pixmap, gc, 0, 0,
4752 img->width - 1, img->height - 1);
4753 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
4754 img->width - 1, 0);
4755 XFreeGC (dpy, gc);
4756
4757 if (img->mask)
4758 {
4759 gc = XCreateGC (dpy, img->mask, 0, NULL);
4760 XSetForeground (dpy, gc, MaskForeground (f));
4761 XDrawLine (dpy, img->mask, gc, 0, 0,
4762 img->width - 1, img->height - 1);
4763 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
4764 img->width - 1, 0);
4765 XFreeGC (dpy, gc);
4766 }
4767 #endif /* !HAVE_NS */
4768 #else
4769 HDC hdc, bmpdc;
4770 HGDIOBJ prev;
4771
4772 hdc = get_frame_dc (f);
4773 bmpdc = CreateCompatibleDC (hdc);
4774 release_frame_dc (f, hdc);
4775
4776 prev = SelectObject (bmpdc, img->pixmap);
4777
4778 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
4779 MoveToEx (bmpdc, 0, 0, NULL);
4780 LineTo (bmpdc, img->width - 1, img->height - 1);
4781 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4782 LineTo (bmpdc, img->width - 1, 0);
4783
4784 if (img->mask)
4785 {
4786 SelectObject (bmpdc, img->mask);
4787 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
4788 MoveToEx (bmpdc, 0, 0, NULL);
4789 LineTo (bmpdc, img->width - 1, img->height - 1);
4790 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4791 LineTo (bmpdc, img->width - 1, 0);
4792 }
4793 SelectObject (bmpdc, prev);
4794 DeleteDC (bmpdc);
4795 #endif /* HAVE_NTGUI */
4796 }
4797 }
4798
4799
4800 /* Build a mask for image IMG which is used on frame F. FILE is the
4801 name of an image file, for error messages. HOW determines how to
4802 determine the background color of IMG. If it is a list '(R G B)',
4803 with R, G, and B being integers >= 0, take that as the color of the
4804 background. Otherwise, determine the background color of IMG
4805 heuristically. Value is non-zero if successful. */
4806
4807 static int
4808 x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4809 {
4810 XImagePtr_or_DC ximg;
4811 #ifndef HAVE_NTGUI
4812 XImagePtr mask_img;
4813 #else
4814 HDC frame_dc;
4815 HGDIOBJ prev;
4816 char *mask_img;
4817 int row_width;
4818 #endif /* HAVE_NTGUI */
4819 int x, y, rc, use_img_background;
4820 unsigned long bg = 0;
4821
4822 if (img->mask)
4823 {
4824 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4825 img->mask = NO_PIXMAP;
4826 img->background_transparent_valid = 0;
4827 }
4828
4829 #ifndef HAVE_NTGUI
4830 #ifndef HAVE_NS
4831 /* Create an image and pixmap serving as mask. */
4832 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
4833 &mask_img, &img->mask);
4834 if (!rc)
4835 return 0;
4836 #endif /* !HAVE_NS */
4837
4838 /* Get the X image of IMG->pixmap. */
4839 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
4840 img->width, img->height,
4841 ~0, ZPixmap);
4842 #else
4843 /* Create the bit array serving as mask. */
4844 row_width = (img->width + 7) / 8;
4845 mask_img = xmalloc (row_width * img->height);
4846 memset (mask_img, 0, row_width * img->height);
4847
4848 /* Create a memory device context for IMG->pixmap. */
4849 frame_dc = get_frame_dc (f);
4850 ximg = CreateCompatibleDC (frame_dc);
4851 release_frame_dc (f, frame_dc);
4852 prev = SelectObject (ximg, img->pixmap);
4853 #endif /* HAVE_NTGUI */
4854
4855 /* Determine the background color of ximg. If HOW is `(R G B)'
4856 take that as color. Otherwise, use the image's background color. */
4857 use_img_background = 1;
4858
4859 if (CONSP (how))
4860 {
4861 int rgb[3], i;
4862
4863 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
4864 {
4865 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
4866 how = XCDR (how);
4867 }
4868
4869 if (i == 3 && NILP (how))
4870 {
4871 char color_name[30];
4872 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
4873 bg = (
4874 #ifdef HAVE_NTGUI
4875 0x00ffffff & /* Filter out palette info. */
4876 #endif /* HAVE_NTGUI */
4877 x_alloc_image_color (f, img, build_string (color_name), 0));
4878 use_img_background = 0;
4879 }
4880 }
4881
4882 if (use_img_background)
4883 bg = four_corners_best (ximg, img->corners, img->width, img->height);
4884
4885 /* Set all bits in mask_img to 1 whose color in ximg is different
4886 from the background color bg. */
4887 #ifndef HAVE_NTGUI
4888 for (y = 0; y < img->height; ++y)
4889 for (x = 0; x < img->width; ++x)
4890 #ifndef HAVE_NS
4891 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
4892 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
4893 #else
4894 if (XGetPixel (ximg, x, y) == bg)
4895 ns_set_alpha (ximg, x, y, 0);
4896 #endif /* HAVE_NS */
4897 #ifndef HAVE_NS
4898 /* Fill in the background_transparent field while we have the mask handy. */
4899 image_background_transparent (img, f, mask_img);
4900
4901 /* Put mask_img into img->mask. */
4902 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
4903 x_destroy_x_image (mask_img);
4904 #endif /* !HAVE_NS */
4905 #else
4906 for (y = 0; y < img->height; ++y)
4907 for (x = 0; x < img->width; ++x)
4908 {
4909 COLORREF p = GetPixel (ximg, x, y);
4910 if (p != bg)
4911 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
4912 }
4913
4914 /* Create the mask image. */
4915 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
4916 mask_img);
4917 /* Fill in the background_transparent field while we have the mask handy. */
4918 SelectObject (ximg, img->mask);
4919 image_background_transparent (img, f, ximg);
4920
4921 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
4922 xfree (mask_img);
4923 #endif /* HAVE_NTGUI */
4924
4925 Destroy_Image (ximg, prev);
4926
4927 return 1;
4928 }
4929
4930 \f
4931 /***********************************************************************
4932 PBM (mono, gray, color)
4933 ***********************************************************************/
4934
4935 static int pbm_image_p (Lisp_Object object);
4936 static int pbm_load (struct frame *f, struct image *img);
4937 static int pbm_scan_number (unsigned char **, unsigned char *);
4938
4939 /* The symbol `pbm' identifying images of this type. */
4940
4941 Lisp_Object Qpbm;
4942
4943 /* Indices of image specification fields in gs_format, below. */
4944
4945 enum pbm_keyword_index
4946 {
4947 PBM_TYPE,
4948 PBM_FILE,
4949 PBM_DATA,
4950 PBM_ASCENT,
4951 PBM_MARGIN,
4952 PBM_RELIEF,
4953 PBM_ALGORITHM,
4954 PBM_HEURISTIC_MASK,
4955 PBM_MASK,
4956 PBM_FOREGROUND,
4957 PBM_BACKGROUND,
4958 PBM_LAST
4959 };
4960
4961 /* Vector of image_keyword structures describing the format
4962 of valid user-defined image specifications. */
4963
4964 static const struct image_keyword pbm_format[PBM_LAST] =
4965 {
4966 {":type", IMAGE_SYMBOL_VALUE, 1},
4967 {":file", IMAGE_STRING_VALUE, 0},
4968 {":data", IMAGE_STRING_VALUE, 0},
4969 {":ascent", IMAGE_ASCENT_VALUE, 0},
4970 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
4971 {":relief", IMAGE_INTEGER_VALUE, 0},
4972 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4973 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4974 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4975 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
4976 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
4977 };
4978
4979 /* Structure describing the image type `pbm'. */
4980
4981 static struct image_type pbm_type =
4982 {
4983 &Qpbm,
4984 pbm_image_p,
4985 pbm_load,
4986 x_clear_image,
4987 NULL
4988 };
4989
4990
4991 /* Return non-zero if OBJECT is a valid PBM image specification. */
4992
4993 static int
4994 pbm_image_p (Lisp_Object object)
4995 {
4996 struct image_keyword fmt[PBM_LAST];
4997
4998 memcpy (fmt, pbm_format, sizeof fmt);
4999
5000 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5001 return 0;
5002
5003 /* Must specify either :data or :file. */
5004 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5005 }
5006
5007
5008 /* Scan a decimal number from *S and return it. Advance *S while
5009 reading the number. END is the end of the string. Value is -1 at
5010 end of input. */
5011
5012 static int
5013 pbm_scan_number (unsigned char **s, unsigned char *end)
5014 {
5015 int c = 0, val = -1;
5016
5017 while (*s < end)
5018 {
5019 /* Skip white-space. */
5020 while (*s < end && (c = *(*s)++, isspace (c)))
5021 ;
5022
5023 if (c == '#')
5024 {
5025 /* Skip comment to end of line. */
5026 while (*s < end && (c = *(*s)++, c != '\n'))
5027 ;
5028 }
5029 else if (isdigit (c))
5030 {
5031 /* Read decimal number. */
5032 val = c - '0';
5033 while (*s < end && (c = *(*s)++, isdigit (c)))
5034 val = 10 * val + c - '0';
5035 break;
5036 }
5037 else
5038 break;
5039 }
5040
5041 return val;
5042 }
5043
5044
5045 #ifdef HAVE_NTGUI
5046 #if 0 /* Unused. ++kfs */
5047
5048 /* Read FILE into memory. Value is a pointer to a buffer allocated
5049 with xmalloc holding FILE's contents. Value is null if an error
5050 occurred. *SIZE is set to the size of the file. */
5051
5052 static char *
5053 pbm_read_file (file, size)
5054 Lisp_Object file;
5055 int *size;
5056 {
5057 FILE *fp = NULL;
5058 char *buf = NULL;
5059 struct stat st;
5060
5061 if (stat (SDATA (file), &st) == 0
5062 && (fp = fopen (SDATA (file), "rb")) != NULL
5063 && (buf = (char *) xmalloc (st.st_size),
5064 fread (buf, 1, st.st_size, fp) == st.st_size))
5065 {
5066 *size = st.st_size;
5067 fclose (fp);
5068 }
5069 else
5070 {
5071 if (fp)
5072 fclose (fp);
5073 if (buf)
5074 {
5075 xfree (buf);
5076 buf = NULL;
5077 }
5078 }
5079
5080 return buf;
5081 }
5082 #endif
5083 #endif /* HAVE_NTGUI */
5084
5085 /* Load PBM image IMG for use on frame F. */
5086
5087 static int
5088 pbm_load (struct frame *f, struct image *img)
5089 {
5090 int raw_p, x, y;
5091 int width, height, max_color_idx = 0;
5092 XImagePtr ximg;
5093 Lisp_Object file, specified_file;
5094 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5095 struct gcpro gcpro1;
5096 unsigned char *contents = NULL;
5097 unsigned char *end, *p;
5098 int size;
5099
5100 specified_file = image_spec_value (img->spec, QCfile, NULL);
5101 file = Qnil;
5102 GCPRO1 (file);
5103
5104 if (STRINGP (specified_file))
5105 {
5106 file = x_find_image_file (specified_file);
5107 if (!STRINGP (file))
5108 {
5109 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5110 UNGCPRO;
5111 return 0;
5112 }
5113
5114 contents = slurp_file (SDATA (file), &size);
5115 if (contents == NULL)
5116 {
5117 image_error ("Error reading `%s'", file, Qnil);
5118 UNGCPRO;
5119 return 0;
5120 }
5121
5122 p = contents;
5123 end = contents + size;
5124 }
5125 else
5126 {
5127 Lisp_Object data;
5128 data = image_spec_value (img->spec, QCdata, NULL);
5129 p = SDATA (data);
5130 end = p + SBYTES (data);
5131 }
5132
5133 /* Check magic number. */
5134 if (end - p < 2 || *p++ != 'P')
5135 {
5136 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5137 error:
5138 xfree (contents);
5139 UNGCPRO;
5140 return 0;
5141 }
5142
5143 switch (*p++)
5144 {
5145 case '1':
5146 raw_p = 0, type = PBM_MONO;
5147 break;
5148
5149 case '2':
5150 raw_p = 0, type = PBM_GRAY;
5151 break;
5152
5153 case '3':
5154 raw_p = 0, type = PBM_COLOR;
5155 break;
5156
5157 case '4':
5158 raw_p = 1, type = PBM_MONO;
5159 break;
5160
5161 case '5':
5162 raw_p = 1, type = PBM_GRAY;
5163 break;
5164
5165 case '6':
5166 raw_p = 1, type = PBM_COLOR;
5167 break;
5168
5169 default:
5170 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5171 goto error;
5172 }
5173
5174 /* Read width, height, maximum color-component. Characters
5175 starting with `#' up to the end of a line are ignored. */
5176 width = pbm_scan_number (&p, end);
5177 height = pbm_scan_number (&p, end);
5178
5179 if (type != PBM_MONO)
5180 {
5181 max_color_idx = pbm_scan_number (&p, end);
5182 if (max_color_idx > 65535 || max_color_idx < 0)
5183 {
5184 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
5185 goto error;
5186 }
5187 }
5188
5189 if (!check_image_size (f, width, height))
5190 {
5191 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
5192 goto error;
5193 }
5194
5195 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5196 &ximg, &img->pixmap))
5197 goto error;
5198
5199 /* Initialize the color hash table. */
5200 init_color_table ();
5201
5202 if (type == PBM_MONO)
5203 {
5204 int c = 0, g;
5205 struct image_keyword fmt[PBM_LAST];
5206 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5207 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5208
5209 /* Parse the image specification. */
5210 memcpy (fmt, pbm_format, sizeof fmt);
5211 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5212
5213 /* Get foreground and background colors, maybe allocate colors. */
5214 if (fmt[PBM_FOREGROUND].count
5215 && STRINGP (fmt[PBM_FOREGROUND].value))
5216 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
5217 if (fmt[PBM_BACKGROUND].count
5218 && STRINGP (fmt[PBM_BACKGROUND].value))
5219 {
5220 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
5221 img->background = bg;
5222 img->background_valid = 1;
5223 }
5224
5225 for (y = 0; y < height; ++y)
5226 for (x = 0; x < width; ++x)
5227 {
5228 if (raw_p)
5229 {
5230 if ((x & 7) == 0)
5231 {
5232 if (p >= end)
5233 {
5234 x_destroy_x_image (ximg);
5235 x_clear_image (f, img);
5236 image_error ("Invalid image size in image `%s'",
5237 img->spec, Qnil);
5238 goto error;
5239 }
5240 c = *p++;
5241 }
5242 g = c & 0x80;
5243 c <<= 1;
5244 }
5245 else
5246 g = pbm_scan_number (&p, end);
5247
5248 XPutPixel (ximg, x, y, g ? fg : bg);
5249 }
5250 }
5251 else
5252 {
5253 int expected_size = height * width;
5254 if (max_color_idx > 255)
5255 expected_size *= 2;
5256 if (type == PBM_COLOR)
5257 expected_size *= 3;
5258
5259 if (raw_p && p + expected_size > end)
5260 {
5261 x_destroy_x_image (ximg);
5262 x_clear_image (f, img);
5263 image_error ("Invalid image size in image `%s'",
5264 img->spec, Qnil);
5265 goto error;
5266 }
5267
5268 for (y = 0; y < height; ++y)
5269 for (x = 0; x < width; ++x)
5270 {
5271 int r, g, b;
5272
5273 if (type == PBM_GRAY && raw_p)
5274 {
5275 r = g = b = *p++;
5276 if (max_color_idx > 255)
5277 r = g = b = r * 256 + *p++;
5278 }
5279 else if (type == PBM_GRAY)
5280 r = g = b = pbm_scan_number (&p, end);
5281 else if (raw_p)
5282 {
5283 r = *p++;
5284 if (max_color_idx > 255)
5285 r = r * 256 + *p++;
5286 g = *p++;
5287 if (max_color_idx > 255)
5288 g = g * 256 + *p++;
5289 b = *p++;
5290 if (max_color_idx > 255)
5291 b = b * 256 + *p++;
5292 }
5293 else
5294 {
5295 r = pbm_scan_number (&p, end);
5296 g = pbm_scan_number (&p, end);
5297 b = pbm_scan_number (&p, end);
5298 }
5299
5300 if (r < 0 || g < 0 || b < 0)
5301 {
5302 x_destroy_x_image (ximg);
5303 image_error ("Invalid pixel value in image `%s'",
5304 img->spec, Qnil);
5305 goto error;
5306 }
5307
5308 /* RGB values are now in the range 0..max_color_idx.
5309 Scale this to the range 0..0xffff supported by X. */
5310 r = (double) r * 65535 / max_color_idx;
5311 g = (double) g * 65535 / max_color_idx;
5312 b = (double) b * 65535 / max_color_idx;
5313 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5314 }
5315 }
5316
5317 #ifdef COLOR_TABLE_SUPPORT
5318 /* Store in IMG->colors the colors allocated for the image, and
5319 free the color table. */
5320 img->colors = colors_in_color_table (&img->ncolors);
5321 free_color_table ();
5322 #endif /* COLOR_TABLE_SUPPORT */
5323
5324 img->width = width;
5325 img->height = height;
5326
5327 /* Maybe fill in the background field while we have ximg handy. */
5328
5329 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5330 /* Casting avoids a GCC warning. */
5331 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5332
5333 /* Put the image into a pixmap. */
5334 x_put_x_image (f, ximg, img->pixmap, width, height);
5335 x_destroy_x_image (ximg);
5336
5337 /* X and W32 versions did it here, MAC version above. ++kfs
5338 img->width = width;
5339 img->height = height; */
5340
5341 UNGCPRO;
5342 xfree (contents);
5343 return 1;
5344 }
5345
5346 \f
5347 /***********************************************************************
5348 PNG
5349 ***********************************************************************/
5350
5351 #if defined (HAVE_PNG) || defined (HAVE_NS)
5352
5353 /* Function prototypes. */
5354
5355 static int png_image_p (Lisp_Object object);
5356 static int png_load (struct frame *f, struct image *img);
5357
5358 /* The symbol `png' identifying images of this type. */
5359
5360 Lisp_Object Qpng;
5361
5362 /* Indices of image specification fields in png_format, below. */
5363
5364 enum png_keyword_index
5365 {
5366 PNG_TYPE,
5367 PNG_DATA,
5368 PNG_FILE,
5369 PNG_ASCENT,
5370 PNG_MARGIN,
5371 PNG_RELIEF,
5372 PNG_ALGORITHM,
5373 PNG_HEURISTIC_MASK,
5374 PNG_MASK,
5375 PNG_BACKGROUND,
5376 PNG_LAST
5377 };
5378
5379 /* Vector of image_keyword structures describing the format
5380 of valid user-defined image specifications. */
5381
5382 static const struct image_keyword png_format[PNG_LAST] =
5383 {
5384 {":type", IMAGE_SYMBOL_VALUE, 1},
5385 {":data", IMAGE_STRING_VALUE, 0},
5386 {":file", IMAGE_STRING_VALUE, 0},
5387 {":ascent", IMAGE_ASCENT_VALUE, 0},
5388 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5389 {":relief", IMAGE_INTEGER_VALUE, 0},
5390 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5391 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5392 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5393 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5394 };
5395
5396 /* Structure describing the image type `png'. */
5397
5398 static struct image_type png_type =
5399 {
5400 &Qpng,
5401 png_image_p,
5402 png_load,
5403 x_clear_image,
5404 NULL
5405 };
5406
5407 /* Return non-zero if OBJECT is a valid PNG image specification. */
5408
5409 static int
5410 png_image_p (Lisp_Object object)
5411 {
5412 struct image_keyword fmt[PNG_LAST];
5413 memcpy (fmt, png_format, sizeof fmt);
5414
5415 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5416 return 0;
5417
5418 /* Must specify either the :data or :file keyword. */
5419 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5420 }
5421
5422 #endif /* HAVE_PNG || HAVE_NS */
5423
5424
5425 #ifdef HAVE_PNG
5426
5427 #ifdef HAVE_NTGUI
5428 /* PNG library details. */
5429
5430 DEF_IMGLIB_FN (png_get_io_ptr);
5431 DEF_IMGLIB_FN (png_sig_cmp);
5432 DEF_IMGLIB_FN (png_create_read_struct);
5433 DEF_IMGLIB_FN (png_create_info_struct);
5434 DEF_IMGLIB_FN (png_destroy_read_struct);
5435 DEF_IMGLIB_FN (png_set_read_fn);
5436 DEF_IMGLIB_FN (png_set_sig_bytes);
5437 DEF_IMGLIB_FN (png_read_info);
5438 DEF_IMGLIB_FN (png_get_IHDR);
5439 DEF_IMGLIB_FN (png_get_valid);
5440 DEF_IMGLIB_FN (png_set_strip_16);
5441 DEF_IMGLIB_FN (png_set_expand);
5442 DEF_IMGLIB_FN (png_set_gray_to_rgb);
5443 DEF_IMGLIB_FN (png_set_background);
5444 DEF_IMGLIB_FN (png_get_bKGD);
5445 DEF_IMGLIB_FN (png_read_update_info);
5446 DEF_IMGLIB_FN (png_get_channels);
5447 DEF_IMGLIB_FN (png_get_rowbytes);
5448 DEF_IMGLIB_FN (png_read_image);
5449 DEF_IMGLIB_FN (png_read_end);
5450 DEF_IMGLIB_FN (png_error);
5451
5452 static int
5453 init_png_functions (Lisp_Object libraries)
5454 {
5455 HMODULE library;
5456
5457 /* Try loading libpng under probable names. */
5458 if (!(library = w32_delayed_load (libraries, Qpng)))
5459 return 0;
5460
5461 LOAD_IMGLIB_FN (library, png_get_io_ptr);
5462 LOAD_IMGLIB_FN (library, png_sig_cmp);
5463 LOAD_IMGLIB_FN (library, png_create_read_struct);
5464 LOAD_IMGLIB_FN (library, png_create_info_struct);
5465 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5466 LOAD_IMGLIB_FN (library, png_set_read_fn);
5467 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5468 LOAD_IMGLIB_FN (library, png_read_info);
5469 LOAD_IMGLIB_FN (library, png_get_IHDR);
5470 LOAD_IMGLIB_FN (library, png_get_valid);
5471 LOAD_IMGLIB_FN (library, png_set_strip_16);
5472 LOAD_IMGLIB_FN (library, png_set_expand);
5473 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5474 LOAD_IMGLIB_FN (library, png_set_background);
5475 LOAD_IMGLIB_FN (library, png_get_bKGD);
5476 LOAD_IMGLIB_FN (library, png_read_update_info);
5477 LOAD_IMGLIB_FN (library, png_get_channels);
5478 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5479 LOAD_IMGLIB_FN (library, png_read_image);
5480 LOAD_IMGLIB_FN (library, png_read_end);
5481 LOAD_IMGLIB_FN (library, png_error);
5482 return 1;
5483 }
5484 #else
5485
5486 #define fn_png_get_io_ptr png_get_io_ptr
5487 #define fn_png_sig_cmp png_sig_cmp
5488 #define fn_png_create_read_struct png_create_read_struct
5489 #define fn_png_create_info_struct png_create_info_struct
5490 #define fn_png_destroy_read_struct png_destroy_read_struct
5491 #define fn_png_set_read_fn png_set_read_fn
5492 #define fn_png_set_sig_bytes png_set_sig_bytes
5493 #define fn_png_read_info png_read_info
5494 #define fn_png_get_IHDR png_get_IHDR
5495 #define fn_png_get_valid png_get_valid
5496 #define fn_png_set_strip_16 png_set_strip_16
5497 #define fn_png_set_expand png_set_expand
5498 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5499 #define fn_png_set_background png_set_background
5500 #define fn_png_get_bKGD png_get_bKGD
5501 #define fn_png_read_update_info png_read_update_info
5502 #define fn_png_get_channels png_get_channels
5503 #define fn_png_get_rowbytes png_get_rowbytes
5504 #define fn_png_read_image png_read_image
5505 #define fn_png_read_end png_read_end
5506 #define fn_png_error png_error
5507
5508 #endif /* HAVE_NTGUI */
5509
5510 /* Error and warning handlers installed when the PNG library
5511 is initialized. */
5512
5513 static void
5514 my_png_error (png_struct *png_ptr, const char *msg)
5515 {
5516 xassert (png_ptr != NULL);
5517 image_error ("PNG error: %s", build_string (msg), Qnil);
5518 longjmp (png_ptr->jmpbuf, 1);
5519 }
5520
5521
5522 static void
5523 my_png_warning (png_struct *png_ptr, const char *msg)
5524 {
5525 xassert (png_ptr != NULL);
5526 image_error ("PNG warning: %s", build_string (msg), Qnil);
5527 }
5528
5529 /* Memory source for PNG decoding. */
5530
5531 struct png_memory_storage
5532 {
5533 unsigned char *bytes; /* The data */
5534 size_t len; /* How big is it? */
5535 int index; /* Where are we? */
5536 };
5537
5538
5539 /* Function set as reader function when reading PNG image from memory.
5540 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5541 bytes from the input to DATA. */
5542
5543 static void
5544 png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
5545 {
5546 struct png_memory_storage *tbr
5547 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
5548
5549 if (length > tbr->len - tbr->index)
5550 fn_png_error (png_ptr, "Read error");
5551
5552 memcpy (data, tbr->bytes + tbr->index, length);
5553 tbr->index = tbr->index + length;
5554 }
5555
5556
5557 /* Function set as reader function when reading PNG image from a file.
5558 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5559 bytes from the input to DATA. */
5560
5561 static void
5562 png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
5563 {
5564 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
5565
5566 if (fread (data, 1, length, fp) < length)
5567 fn_png_error (png_ptr, "Read error");
5568 }
5569
5570
5571 /* Load PNG image IMG for use on frame F. Value is non-zero if
5572 successful. */
5573
5574 static int
5575 png_load (struct frame *f, struct image *img)
5576 {
5577 Lisp_Object file, specified_file;
5578 Lisp_Object specified_data;
5579 int x, y, i;
5580 XImagePtr ximg, mask_img = NULL;
5581 struct gcpro gcpro1;
5582 png_struct *png_ptr = NULL;
5583 png_info *info_ptr = NULL, *end_info = NULL;
5584 FILE *volatile fp = NULL;
5585 png_byte sig[8];
5586 png_byte * volatile pixels = NULL;
5587 png_byte ** volatile rows = NULL;
5588 png_uint_32 width, height;
5589 int bit_depth, color_type, interlace_type;
5590 png_byte channels;
5591 png_uint_32 row_bytes;
5592 int transparent_p;
5593 struct png_memory_storage tbr; /* Data to be read */
5594
5595 /* Find out what file to load. */
5596 specified_file = image_spec_value (img->spec, QCfile, NULL);
5597 specified_data = image_spec_value (img->spec, QCdata, NULL);
5598 file = Qnil;
5599 GCPRO1 (file);
5600
5601 if (NILP (specified_data))
5602 {
5603 file = x_find_image_file (specified_file);
5604 if (!STRINGP (file))
5605 {
5606 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5607 UNGCPRO;
5608 return 0;
5609 }
5610
5611 /* Open the image file. */
5612 fp = fopen (SDATA (file), "rb");
5613 if (!fp)
5614 {
5615 image_error ("Cannot open image file `%s'", file, Qnil);
5616 UNGCPRO;
5617 return 0;
5618 }
5619
5620 /* Check PNG signature. */
5621 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
5622 || fn_png_sig_cmp (sig, 0, sizeof sig))
5623 {
5624 image_error ("Not a PNG file: `%s'", file, Qnil);
5625 UNGCPRO;
5626 fclose (fp);
5627 return 0;
5628 }
5629 }
5630 else
5631 {
5632 /* Read from memory. */
5633 tbr.bytes = SDATA (specified_data);
5634 tbr.len = SBYTES (specified_data);
5635 tbr.index = 0;
5636
5637 /* Check PNG signature. */
5638 if (tbr.len < sizeof sig
5639 || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
5640 {
5641 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
5642 UNGCPRO;
5643 return 0;
5644 }
5645
5646 /* Need to skip past the signature. */
5647 tbr.bytes += sizeof (sig);
5648 }
5649
5650 /* Initialize read and info structs for PNG lib. Casting return
5651 value avoids a GCC warning on W32. */
5652 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
5653 NULL, my_png_error,
5654 my_png_warning);
5655 if (!png_ptr)
5656 {
5657 if (fp) fclose (fp);
5658 UNGCPRO;
5659 return 0;
5660 }
5661
5662 /* Casting return value avoids a GCC warning on W32. */
5663 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
5664 if (!info_ptr)
5665 {
5666 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
5667 if (fp) fclose (fp);
5668 UNGCPRO;
5669 return 0;
5670 }
5671
5672 /* Casting return value avoids a GCC warning on W32. */
5673 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
5674 if (!end_info)
5675 {
5676 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
5677 if (fp) fclose (fp);
5678 UNGCPRO;
5679 return 0;
5680 }
5681
5682 /* Set error jump-back. We come back here when the PNG library
5683 detects an error. */
5684 if (setjmp (png_ptr->jmpbuf))
5685 {
5686 error:
5687 if (png_ptr)
5688 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
5689 xfree (pixels);
5690 xfree (rows);
5691 if (fp) fclose (fp);
5692 UNGCPRO;
5693 return 0;
5694 }
5695
5696 /* Read image info. */
5697 if (!NILP (specified_data))
5698 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
5699 else
5700 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
5701
5702 fn_png_set_sig_bytes (png_ptr, sizeof sig);
5703 fn_png_read_info (png_ptr, info_ptr);
5704 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
5705 &interlace_type, NULL, NULL);
5706
5707 if (!check_image_size (f, width, height))
5708 {
5709 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
5710 goto error;
5711 }
5712 /* If image contains simply transparency data, we prefer to
5713 construct a clipping mask. */
5714 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
5715 transparent_p = 1;
5716 else
5717 transparent_p = 0;
5718
5719 /* This function is easier to write if we only have to handle
5720 one data format: RGB or RGBA with 8 bits per channel. Let's
5721 transform other formats into that format. */
5722
5723 /* Strip more than 8 bits per channel. */
5724 if (bit_depth == 16)
5725 fn_png_set_strip_16 (png_ptr);
5726
5727 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5728 if available. */
5729 fn_png_set_expand (png_ptr);
5730
5731 /* Convert grayscale images to RGB. */
5732 if (color_type == PNG_COLOR_TYPE_GRAY
5733 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
5734 fn_png_set_gray_to_rgb (png_ptr);
5735
5736 /* Handle alpha channel by combining the image with a background
5737 color. Do this only if a real alpha channel is supplied. For
5738 simple transparency, we prefer a clipping mask. */
5739 if (!transparent_p)
5740 {
5741 /* png_color_16 *image_bg; */
5742 Lisp_Object specified_bg
5743 = image_spec_value (img->spec, QCbackground, NULL);
5744 int shift = (bit_depth == 16) ? 0 : 8;
5745
5746 if (STRINGP (specified_bg))
5747 /* The user specified `:background', use that. */
5748 {
5749 XColor color;
5750 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
5751 {
5752 png_color_16 user_bg;
5753
5754 memset (&user_bg, 0, sizeof user_bg);
5755 user_bg.red = color.red >> shift;
5756 user_bg.green = color.green >> shift;
5757 user_bg.blue = color.blue >> shift;
5758
5759 fn_png_set_background (png_ptr, &user_bg,
5760 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5761 }
5762 }
5763 else
5764 {
5765 /* We use the current frame background, ignoring any default
5766 background color set by the image. */
5767 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
5768 XColor color;
5769 png_color_16 frame_background;
5770
5771 color.pixel = FRAME_BACKGROUND_PIXEL (f);
5772 x_query_color (f, &color);
5773
5774 memset (&frame_background, 0, sizeof frame_background);
5775 frame_background.red = color.red >> shift;
5776 frame_background.green = color.green >> shift;
5777 frame_background.blue = color.blue >> shift;
5778 #endif /* HAVE_X_WINDOWS */
5779
5780 fn_png_set_background (png_ptr, &frame_background,
5781 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5782 }
5783 }
5784
5785 /* Update info structure. */
5786 fn_png_read_update_info (png_ptr, info_ptr);
5787
5788 /* Get number of channels. Valid values are 1 for grayscale images
5789 and images with a palette, 2 for grayscale images with transparency
5790 information (alpha channel), 3 for RGB images, and 4 for RGB
5791 images with alpha channel, i.e. RGBA. If conversions above were
5792 sufficient we should only have 3 or 4 channels here. */
5793 channels = fn_png_get_channels (png_ptr, info_ptr);
5794 xassert (channels == 3 || channels == 4);
5795
5796 /* Number of bytes needed for one row of the image. */
5797 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
5798
5799 /* Allocate memory for the image. */
5800 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
5801 rows = (png_byte **) xmalloc (height * sizeof *rows);
5802 for (i = 0; i < height; ++i)
5803 rows[i] = pixels + i * row_bytes;
5804
5805 /* Read the entire image. */
5806 fn_png_read_image (png_ptr, rows);
5807 fn_png_read_end (png_ptr, info_ptr);
5808 if (fp)
5809 {
5810 fclose (fp);
5811 fp = NULL;
5812 }
5813
5814 /* Create the X image and pixmap. */
5815 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
5816 &img->pixmap))
5817 goto error;
5818
5819 /* Create an image and pixmap serving as mask if the PNG image
5820 contains an alpha channel. */
5821 if (channels == 4
5822 && !transparent_p
5823 && !x_create_x_image_and_pixmap (f, width, height, 1,
5824 &mask_img, &img->mask))
5825 {
5826 x_destroy_x_image (ximg);
5827 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
5828 img->pixmap = NO_PIXMAP;
5829 goto error;
5830 }
5831
5832 /* Fill the X image and mask from PNG data. */
5833 init_color_table ();
5834
5835 for (y = 0; y < height; ++y)
5836 {
5837 png_byte *p = rows[y];
5838
5839 for (x = 0; x < width; ++x)
5840 {
5841 unsigned r, g, b;
5842
5843 r = *p++ << 8;
5844 g = *p++ << 8;
5845 b = *p++ << 8;
5846 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5847 /* An alpha channel, aka mask channel, associates variable
5848 transparency with an image. Where other image formats
5849 support binary transparency---fully transparent or fully
5850 opaque---PNG allows up to 254 levels of partial transparency.
5851 The PNG library implements partial transparency by combining
5852 the image with a specified background color.
5853
5854 I'm not sure how to handle this here nicely: because the
5855 background on which the image is displayed may change, for
5856 real alpha channel support, it would be necessary to create
5857 a new image for each possible background.
5858
5859 What I'm doing now is that a mask is created if we have
5860 boolean transparency information. Otherwise I'm using
5861 the frame's background color to combine the image with. */
5862
5863 if (channels == 4)
5864 {
5865 if (mask_img)
5866 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
5867 ++p;
5868 }
5869 }
5870 }
5871
5872 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5873 /* Set IMG's background color from the PNG image, unless the user
5874 overrode it. */
5875 {
5876 png_color_16 *bg;
5877 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
5878 {
5879 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
5880 img->background_valid = 1;
5881 }
5882 }
5883
5884 #ifdef COLOR_TABLE_SUPPORT
5885 /* Remember colors allocated for this image. */
5886 img->colors = colors_in_color_table (&img->ncolors);
5887 free_color_table ();
5888 #endif /* COLOR_TABLE_SUPPORT */
5889
5890 /* Clean up. */
5891 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
5892 xfree (rows);
5893 xfree (pixels);
5894
5895 img->width = width;
5896 img->height = height;
5897
5898 /* Maybe fill in the background field while we have ximg handy.
5899 Casting avoids a GCC warning. */
5900 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5901
5902 /* Put the image into the pixmap, then free the X image and its buffer. */
5903 x_put_x_image (f, ximg, img->pixmap, width, height);
5904 x_destroy_x_image (ximg);
5905
5906 /* Same for the mask. */
5907 if (mask_img)
5908 {
5909 /* Fill in the background_transparent field while we have the
5910 mask handy. Casting avoids a GCC warning. */
5911 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
5912
5913 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5914 x_destroy_x_image (mask_img);
5915 }
5916
5917 UNGCPRO;
5918 return 1;
5919 }
5920
5921 #else /* HAVE_PNG */
5922
5923 #ifdef HAVE_NS
5924 static int
5925 png_load (struct frame *f, struct image *img)
5926 {
5927 return ns_load_image(f, img,
5928 image_spec_value (img->spec, QCfile, NULL),
5929 image_spec_value (img->spec, QCdata, NULL));
5930 }
5931 #endif /* HAVE_NS */
5932
5933
5934 #endif /* !HAVE_PNG */
5935
5936
5937 \f
5938 /***********************************************************************
5939 JPEG
5940 ***********************************************************************/
5941
5942 #if defined (HAVE_JPEG) || defined (HAVE_NS)
5943
5944 static int jpeg_image_p (Lisp_Object object);
5945 static int jpeg_load (struct frame *f, struct image *img);
5946
5947 /* The symbol `jpeg' identifying images of this type. */
5948
5949 Lisp_Object Qjpeg;
5950
5951 /* Indices of image specification fields in gs_format, below. */
5952
5953 enum jpeg_keyword_index
5954 {
5955 JPEG_TYPE,
5956 JPEG_DATA,
5957 JPEG_FILE,
5958 JPEG_ASCENT,
5959 JPEG_MARGIN,
5960 JPEG_RELIEF,
5961 JPEG_ALGORITHM,
5962 JPEG_HEURISTIC_MASK,
5963 JPEG_MASK,
5964 JPEG_BACKGROUND,
5965 JPEG_LAST
5966 };
5967
5968 /* Vector of image_keyword structures describing the format
5969 of valid user-defined image specifications. */
5970
5971 static const struct image_keyword jpeg_format[JPEG_LAST] =
5972 {
5973 {":type", IMAGE_SYMBOL_VALUE, 1},
5974 {":data", IMAGE_STRING_VALUE, 0},
5975 {":file", IMAGE_STRING_VALUE, 0},
5976 {":ascent", IMAGE_ASCENT_VALUE, 0},
5977 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5978 {":relief", IMAGE_INTEGER_VALUE, 0},
5979 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5980 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5981 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5982 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5983 };
5984
5985 /* Structure describing the image type `jpeg'. */
5986
5987 static struct image_type jpeg_type =
5988 {
5989 &Qjpeg,
5990 jpeg_image_p,
5991 jpeg_load,
5992 x_clear_image,
5993 NULL
5994 };
5995
5996 /* Return non-zero if OBJECT is a valid JPEG image specification. */
5997
5998 static int
5999 jpeg_image_p (Lisp_Object object)
6000 {
6001 struct image_keyword fmt[JPEG_LAST];
6002
6003 memcpy (fmt, jpeg_format, sizeof fmt);
6004
6005 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6006 return 0;
6007
6008 /* Must specify either the :data or :file keyword. */
6009 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6010 }
6011
6012 #endif /* HAVE_JPEG || HAVE_NS */
6013
6014 #ifdef HAVE_JPEG
6015
6016 /* Work around a warning about HAVE_STDLIB_H being redefined in
6017 jconfig.h. */
6018 #ifdef HAVE_STDLIB_H
6019 #define HAVE_STDLIB_H_1
6020 #undef HAVE_STDLIB_H
6021 #endif /* HAVE_STLIB_H */
6022
6023 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6024 /* In older releases of the jpeg library, jpeglib.h will define boolean
6025 differently depending on __WIN32__, so make sure it is defined. */
6026 #define __WIN32__ 1
6027 #endif
6028
6029 #include <jpeglib.h>
6030 #include <jerror.h>
6031
6032 #ifdef HAVE_STLIB_H_1
6033 #define HAVE_STDLIB_H 1
6034 #endif
6035
6036 #ifdef HAVE_NTGUI
6037
6038 /* JPEG library details. */
6039 DEF_IMGLIB_FN (jpeg_CreateDecompress);
6040 DEF_IMGLIB_FN (jpeg_start_decompress);
6041 DEF_IMGLIB_FN (jpeg_finish_decompress);
6042 DEF_IMGLIB_FN (jpeg_destroy_decompress);
6043 DEF_IMGLIB_FN (jpeg_read_header);
6044 DEF_IMGLIB_FN (jpeg_read_scanlines);
6045 DEF_IMGLIB_FN (jpeg_std_error);
6046 DEF_IMGLIB_FN (jpeg_resync_to_restart);
6047
6048 static int
6049 init_jpeg_functions (Lisp_Object libraries)
6050 {
6051 HMODULE library;
6052
6053 if (!(library = w32_delayed_load (libraries, Qjpeg)))
6054 return 0;
6055
6056 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
6057 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
6058 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
6059 LOAD_IMGLIB_FN (library, jpeg_read_header);
6060 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
6061 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
6062 LOAD_IMGLIB_FN (library, jpeg_std_error);
6063 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
6064 return 1;
6065 }
6066
6067 /* Wrapper since we can't directly assign the function pointer
6068 to another function pointer that was declared more completely easily. */
6069 static boolean
6070 jpeg_resync_to_restart_wrapper (cinfo, desired)
6071 j_decompress_ptr cinfo;
6072 int desired;
6073 {
6074 return fn_jpeg_resync_to_restart (cinfo, desired);
6075 }
6076
6077 #else
6078
6079 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6080 #define fn_jpeg_start_decompress jpeg_start_decompress
6081 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6082 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6083 #define fn_jpeg_read_header jpeg_read_header
6084 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6085 #define fn_jpeg_std_error jpeg_std_error
6086 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6087
6088 #endif /* HAVE_NTGUI */
6089
6090 struct my_jpeg_error_mgr
6091 {
6092 struct jpeg_error_mgr pub;
6093 jmp_buf setjmp_buffer;
6094 };
6095
6096
6097 static void
6098 my_error_exit (j_common_ptr cinfo)
6099 {
6100 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6101 longjmp (mgr->setjmp_buffer, 1);
6102 }
6103
6104
6105 /* Init source method for JPEG data source manager. Called by
6106 jpeg_read_header() before any data is actually read. See
6107 libjpeg.doc from the JPEG lib distribution. */
6108
6109 static void
6110 our_common_init_source (j_decompress_ptr cinfo)
6111 {
6112 }
6113
6114
6115 /* Method to terminate data source. Called by
6116 jpeg_finish_decompress() after all data has been processed. */
6117
6118 static void
6119 our_common_term_source (j_decompress_ptr cinfo)
6120 {
6121 }
6122
6123
6124 /* Fill input buffer method for JPEG data source manager. Called
6125 whenever more data is needed. We read the whole image in one step,
6126 so this only adds a fake end of input marker at the end. */
6127
6128 static JOCTET our_memory_buffer[2];
6129
6130 static boolean
6131 our_memory_fill_input_buffer (j_decompress_ptr cinfo)
6132 {
6133 /* Insert a fake EOI marker. */
6134 struct jpeg_source_mgr *src = cinfo->src;
6135
6136 our_memory_buffer[0] = (JOCTET) 0xFF;
6137 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
6138
6139 src->next_input_byte = our_memory_buffer;
6140 src->bytes_in_buffer = 2;
6141 return 1;
6142 }
6143
6144
6145 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6146 is the JPEG data source manager. */
6147
6148 static void
6149 our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
6150 {
6151 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6152
6153 if (src)
6154 {
6155 if (num_bytes > src->bytes_in_buffer)
6156 ERREXIT (cinfo, JERR_INPUT_EOF);
6157
6158 src->bytes_in_buffer -= num_bytes;
6159 src->next_input_byte += num_bytes;
6160 }
6161 }
6162
6163
6164 /* Set up the JPEG lib for reading an image from DATA which contains
6165 LEN bytes. CINFO is the decompression info structure created for
6166 reading the image. */
6167
6168 static void
6169 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
6170 {
6171 struct jpeg_source_mgr *src;
6172
6173 if (cinfo->src == NULL)
6174 {
6175 /* First time for this JPEG object? */
6176 cinfo->src = (struct jpeg_source_mgr *)
6177 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6178 sizeof (struct jpeg_source_mgr));
6179 src = (struct jpeg_source_mgr *) cinfo->src;
6180 src->next_input_byte = data;
6181 }
6182
6183 src = (struct jpeg_source_mgr *) cinfo->src;
6184 src->init_source = our_common_init_source;
6185 src->fill_input_buffer = our_memory_fill_input_buffer;
6186 src->skip_input_data = our_memory_skip_input_data;
6187 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6188 src->term_source = our_common_term_source;
6189 src->bytes_in_buffer = len;
6190 src->next_input_byte = data;
6191 }
6192
6193
6194 struct jpeg_stdio_mgr
6195 {
6196 struct jpeg_source_mgr mgr;
6197 boolean finished;
6198 FILE *file;
6199 JOCTET *buffer;
6200 };
6201
6202
6203 /* Size of buffer to read JPEG from file.
6204 Not too big, as we want to use alloc_small. */
6205 #define JPEG_STDIO_BUFFER_SIZE 8192
6206
6207
6208 /* Fill input buffer method for JPEG data source manager. Called
6209 whenever more data is needed. The data is read from a FILE *. */
6210
6211 static boolean
6212 our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
6213 {
6214 struct jpeg_stdio_mgr *src;
6215
6216 src = (struct jpeg_stdio_mgr *) cinfo->src;
6217 if (!src->finished)
6218 {
6219 size_t bytes;
6220
6221 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
6222 if (bytes > 0)
6223 src->mgr.bytes_in_buffer = bytes;
6224 else
6225 {
6226 WARNMS (cinfo, JWRN_JPEG_EOF);
6227 src->finished = 1;
6228 src->buffer[0] = (JOCTET) 0xFF;
6229 src->buffer[1] = (JOCTET) JPEG_EOI;
6230 src->mgr.bytes_in_buffer = 2;
6231 }
6232 src->mgr.next_input_byte = src->buffer;
6233 }
6234
6235 return 1;
6236 }
6237
6238
6239 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6240 is the JPEG data source manager. */
6241
6242 static void
6243 our_stdio_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
6244 {
6245 struct jpeg_stdio_mgr *src;
6246 src = (struct jpeg_stdio_mgr *) cinfo->src;
6247
6248 while (num_bytes > 0 && !src->finished)
6249 {
6250 if (num_bytes <= src->mgr.bytes_in_buffer)
6251 {
6252 src->mgr.bytes_in_buffer -= num_bytes;
6253 src->mgr.next_input_byte += num_bytes;
6254 break;
6255 }
6256 else
6257 {
6258 num_bytes -= src->mgr.bytes_in_buffer;
6259 src->mgr.bytes_in_buffer = 0;
6260 src->mgr.next_input_byte = NULL;
6261
6262 our_stdio_fill_input_buffer (cinfo);
6263 }
6264 }
6265 }
6266
6267
6268 /* Set up the JPEG lib for reading an image from a FILE *.
6269 CINFO is the decompression info structure created for
6270 reading the image. */
6271
6272 static void
6273 jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
6274 {
6275 struct jpeg_stdio_mgr *src;
6276
6277 if (cinfo->src != NULL)
6278 src = (struct jpeg_stdio_mgr *) cinfo->src;
6279 else
6280 {
6281 /* First time for this JPEG object? */
6282 cinfo->src = (struct jpeg_source_mgr *)
6283 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6284 sizeof (struct jpeg_stdio_mgr));
6285 src = (struct jpeg_stdio_mgr *) cinfo->src;
6286 src->buffer = (JOCTET *)
6287 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6288 JPEG_STDIO_BUFFER_SIZE);
6289 }
6290
6291 src->file = fp;
6292 src->finished = 0;
6293 src->mgr.init_source = our_common_init_source;
6294 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
6295 src->mgr.skip_input_data = our_stdio_skip_input_data;
6296 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6297 src->mgr.term_source = our_common_term_source;
6298 src->mgr.bytes_in_buffer = 0;
6299 src->mgr.next_input_byte = NULL;
6300 }
6301
6302
6303 /* Load image IMG for use on frame F. Patterned after example.c
6304 from the JPEG lib. */
6305
6306 static int
6307 jpeg_load (struct frame *f, struct image *img)
6308 {
6309 struct jpeg_decompress_struct cinfo;
6310 struct my_jpeg_error_mgr mgr;
6311 Lisp_Object file, specified_file;
6312 Lisp_Object specified_data;
6313 FILE * volatile fp = NULL;
6314 JSAMPARRAY buffer;
6315 int row_stride, x, y;
6316 XImagePtr ximg = NULL;
6317 int rc;
6318 unsigned long *colors;
6319 int width, height;
6320 struct gcpro gcpro1;
6321
6322 /* Open the JPEG file. */
6323 specified_file = image_spec_value (img->spec, QCfile, NULL);
6324 specified_data = image_spec_value (img->spec, QCdata, NULL);
6325 file = Qnil;
6326 GCPRO1 (file);
6327
6328 if (NILP (specified_data))
6329 {
6330 file = x_find_image_file (specified_file);
6331 if (!STRINGP (file))
6332 {
6333 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6334 UNGCPRO;
6335 return 0;
6336 }
6337
6338 fp = fopen (SDATA (file), "rb");
6339 if (fp == NULL)
6340 {
6341 image_error ("Cannot open `%s'", file, Qnil);
6342 UNGCPRO;
6343 return 0;
6344 }
6345 }
6346
6347 /* Customize libjpeg's error handling to call my_error_exit when an
6348 error is detected. This function will perform a longjmp.
6349 Casting return value avoids a GCC warning on W32. */
6350 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
6351 mgr.pub.error_exit = my_error_exit;
6352
6353 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6354 {
6355 if (rc == 1)
6356 {
6357 /* Called from my_error_exit. Display a JPEG error. */
6358 char buffer[JMSG_LENGTH_MAX];
6359 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
6360 image_error ("Error reading JPEG image `%s': %s", img->spec,
6361 build_string (buffer));
6362 }
6363
6364 /* Close the input file and destroy the JPEG object. */
6365 if (fp)
6366 fclose ((FILE *) fp);
6367 fn_jpeg_destroy_decompress (&cinfo);
6368
6369 /* If we already have an XImage, free that. */
6370 x_destroy_x_image (ximg);
6371
6372 /* Free pixmap and colors. */
6373 x_clear_image (f, img);
6374
6375 UNGCPRO;
6376 return 0;
6377 }
6378
6379 /* Create the JPEG decompression object. Let it read from fp.
6380 Read the JPEG image header. */
6381 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
6382
6383 if (NILP (specified_data))
6384 jpeg_file_src (&cinfo, (FILE *) fp);
6385 else
6386 jpeg_memory_src (&cinfo, SDATA (specified_data),
6387 SBYTES (specified_data));
6388
6389 fn_jpeg_read_header (&cinfo, 1);
6390
6391 /* Customize decompression so that color quantization will be used.
6392 Start decompression. */
6393 cinfo.quantize_colors = 1;
6394 fn_jpeg_start_decompress (&cinfo);
6395 width = img->width = cinfo.output_width;
6396 height = img->height = cinfo.output_height;
6397
6398 if (!check_image_size (f, width, height))
6399 {
6400 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
6401 longjmp (mgr.setjmp_buffer, 2);
6402 }
6403
6404 /* Create X image and pixmap. */
6405 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6406 longjmp (mgr.setjmp_buffer, 2);
6407
6408 /* Allocate colors. When color quantization is used,
6409 cinfo.actual_number_of_colors has been set with the number of
6410 colors generated, and cinfo.colormap is a two-dimensional array
6411 of color indices in the range 0..cinfo.actual_number_of_colors.
6412 No more than 255 colors will be generated. */
6413 {
6414 int i, ir, ig, ib;
6415
6416 if (cinfo.out_color_components > 2)
6417 ir = 0, ig = 1, ib = 2;
6418 else if (cinfo.out_color_components > 1)
6419 ir = 0, ig = 1, ib = 0;
6420 else
6421 ir = 0, ig = 0, ib = 0;
6422
6423 /* Use the color table mechanism because it handles colors that
6424 cannot be allocated nicely. Such colors will be replaced with
6425 a default color, and we don't have to care about which colors
6426 can be freed safely, and which can't. */
6427 init_color_table ();
6428 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6429 * sizeof *colors);
6430
6431 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6432 {
6433 /* Multiply RGB values with 255 because X expects RGB values
6434 in the range 0..0xffff. */
6435 int r = cinfo.colormap[ir][i] << 8;
6436 int g = cinfo.colormap[ig][i] << 8;
6437 int b = cinfo.colormap[ib][i] << 8;
6438 colors[i] = lookup_rgb_color (f, r, g, b);
6439 }
6440
6441 #ifdef COLOR_TABLE_SUPPORT
6442 /* Remember those colors actually allocated. */
6443 img->colors = colors_in_color_table (&img->ncolors);
6444 free_color_table ();
6445 #endif /* COLOR_TABLE_SUPPORT */
6446 }
6447
6448 /* Read pixels. */
6449 row_stride = width * cinfo.output_components;
6450 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6451 row_stride, 1);
6452 for (y = 0; y < height; ++y)
6453 {
6454 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
6455 for (x = 0; x < cinfo.output_width; ++x)
6456 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6457 }
6458
6459 /* Clean up. */
6460 fn_jpeg_finish_decompress (&cinfo);
6461 fn_jpeg_destroy_decompress (&cinfo);
6462 if (fp)
6463 fclose ((FILE *) fp);
6464
6465 /* Maybe fill in the background field while we have ximg handy. */
6466 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6467 /* Casting avoids a GCC warning. */
6468 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6469
6470 /* Put the image into the pixmap. */
6471 x_put_x_image (f, ximg, img->pixmap, width, height);
6472 x_destroy_x_image (ximg);
6473 UNGCPRO;
6474 return 1;
6475 }
6476
6477 #else /* HAVE_JPEG */
6478
6479 #ifdef HAVE_NS
6480 static int
6481 jpeg_load (struct frame *f, struct image *img)
6482 {
6483 return ns_load_image (f, img,
6484 image_spec_value (img->spec, QCfile, NULL),
6485 image_spec_value (img->spec, QCdata, NULL));
6486 }
6487 #endif /* HAVE_NS */
6488
6489 #endif /* !HAVE_JPEG */
6490
6491
6492 \f
6493 /***********************************************************************
6494 TIFF
6495 ***********************************************************************/
6496
6497 #if defined (HAVE_TIFF) || defined (HAVE_NS)
6498
6499 static int tiff_image_p (Lisp_Object object);
6500 static int tiff_load (struct frame *f, struct image *img);
6501
6502 /* The symbol `tiff' identifying images of this type. */
6503
6504 Lisp_Object Qtiff;
6505
6506 /* Indices of image specification fields in tiff_format, below. */
6507
6508 enum tiff_keyword_index
6509 {
6510 TIFF_TYPE,
6511 TIFF_DATA,
6512 TIFF_FILE,
6513 TIFF_ASCENT,
6514 TIFF_MARGIN,
6515 TIFF_RELIEF,
6516 TIFF_ALGORITHM,
6517 TIFF_HEURISTIC_MASK,
6518 TIFF_MASK,
6519 TIFF_BACKGROUND,
6520 TIFF_INDEX,
6521 TIFF_LAST
6522 };
6523
6524 /* Vector of image_keyword structures describing the format
6525 of valid user-defined image specifications. */
6526
6527 static const struct image_keyword tiff_format[TIFF_LAST] =
6528 {
6529 {":type", IMAGE_SYMBOL_VALUE, 1},
6530 {":data", IMAGE_STRING_VALUE, 0},
6531 {":file", IMAGE_STRING_VALUE, 0},
6532 {":ascent", IMAGE_ASCENT_VALUE, 0},
6533 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6534 {":relief", IMAGE_INTEGER_VALUE, 0},
6535 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6536 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6537 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6538 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6539 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
6540 };
6541
6542 /* Structure describing the image type `tiff'. */
6543
6544 static struct image_type tiff_type =
6545 {
6546 &Qtiff,
6547 tiff_image_p,
6548 tiff_load,
6549 x_clear_image,
6550 NULL
6551 };
6552
6553 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6554
6555 static int
6556 tiff_image_p (Lisp_Object object)
6557 {
6558 struct image_keyword fmt[TIFF_LAST];
6559 memcpy (fmt, tiff_format, sizeof fmt);
6560
6561 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
6562 return 0;
6563
6564 /* Must specify either the :data or :file keyword. */
6565 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6566 }
6567
6568 #endif /* HAVE_TIFF || HAVE_NS */
6569
6570 #ifdef HAVE_TIFF
6571
6572 #include <tiffio.h>
6573
6574 #ifdef HAVE_NTGUI
6575
6576 /* TIFF library details. */
6577 DEF_IMGLIB_FN (TIFFSetErrorHandler);
6578 DEF_IMGLIB_FN (TIFFSetWarningHandler);
6579 DEF_IMGLIB_FN (TIFFOpen);
6580 DEF_IMGLIB_FN (TIFFClientOpen);
6581 DEF_IMGLIB_FN (TIFFGetField);
6582 DEF_IMGLIB_FN (TIFFReadRGBAImage);
6583 DEF_IMGLIB_FN (TIFFClose);
6584 DEF_IMGLIB_FN (TIFFSetDirectory);
6585
6586 static int
6587 init_tiff_functions (Lisp_Object libraries)
6588 {
6589 HMODULE library;
6590
6591 if (!(library = w32_delayed_load (libraries, Qtiff)))
6592 return 0;
6593
6594 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
6595 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
6596 LOAD_IMGLIB_FN (library, TIFFOpen);
6597 LOAD_IMGLIB_FN (library, TIFFClientOpen);
6598 LOAD_IMGLIB_FN (library, TIFFGetField);
6599 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
6600 LOAD_IMGLIB_FN (library, TIFFClose);
6601 LOAD_IMGLIB_FN (library, TIFFSetDirectory);
6602 return 1;
6603 }
6604
6605 #else
6606
6607 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6608 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6609 #define fn_TIFFOpen TIFFOpen
6610 #define fn_TIFFClientOpen TIFFClientOpen
6611 #define fn_TIFFGetField TIFFGetField
6612 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6613 #define fn_TIFFClose TIFFClose
6614 #define fn_TIFFSetDirectory TIFFSetDirectory
6615 #endif /* HAVE_NTGUI */
6616
6617
6618 /* Reading from a memory buffer for TIFF images Based on the PNG
6619 memory source, but we have to provide a lot of extra functions.
6620 Blah.
6621
6622 We really only need to implement read and seek, but I am not
6623 convinced that the TIFF library is smart enough not to destroy
6624 itself if we only hand it the function pointers we need to
6625 override. */
6626
6627 typedef struct
6628 {
6629 unsigned char *bytes;
6630 size_t len;
6631 int index;
6632 }
6633 tiff_memory_source;
6634
6635 static size_t
6636 tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size)
6637 {
6638 tiff_memory_source *src = (tiff_memory_source *) data;
6639
6640 if (size > src->len - src->index)
6641 return (size_t) -1;
6642 memcpy (buf, src->bytes + src->index, size);
6643 src->index += size;
6644 return size;
6645 }
6646
6647 static size_t
6648 tiff_write_from_memory (thandle_t data, tdata_t buf, tsize_t size)
6649 {
6650 return (size_t) -1;
6651 }
6652
6653 static toff_t
6654 tiff_seek_in_memory (thandle_t data, toff_t off, int whence)
6655 {
6656 tiff_memory_source *src = (tiff_memory_source *) data;
6657 int idx;
6658
6659 switch (whence)
6660 {
6661 case SEEK_SET: /* Go from beginning of source. */
6662 idx = off;
6663 break;
6664
6665 case SEEK_END: /* Go from end of source. */
6666 idx = src->len + off;
6667 break;
6668
6669 case SEEK_CUR: /* Go from current position. */
6670 idx = src->index + off;
6671 break;
6672
6673 default: /* Invalid `whence'. */
6674 return -1;
6675 }
6676
6677 if (idx > src->len || idx < 0)
6678 return -1;
6679
6680 src->index = idx;
6681 return src->index;
6682 }
6683
6684 static int
6685 tiff_close_memory (thandle_t data)
6686 {
6687 /* NOOP */
6688 return 0;
6689 }
6690
6691 static int
6692 tiff_mmap_memory (thandle_t data, tdata_t *pbase, toff_t *psize)
6693 {
6694 /* It is already _IN_ memory. */
6695 return 0;
6696 }
6697
6698 static void
6699 tiff_unmap_memory (thandle_t data, tdata_t base, toff_t size)
6700 {
6701 /* We don't need to do this. */
6702 }
6703
6704 static toff_t
6705 tiff_size_of_memory (thandle_t data)
6706 {
6707 return ((tiff_memory_source *) data)->len;
6708 }
6709
6710
6711 static void
6712 tiff_error_handler (const char *title, const char *format, va_list ap)
6713 {
6714 char buf[512];
6715 int len;
6716
6717 len = sprintf (buf, "TIFF error: %s ", title);
6718 vsprintf (buf + len, format, ap);
6719 add_to_log (buf, Qnil, Qnil);
6720 }
6721
6722
6723 static void
6724 tiff_warning_handler (const char *title, const char *format, va_list ap)
6725 {
6726 char buf[512];
6727 int len;
6728
6729 len = sprintf (buf, "TIFF warning: %s ", title);
6730 vsprintf (buf + len, format, ap);
6731 add_to_log (buf, Qnil, Qnil);
6732 }
6733
6734
6735 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6736 successful. */
6737
6738 static int
6739 tiff_load (struct frame *f, struct image *img)
6740 {
6741 Lisp_Object file, specified_file;
6742 Lisp_Object specified_data;
6743 TIFF *tiff;
6744 int width, height, x, y, count;
6745 uint32 *buf;
6746 int rc, rc2;
6747 XImagePtr ximg;
6748 struct gcpro gcpro1;
6749 tiff_memory_source memsrc;
6750 Lisp_Object image;
6751
6752 specified_file = image_spec_value (img->spec, QCfile, NULL);
6753 specified_data = image_spec_value (img->spec, QCdata, NULL);
6754 file = Qnil;
6755 GCPRO1 (file);
6756
6757 fn_TIFFSetErrorHandler (tiff_error_handler);
6758 fn_TIFFSetWarningHandler (tiff_warning_handler);
6759
6760 if (NILP (specified_data))
6761 {
6762 /* Read from a file */
6763 file = x_find_image_file (specified_file);
6764 if (!STRINGP (file))
6765 {
6766 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6767 UNGCPRO;
6768 return 0;
6769 }
6770
6771 /* Try to open the image file. Casting return value avoids a
6772 GCC warning on W32. */
6773 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
6774 if (tiff == NULL)
6775 {
6776 image_error ("Cannot open `%s'", file, Qnil);
6777 UNGCPRO;
6778 return 0;
6779 }
6780 }
6781 else
6782 {
6783 /* Memory source! */
6784 memsrc.bytes = SDATA (specified_data);
6785 memsrc.len = SBYTES (specified_data);
6786 memsrc.index = 0;
6787
6788 /* Casting return value avoids a GCC warning on W32. */
6789 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
6790 (TIFFReadWriteProc) tiff_read_from_memory,
6791 (TIFFReadWriteProc) tiff_write_from_memory,
6792 tiff_seek_in_memory,
6793 tiff_close_memory,
6794 tiff_size_of_memory,
6795 tiff_mmap_memory,
6796 tiff_unmap_memory);
6797
6798 if (!tiff)
6799 {
6800 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
6801 UNGCPRO;
6802 return 0;
6803 }
6804 }
6805
6806 image = image_spec_value (img->spec, QCindex, NULL);
6807 if (INTEGERP (image))
6808 {
6809 int ino = XFASTINT (image);
6810 if (!fn_TIFFSetDirectory (tiff, ino))
6811 {
6812 image_error ("Invalid image number `%s' in image `%s'",
6813 image, img->spec);
6814 fn_TIFFClose (tiff);
6815 UNGCPRO;
6816 return 0;
6817 }
6818 }
6819
6820 /* Get width and height of the image, and allocate a raster buffer
6821 of width x height 32-bit values. */
6822 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
6823 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
6824
6825 if (!check_image_size (f, width, height))
6826 {
6827 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
6828 fn_TIFFClose (tiff);
6829 UNGCPRO;
6830 return 0;
6831 }
6832
6833 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
6834
6835 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
6836
6837 /* Count the number of images in the file. */
6838 for (count = 1, rc2 = 1; rc2; count++)
6839 rc2 = fn_TIFFSetDirectory (tiff, count);
6840
6841 if (count > 1)
6842 img->data.lisp_val = Fcons (Qcount,
6843 Fcons (make_number (count),
6844 img->data.lisp_val));
6845
6846 fn_TIFFClose (tiff);
6847 if (!rc)
6848 {
6849 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
6850 xfree (buf);
6851 UNGCPRO;
6852 return 0;
6853 }
6854
6855 /* Create the X image and pixmap. */
6856 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6857 {
6858 xfree (buf);
6859 UNGCPRO;
6860 return 0;
6861 }
6862
6863 /* Initialize the color table. */
6864 init_color_table ();
6865
6866 /* Process the pixel raster. Origin is in the lower-left corner. */
6867 for (y = 0; y < height; ++y)
6868 {
6869 uint32 *row = buf + y * width;
6870
6871 for (x = 0; x < width; ++x)
6872 {
6873 uint32 abgr = row[x];
6874 int r = TIFFGetR (abgr) << 8;
6875 int g = TIFFGetG (abgr) << 8;
6876 int b = TIFFGetB (abgr) << 8;
6877 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
6878 }
6879 }
6880
6881 #ifdef COLOR_TABLE_SUPPORT
6882 /* Remember the colors allocated for the image. Free the color table. */
6883 img->colors = colors_in_color_table (&img->ncolors);
6884 free_color_table ();
6885 #endif /* COLOR_TABLE_SUPPORT */
6886
6887 img->width = width;
6888 img->height = height;
6889
6890 /* Maybe fill in the background field while we have ximg handy. */
6891 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6892 /* Casting avoids a GCC warning on W32. */
6893 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6894
6895 /* Put the image into the pixmap, then free the X image and its buffer. */
6896 x_put_x_image (f, ximg, img->pixmap, width, height);
6897 x_destroy_x_image (ximg);
6898 xfree (buf);
6899
6900 UNGCPRO;
6901 return 1;
6902 }
6903
6904 #else /* HAVE_TIFF */
6905
6906 #ifdef HAVE_NS
6907 static int
6908 tiff_load (struct frame *f, struct image *img)
6909 {
6910 return ns_load_image (f, img,
6911 image_spec_value (img->spec, QCfile, NULL),
6912 image_spec_value (img->spec, QCdata, NULL));
6913 }
6914 #endif /* HAVE_NS */
6915
6916 #endif /* !HAVE_TIFF */
6917
6918
6919 \f
6920 /***********************************************************************
6921 GIF
6922 ***********************************************************************/
6923
6924 #if defined (HAVE_GIF) || defined (HAVE_NS)
6925
6926 static int gif_image_p (Lisp_Object object);
6927 static int gif_load (struct frame *f, struct image *img);
6928 static void gif_clear_image (struct frame *f, struct image *img);
6929
6930 /* The symbol `gif' identifying images of this type. */
6931
6932 Lisp_Object Qgif;
6933
6934 /* Indices of image specification fields in gif_format, below. */
6935
6936 enum gif_keyword_index
6937 {
6938 GIF_TYPE,
6939 GIF_DATA,
6940 GIF_FILE,
6941 GIF_ASCENT,
6942 GIF_MARGIN,
6943 GIF_RELIEF,
6944 GIF_ALGORITHM,
6945 GIF_HEURISTIC_MASK,
6946 GIF_MASK,
6947 GIF_IMAGE,
6948 GIF_BACKGROUND,
6949 GIF_LAST
6950 };
6951
6952 /* Vector of image_keyword structures describing the format
6953 of valid user-defined image specifications. */
6954
6955 static const struct image_keyword gif_format[GIF_LAST] =
6956 {
6957 {":type", IMAGE_SYMBOL_VALUE, 1},
6958 {":data", IMAGE_STRING_VALUE, 0},
6959 {":file", IMAGE_STRING_VALUE, 0},
6960 {":ascent", IMAGE_ASCENT_VALUE, 0},
6961 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6962 {":relief", IMAGE_INTEGER_VALUE, 0},
6963 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6964 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6965 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6966 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6967 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6968 };
6969
6970 /* Structure describing the image type `gif'. */
6971
6972 static struct image_type gif_type =
6973 {
6974 &Qgif,
6975 gif_image_p,
6976 gif_load,
6977 gif_clear_image,
6978 NULL
6979 };
6980
6981 /* Free X resources of GIF image IMG which is used on frame F. */
6982
6983 static void
6984 gif_clear_image (struct frame *f, struct image *img)
6985 {
6986 /* IMG->data.ptr_val may contain metadata with extension data. */
6987 img->data.lisp_val = Qnil;
6988 x_clear_image (f, img);
6989 }
6990
6991 /* Return non-zero if OBJECT is a valid GIF image specification. */
6992
6993 static int
6994 gif_image_p (Lisp_Object object)
6995 {
6996 struct image_keyword fmt[GIF_LAST];
6997 memcpy (fmt, gif_format, sizeof fmt);
6998
6999 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7000 return 0;
7001
7002 /* Must specify either the :data or :file keyword. */
7003 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7004 }
7005
7006 #endif /* HAVE_GIF */
7007
7008 #ifdef HAVE_GIF
7009
7010 #if defined (HAVE_NTGUI)
7011 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7012 Undefine before redefining to avoid a preprocessor warning. */
7013 #ifdef DrawText
7014 #undef DrawText
7015 #endif
7016 /* avoid conflict with QuickdrawText.h */
7017 #define DrawText gif_DrawText
7018 #include <gif_lib.h>
7019 #undef DrawText
7020
7021 #else /* HAVE_NTGUI */
7022
7023 #include <gif_lib.h>
7024
7025 #endif /* HAVE_NTGUI */
7026
7027
7028 #ifdef HAVE_NTGUI
7029
7030 /* GIF library details. */
7031 DEF_IMGLIB_FN (DGifCloseFile);
7032 DEF_IMGLIB_FN (DGifSlurp);
7033 DEF_IMGLIB_FN (DGifOpen);
7034 DEF_IMGLIB_FN (DGifOpenFileName);
7035
7036 static int
7037 init_gif_functions (Lisp_Object libraries)
7038 {
7039 HMODULE library;
7040
7041 if (!(library = w32_delayed_load (libraries, Qgif)))
7042 return 0;
7043
7044 LOAD_IMGLIB_FN (library, DGifCloseFile);
7045 LOAD_IMGLIB_FN (library, DGifSlurp);
7046 LOAD_IMGLIB_FN (library, DGifOpen);
7047 LOAD_IMGLIB_FN (library, DGifOpenFileName);
7048 return 1;
7049 }
7050
7051 #else
7052
7053 #define fn_DGifCloseFile DGifCloseFile
7054 #define fn_DGifSlurp DGifSlurp
7055 #define fn_DGifOpen DGifOpen
7056 #define fn_DGifOpenFileName DGifOpenFileName
7057
7058 #endif /* HAVE_NTGUI */
7059
7060 /* Reading a GIF image from memory
7061 Based on the PNG memory stuff to a certain extent. */
7062
7063 typedef struct
7064 {
7065 unsigned char *bytes;
7066 size_t len;
7067 int index;
7068 }
7069 gif_memory_source;
7070
7071 /* Make the current memory source available to gif_read_from_memory.
7072 It's done this way because not all versions of libungif support
7073 a UserData field in the GifFileType structure. */
7074 static gif_memory_source *current_gif_memory_src;
7075
7076 static int
7077 gif_read_from_memory (GifFileType *file, GifByteType *buf, int len)
7078 {
7079 gif_memory_source *src = current_gif_memory_src;
7080
7081 if (len > src->len - src->index)
7082 return -1;
7083
7084 memcpy (buf, src->bytes + src->index, len);
7085 src->index += len;
7086 return len;
7087 }
7088
7089
7090 /* Load GIF image IMG for use on frame F. Value is non-zero if
7091 successful. */
7092
7093 static const int interlace_start[] = {0, 4, 2, 1};
7094 static const int interlace_increment[] = {8, 8, 4, 2};
7095
7096 static int
7097 gif_load (struct frame *f, struct image *img)
7098 {
7099 Lisp_Object file, specified_file;
7100 Lisp_Object specified_data;
7101 int rc, width, height, x, y, i;
7102 XImagePtr ximg;
7103 ColorMapObject *gif_color_map;
7104 unsigned long pixel_colors[256];
7105 GifFileType *gif;
7106 struct gcpro gcpro1;
7107 Lisp_Object image;
7108 int ino, image_height, image_width;
7109 gif_memory_source memsrc;
7110 unsigned char *raster;
7111
7112 specified_file = image_spec_value (img->spec, QCfile, NULL);
7113 specified_data = image_spec_value (img->spec, QCdata, NULL);
7114 file = Qnil;
7115 GCPRO1 (file);
7116
7117 if (NILP (specified_data))
7118 {
7119 file = x_find_image_file (specified_file);
7120 if (!STRINGP (file))
7121 {
7122 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7123 UNGCPRO;
7124 return 0;
7125 }
7126
7127 /* Open the GIF file. Casting return value avoids a GCC warning
7128 on W32. */
7129 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
7130 if (gif == NULL)
7131 {
7132 image_error ("Cannot open `%s'", file, Qnil);
7133 UNGCPRO;
7134 return 0;
7135 }
7136 }
7137 else
7138 {
7139 /* Read from memory! */
7140 current_gif_memory_src = &memsrc;
7141 memsrc.bytes = SDATA (specified_data);
7142 memsrc.len = SBYTES (specified_data);
7143 memsrc.index = 0;
7144
7145 /* Casting return value avoids a GCC warning on W32. */
7146 gif = (GifFileType *) fn_DGifOpen (&memsrc, gif_read_from_memory);
7147 if (!gif)
7148 {
7149 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
7150 UNGCPRO;
7151 return 0;
7152 }
7153 }
7154
7155 /* Before reading entire contents, check the declared image size. */
7156 if (!check_image_size (f, gif->SWidth, gif->SHeight))
7157 {
7158 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7159 fn_DGifCloseFile (gif);
7160 UNGCPRO;
7161 return 0;
7162 }
7163
7164 /* Read entire contents. */
7165 rc = fn_DGifSlurp (gif);
7166 if (rc == GIF_ERROR)
7167 {
7168 image_error ("Error reading `%s'", img->spec, Qnil);
7169 fn_DGifCloseFile (gif);
7170 UNGCPRO;
7171 return 0;
7172 }
7173
7174 image = image_spec_value (img->spec, QCindex, NULL);
7175 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7176 if (ino >= gif->ImageCount)
7177 {
7178 image_error ("Invalid image number `%s' in image `%s'",
7179 image, img->spec);
7180 fn_DGifCloseFile (gif);
7181 UNGCPRO;
7182 return 0;
7183 }
7184
7185 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
7186 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
7187 image_height = gif->SavedImages[ino].ImageDesc.Height;
7188 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
7189 image_width = gif->SavedImages[ino].ImageDesc.Width;
7190 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
7191
7192 width = img->width = max (gif->SWidth,
7193 max (gif->Image.Left + gif->Image.Width,
7194 img->corners[RIGHT_CORNER]));
7195 height = img->height = max (gif->SHeight,
7196 max (gif->Image.Top + gif->Image.Height,
7197 img->corners[BOT_CORNER]));
7198
7199 if (!check_image_size (f, width, height))
7200 {
7201 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7202 fn_DGifCloseFile (gif);
7203 UNGCPRO;
7204 return 0;
7205 }
7206
7207 /* Create the X image and pixmap. */
7208 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7209 {
7210 fn_DGifCloseFile (gif);
7211 UNGCPRO;
7212 return 0;
7213 }
7214
7215 /* Allocate colors. */
7216 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
7217 if (!gif_color_map)
7218 gif_color_map = gif->SColorMap;
7219 init_color_table ();
7220 memset (pixel_colors, 0, sizeof pixel_colors);
7221
7222 if (gif_color_map)
7223 for (i = 0; i < gif_color_map->ColorCount; ++i)
7224 {
7225 int r = gif_color_map->Colors[i].Red << 8;
7226 int g = gif_color_map->Colors[i].Green << 8;
7227 int b = gif_color_map->Colors[i].Blue << 8;
7228 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7229 }
7230
7231 #ifdef COLOR_TABLE_SUPPORT
7232 img->colors = colors_in_color_table (&img->ncolors);
7233 free_color_table ();
7234 #endif /* COLOR_TABLE_SUPPORT */
7235
7236 /* Clear the part of the screen image that are not covered by
7237 the image from the GIF file. Full animated GIF support
7238 requires more than can be done here (see the gif89 spec,
7239 disposal methods). Let's simply assume that the part
7240 not covered by a sub-image is in the frame's background color. */
7241 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
7242 for (x = 0; x < width; ++x)
7243 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7244
7245 for (y = img->corners[BOT_CORNER]; y < height; ++y)
7246 for (x = 0; x < width; ++x)
7247 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7248
7249 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
7250 {
7251 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
7252 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7253 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
7254 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7255 }
7256
7257 /* Read the GIF image into the X image. We use a local variable
7258 `raster' here because RasterBits below is a char *, and invites
7259 problems with bytes >= 0x80. */
7260 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
7261
7262 if (gif->SavedImages[ino].ImageDesc.Interlace)
7263 {
7264 int pass;
7265 int row = interlace_start[0];
7266
7267 pass = 0;
7268
7269 for (y = 0; y < image_height; y++)
7270 {
7271 if (row >= image_height)
7272 {
7273 row = interlace_start[++pass];
7274 while (row >= image_height)
7275 row = interlace_start[++pass];
7276 }
7277
7278 for (x = 0; x < image_width; x++)
7279 {
7280 int i = raster[(y * image_width) + x];
7281 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7282 row + img->corners[TOP_CORNER], pixel_colors[i]);
7283 }
7284
7285 row += interlace_increment[pass];
7286 }
7287 }
7288 else
7289 {
7290 for (y = 0; y < image_height; ++y)
7291 for (x = 0; x < image_width; ++x)
7292 {
7293 int i = raster[y * image_width + x];
7294 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7295 y + img->corners[TOP_CORNER], pixel_colors[i]);
7296 }
7297 }
7298
7299 /* Save GIF image extension data for `image-metadata'.
7300 Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)). */
7301 img->data.lisp_val = Qnil;
7302 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
7303 {
7304 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
7305 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
7306 /* Append (... FUNCTION "BYTES") */
7307 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
7308 Fcons (make_number (ext->Function),
7309 img->data.lisp_val));
7310 img->data.lisp_val = Fcons (Qextension_data,
7311 Fcons (Fnreverse (img->data.lisp_val),
7312 Qnil));
7313 }
7314 if (gif->ImageCount > 1)
7315 img->data.lisp_val = Fcons (Qcount,
7316 Fcons (make_number (gif->ImageCount),
7317 img->data.lisp_val));
7318
7319 fn_DGifCloseFile (gif);
7320
7321 /* Maybe fill in the background field while we have ximg handy. */
7322 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7323 /* Casting avoids a GCC warning. */
7324 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7325
7326 /* Put the image into the pixmap, then free the X image and its buffer. */
7327 x_put_x_image (f, ximg, img->pixmap, width, height);
7328 x_destroy_x_image (ximg);
7329
7330 UNGCPRO;
7331 return 1;
7332 }
7333
7334 #else /* !HAVE_GIF */
7335
7336 #ifdef HAVE_NS
7337 static int
7338 gif_load (struct frame *f, struct image *img)
7339 {
7340 return ns_load_image (f, img,
7341 image_spec_value (img->spec, QCfile, NULL),
7342 image_spec_value (img->spec, QCdata, NULL));
7343 }
7344 #endif /* HAVE_NS */
7345
7346 #endif /* HAVE_GIF */
7347
7348
7349 \f
7350 /***********************************************************************
7351 SVG
7352 ***********************************************************************/
7353
7354 #if defined (HAVE_RSVG)
7355
7356 /* Function prototypes. */
7357
7358 static int svg_image_p (Lisp_Object object);
7359 static int svg_load (struct frame *f, struct image *img);
7360
7361 static int svg_load_image (struct frame *, struct image *,
7362 unsigned char *, unsigned int);
7363
7364 /* The symbol `svg' identifying images of this type. */
7365
7366 Lisp_Object Qsvg;
7367
7368 /* Indices of image specification fields in svg_format, below. */
7369
7370 enum svg_keyword_index
7371 {
7372 SVG_TYPE,
7373 SVG_DATA,
7374 SVG_FILE,
7375 SVG_ASCENT,
7376 SVG_MARGIN,
7377 SVG_RELIEF,
7378 SVG_ALGORITHM,
7379 SVG_HEURISTIC_MASK,
7380 SVG_MASK,
7381 SVG_BACKGROUND,
7382 SVG_LAST
7383 };
7384
7385 /* Vector of image_keyword structures describing the format
7386 of valid user-defined image specifications. */
7387
7388 static const struct image_keyword svg_format[SVG_LAST] =
7389 {
7390 {":type", IMAGE_SYMBOL_VALUE, 1},
7391 {":data", IMAGE_STRING_VALUE, 0},
7392 {":file", IMAGE_STRING_VALUE, 0},
7393 {":ascent", IMAGE_ASCENT_VALUE, 0},
7394 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7395 {":relief", IMAGE_INTEGER_VALUE, 0},
7396 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7397 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7398 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7399 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7400 };
7401
7402 /* Structure describing the image type `svg'. Its the same type of
7403 structure defined for all image formats, handled by emacs image
7404 functions. See struct image_type in dispextern.h. */
7405
7406 static struct image_type svg_type =
7407 {
7408 /* An identifier showing that this is an image structure for the SVG format. */
7409 &Qsvg,
7410 /* Handle to a function that can be used to identify a SVG file. */
7411 svg_image_p,
7412 /* Handle to function used to load a SVG file. */
7413 svg_load,
7414 /* Handle to function to free sresources for SVG. */
7415 x_clear_image,
7416 /* An internal field to link to the next image type in a list of
7417 image types, will be filled in when registering the format. */
7418 NULL
7419 };
7420
7421
7422 /* Return non-zero if OBJECT is a valid SVG image specification. Do
7423 this by calling parse_image_spec and supplying the keywords that
7424 identify the SVG format. */
7425
7426 static int
7427 svg_image_p (Lisp_Object object)
7428 {
7429 struct image_keyword fmt[SVG_LAST];
7430 memcpy (fmt, svg_format, sizeof fmt);
7431
7432 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
7433 return 0;
7434
7435 /* Must specify either the :data or :file keyword. */
7436 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
7437 }
7438
7439 #include <librsvg/rsvg.h>
7440
7441 #ifdef HAVE_NTGUI
7442
7443 /* SVG library functions. */
7444 DEF_IMGLIB_FN (rsvg_handle_new);
7445 DEF_IMGLIB_FN (rsvg_handle_get_dimensions);
7446 DEF_IMGLIB_FN (rsvg_handle_write);
7447 DEF_IMGLIB_FN (rsvg_handle_close);
7448 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf);
7449 DEF_IMGLIB_FN (rsvg_handle_free);
7450
7451 DEF_IMGLIB_FN (gdk_pixbuf_get_width);
7452 DEF_IMGLIB_FN (gdk_pixbuf_get_height);
7453 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels);
7454 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride);
7455 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace);
7456 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels);
7457 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha);
7458 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample);
7459
7460 DEF_IMGLIB_FN (g_type_init);
7461 DEF_IMGLIB_FN (g_object_unref);
7462 DEF_IMGLIB_FN (g_error_free);
7463
7464 Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
7465
7466 static int
7467 init_svg_functions (Lisp_Object libraries)
7468 {
7469 HMODULE library, gdklib, glib, gobject;
7470
7471 if (!(glib = w32_delayed_load (libraries, Qglib))
7472 || !(gobject = w32_delayed_load (libraries, Qgobject))
7473 || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
7474 || !(library = w32_delayed_load (libraries, Qsvg)))
7475 return 0;
7476
7477 LOAD_IMGLIB_FN (library, rsvg_handle_new);
7478 LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions);
7479 LOAD_IMGLIB_FN (library, rsvg_handle_write);
7480 LOAD_IMGLIB_FN (library, rsvg_handle_close);
7481 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
7482 LOAD_IMGLIB_FN (library, rsvg_handle_free);
7483
7484 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
7485 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
7486 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
7487 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
7488 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
7489 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
7490 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
7491 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
7492
7493 LOAD_IMGLIB_FN (gobject, g_type_init);
7494 LOAD_IMGLIB_FN (gobject, g_object_unref);
7495 LOAD_IMGLIB_FN (glib, g_error_free);
7496
7497 return 1;
7498 }
7499
7500 #else
7501 /* The following aliases for library functions allow dynamic loading
7502 to be used on some platforms. */
7503 #define fn_rsvg_handle_new rsvg_handle_new
7504 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
7505 #define fn_rsvg_handle_write rsvg_handle_write
7506 #define fn_rsvg_handle_close rsvg_handle_close
7507 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
7508 #define fn_rsvg_handle_free rsvg_handle_free
7509
7510 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
7511 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
7512 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
7513 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
7514 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
7515 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
7516 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
7517 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
7518
7519 #define fn_g_type_init g_type_init
7520 #define fn_g_object_unref g_object_unref
7521 #define fn_g_error_free g_error_free
7522 #endif /* !HAVE_NTGUI */
7523
7524 /* Load SVG image IMG for use on frame F. Value is non-zero if
7525 successful. this function will go into the svg_type structure, and
7526 the prototype thus needs to be compatible with that structure. */
7527
7528 static int
7529 svg_load (struct frame *f, struct image *img)
7530 {
7531 int success_p = 0;
7532 Lisp_Object file_name;
7533
7534 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7535 file_name = image_spec_value (img->spec, QCfile, NULL);
7536 if (STRINGP (file_name))
7537 {
7538 Lisp_Object file;
7539 unsigned char *contents;
7540 int size;
7541 struct gcpro gcpro1;
7542
7543 file = x_find_image_file (file_name);
7544 GCPRO1 (file);
7545 if (!STRINGP (file))
7546 {
7547 image_error ("Cannot find image file `%s'", file_name, Qnil);
7548 UNGCPRO;
7549 return 0;
7550 }
7551
7552 /* Read the entire file into memory. */
7553 contents = slurp_file (SDATA (file), &size);
7554 if (contents == NULL)
7555 {
7556 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
7557 UNGCPRO;
7558 return 0;
7559 }
7560 /* If the file was slurped into memory properly, parse it. */
7561 success_p = svg_load_image (f, img, contents, size);
7562 xfree (contents);
7563 UNGCPRO;
7564 }
7565 /* Else its not a file, its a lisp object. Load the image from a
7566 lisp object rather than a file. */
7567 else
7568 {
7569 Lisp_Object data;
7570
7571 data = image_spec_value (img->spec, QCdata, NULL);
7572 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
7573 }
7574
7575 return success_p;
7576 }
7577
7578 /* svg_load_image is a helper function for svg_load, which does the
7579 actual loading given contents and size, apart from frame and image
7580 structures, passed from svg_load.
7581
7582 Uses librsvg to do most of the image processing.
7583
7584 Returns non-zero when successful. */
7585 static int
7586 svg_load_image (struct frame *f, /* Pointer to emacs frame structure. */
7587 struct image *img, /* Pointer to emacs image structure. */
7588 unsigned char *contents, /* String containing the SVG XML data to be parsed. */
7589 unsigned int size) /* Size of data in bytes. */
7590 {
7591 RsvgHandle *rsvg_handle;
7592 RsvgDimensionData dimension_data;
7593 GError *error = NULL;
7594 GdkPixbuf *pixbuf;
7595 int width;
7596 int height;
7597 const guint8 *pixels;
7598 int rowstride;
7599 XImagePtr ximg;
7600 Lisp_Object specified_bg;
7601 XColor background;
7602 int x;
7603 int y;
7604
7605 /* g_type_init is a glib function that must be called prior to using
7606 gnome type library functions. */
7607 fn_g_type_init ();
7608 /* Make a handle to a new rsvg object. */
7609 rsvg_handle = (RsvgHandle *) fn_rsvg_handle_new ();
7610
7611 /* Parse the contents argument and fill in the rsvg_handle. */
7612 fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
7613 if (error) goto rsvg_error;
7614
7615 /* The parsing is complete, rsvg_handle is ready to used, close it
7616 for further writes. */
7617 fn_rsvg_handle_close (rsvg_handle, &error);
7618 if (error) goto rsvg_error;
7619
7620 fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
7621 if (! check_image_size (f, dimension_data.width, dimension_data.height))
7622 {
7623 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7624 goto rsvg_error;
7625 }
7626
7627 /* We can now get a valid pixel buffer from the svg file, if all
7628 went ok. */
7629 pixbuf = (GdkPixbuf *) fn_rsvg_handle_get_pixbuf (rsvg_handle);
7630 if (!pixbuf) goto rsvg_error;
7631 fn_g_object_unref (rsvg_handle);
7632
7633 /* Extract some meta data from the svg handle. */
7634 width = fn_gdk_pixbuf_get_width (pixbuf);
7635 height = fn_gdk_pixbuf_get_height (pixbuf);
7636 pixels = (const guint8 *) fn_gdk_pixbuf_get_pixels (pixbuf);
7637 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
7638
7639 /* Validate the svg meta data. */
7640 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
7641 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
7642 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
7643 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
7644
7645 /* Try to create a x pixmap to hold the svg pixmap. */
7646 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7647 {
7648 fn_g_object_unref (pixbuf);
7649 return 0;
7650 }
7651
7652 init_color_table ();
7653
7654 /* Handle alpha channel by combining the image with a background
7655 color. */
7656 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
7657 if (!STRINGP (specified_bg)
7658 || !x_defined_color (f, SDATA (specified_bg), &background, 0))
7659 {
7660 #ifndef HAVE_NS
7661 background.pixel = FRAME_BACKGROUND_PIXEL (f);
7662 x_query_color (f, &background);
7663 #else
7664 ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1);
7665 #endif
7666 }
7667
7668 /* SVG pixmaps specify transparency in the last byte, so right
7669 shift 8 bits to get rid of it, since emacs doesn't support
7670 transparency. */
7671 background.red >>= 8;
7672 background.green >>= 8;
7673 background.blue >>= 8;
7674
7675 /* This loop handles opacity values, since Emacs assumes
7676 non-transparent images. Each pixel must be "flattened" by
7677 calculating the resulting color, given the transparency of the
7678 pixel, and the image background color. */
7679 for (y = 0; y < height; ++y)
7680 {
7681 for (x = 0; x < width; ++x)
7682 {
7683 unsigned red;
7684 unsigned green;
7685 unsigned blue;
7686 unsigned opacity;
7687
7688 red = *pixels++;
7689 green = *pixels++;
7690 blue = *pixels++;
7691 opacity = *pixels++;
7692
7693 red = ((red * opacity)
7694 + (background.red * ((1 << 8) - opacity)));
7695 green = ((green * opacity)
7696 + (background.green * ((1 << 8) - opacity)));
7697 blue = ((blue * opacity)
7698 + (background.blue * ((1 << 8) - opacity)));
7699
7700 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
7701 }
7702
7703 pixels += rowstride - 4 * width;
7704 }
7705
7706 #ifdef COLOR_TABLE_SUPPORT
7707 /* Remember colors allocated for this image. */
7708 img->colors = colors_in_color_table (&img->ncolors);
7709 free_color_table ();
7710 #endif /* COLOR_TABLE_SUPPORT */
7711
7712 fn_g_object_unref (pixbuf);
7713
7714 img->width = width;
7715 img->height = height;
7716
7717 /* Maybe fill in the background field while we have ximg handy.
7718 Casting avoids a GCC warning. */
7719 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7720
7721 /* Put the image into the pixmap, then free the X image and its
7722 buffer. */
7723 x_put_x_image (f, ximg, img->pixmap, width, height);
7724 x_destroy_x_image (ximg);
7725
7726 return 1;
7727
7728 rsvg_error:
7729 fn_g_object_unref (rsvg_handle);
7730 /* FIXME: Use error->message so the user knows what is the actual
7731 problem with the image. */
7732 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
7733 fn_g_error_free (error);
7734 return 0;
7735 }
7736
7737 #endif /* defined (HAVE_RSVG) */
7738
7739
7740
7741 \f
7742 /***********************************************************************
7743 Ghostscript
7744 ***********************************************************************/
7745
7746 #ifdef HAVE_X_WINDOWS
7747 #define HAVE_GHOSTSCRIPT 1
7748 #endif /* HAVE_X_WINDOWS */
7749
7750 /* The symbol `postscript' identifying images of this type. */
7751
7752 Lisp_Object Qpostscript;
7753
7754 #ifdef HAVE_GHOSTSCRIPT
7755
7756 static int gs_image_p (Lisp_Object object);
7757 static int gs_load (struct frame *f, struct image *img);
7758 static void gs_clear_image (struct frame *f, struct image *img);
7759
7760 /* Keyword symbols. */
7761
7762 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
7763
7764 /* Indices of image specification fields in gs_format, below. */
7765
7766 enum gs_keyword_index
7767 {
7768 GS_TYPE,
7769 GS_PT_WIDTH,
7770 GS_PT_HEIGHT,
7771 GS_FILE,
7772 GS_LOADER,
7773 GS_BOUNDING_BOX,
7774 GS_ASCENT,
7775 GS_MARGIN,
7776 GS_RELIEF,
7777 GS_ALGORITHM,
7778 GS_HEURISTIC_MASK,
7779 GS_MASK,
7780 GS_BACKGROUND,
7781 GS_LAST
7782 };
7783
7784 /* Vector of image_keyword structures describing the format
7785 of valid user-defined image specifications. */
7786
7787 static const struct image_keyword gs_format[GS_LAST] =
7788 {
7789 {":type", IMAGE_SYMBOL_VALUE, 1},
7790 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7791 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7792 {":file", IMAGE_STRING_VALUE, 1},
7793 {":loader", IMAGE_FUNCTION_VALUE, 0},
7794 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
7795 {":ascent", IMAGE_ASCENT_VALUE, 0},
7796 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7797 {":relief", IMAGE_INTEGER_VALUE, 0},
7798 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7799 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7800 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7801 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7802 };
7803
7804 /* Structure describing the image type `ghostscript'. */
7805
7806 static struct image_type gs_type =
7807 {
7808 &Qpostscript,
7809 gs_image_p,
7810 gs_load,
7811 gs_clear_image,
7812 NULL
7813 };
7814
7815
7816 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7817
7818 static void
7819 gs_clear_image (struct frame *f, struct image *img)
7820 {
7821 /* IMG->data.ptr_val may contain a recorded colormap. */
7822 xfree (img->data.ptr_val);
7823 x_clear_image (f, img);
7824 }
7825
7826
7827 /* Return non-zero if OBJECT is a valid Ghostscript image
7828 specification. */
7829
7830 static int
7831 gs_image_p (Lisp_Object object)
7832 {
7833 struct image_keyword fmt[GS_LAST];
7834 Lisp_Object tem;
7835 int i;
7836
7837 memcpy (fmt, gs_format, sizeof fmt);
7838
7839 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
7840 return 0;
7841
7842 /* Bounding box must be a list or vector containing 4 integers. */
7843 tem = fmt[GS_BOUNDING_BOX].value;
7844 if (CONSP (tem))
7845 {
7846 for (i = 0; i < 4; ++i, tem = XCDR (tem))
7847 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
7848 return 0;
7849 if (!NILP (tem))
7850 return 0;
7851 }
7852 else if (VECTORP (tem))
7853 {
7854 if (XVECTOR (tem)->size != 4)
7855 return 0;
7856 for (i = 0; i < 4; ++i)
7857 if (!INTEGERP (XVECTOR (tem)->contents[i]))
7858 return 0;
7859 }
7860 else
7861 return 0;
7862
7863 return 1;
7864 }
7865
7866
7867 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7868 if successful. */
7869
7870 static int
7871 gs_load (struct frame *f, struct image *img)
7872 {
7873 char buffer[100];
7874 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
7875 struct gcpro gcpro1, gcpro2;
7876 Lisp_Object frame;
7877 double in_width, in_height;
7878 Lisp_Object pixel_colors = Qnil;
7879
7880 /* Compute pixel size of pixmap needed from the given size in the
7881 image specification. Sizes in the specification are in pt. 1 pt
7882 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7883 info. */
7884 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
7885 in_width = XFASTINT (pt_width) / 72.0;
7886 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
7887 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
7888 in_height = XFASTINT (pt_height) / 72.0;
7889 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
7890
7891 if (!check_image_size (f, img->width, img->height))
7892 {
7893 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7894 return 0;
7895 }
7896
7897 /* Create the pixmap. */
7898 xassert (img->pixmap == NO_PIXMAP);
7899
7900 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7901 BLOCK_INPUT;
7902 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7903 img->width, img->height,
7904 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
7905 UNBLOCK_INPUT;
7906
7907 if (!img->pixmap)
7908 {
7909 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
7910 return 0;
7911 }
7912
7913 /* Call the loader to fill the pixmap. It returns a process object
7914 if successful. We do not record_unwind_protect here because
7915 other places in redisplay like calling window scroll functions
7916 don't either. Let the Lisp loader use `unwind-protect' instead. */
7917 GCPRO2 (window_and_pixmap_id, pixel_colors);
7918
7919 sprintf (buffer, "%lu %lu",
7920 (unsigned long) FRAME_X_WINDOW (f),
7921 (unsigned long) img->pixmap);
7922 window_and_pixmap_id = build_string (buffer);
7923
7924 sprintf (buffer, "%lu %lu",
7925 FRAME_FOREGROUND_PIXEL (f),
7926 FRAME_BACKGROUND_PIXEL (f));
7927 pixel_colors = build_string (buffer);
7928
7929 XSETFRAME (frame, f);
7930 loader = image_spec_value (img->spec, QCloader, NULL);
7931 if (NILP (loader))
7932 loader = intern ("gs-load-image");
7933
7934 img->data.lisp_val = call6 (loader, frame, img->spec,
7935 make_number (img->width),
7936 make_number (img->height),
7937 window_and_pixmap_id,
7938 pixel_colors);
7939 UNGCPRO;
7940 return PROCESSP (img->data.lisp_val);
7941 }
7942
7943
7944 /* Kill the Ghostscript process that was started to fill PIXMAP on
7945 frame F. Called from XTread_socket when receiving an event
7946 telling Emacs that Ghostscript has finished drawing. */
7947
7948 void
7949 x_kill_gs_process (Pixmap pixmap, struct frame *f)
7950 {
7951 struct image_cache *c = FRAME_IMAGE_CACHE (f);
7952 int class, i;
7953 struct image *img;
7954
7955 /* Find the image containing PIXMAP. */
7956 for (i = 0; i < c->used; ++i)
7957 if (c->images[i]->pixmap == pixmap)
7958 break;
7959
7960 /* Should someone in between have cleared the image cache, for
7961 instance, give up. */
7962 if (i == c->used)
7963 return;
7964
7965 /* Kill the GS process. We should have found PIXMAP in the image
7966 cache and its image should contain a process object. */
7967 img = c->images[i];
7968 xassert (PROCESSP (img->data.lisp_val));
7969 Fkill_process (img->data.lisp_val, Qnil);
7970 img->data.lisp_val = Qnil;
7971
7972 #if defined (HAVE_X_WINDOWS)
7973
7974 /* On displays with a mutable colormap, figure out the colors
7975 allocated for the image by looking at the pixels of an XImage for
7976 img->pixmap. */
7977 class = FRAME_X_VISUAL (f)->class;
7978 if (class != StaticColor && class != StaticGray && class != TrueColor)
7979 {
7980 XImagePtr ximg;
7981
7982 BLOCK_INPUT;
7983
7984 /* Try to get an XImage for img->pixmep. */
7985 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7986 0, 0, img->width, img->height, ~0, ZPixmap);
7987 if (ximg)
7988 {
7989 int x, y;
7990
7991 /* Initialize the color table. */
7992 init_color_table ();
7993
7994 /* For each pixel of the image, look its color up in the
7995 color table. After having done so, the color table will
7996 contain an entry for each color used by the image. */
7997 for (y = 0; y < img->height; ++y)
7998 for (x = 0; x < img->width; ++x)
7999 {
8000 unsigned long pixel = XGetPixel (ximg, x, y);
8001 lookup_pixel_color (f, pixel);
8002 }
8003
8004 /* Record colors in the image. Free color table and XImage. */
8005 #ifdef COLOR_TABLE_SUPPORT
8006 img->colors = colors_in_color_table (&img->ncolors);
8007 free_color_table ();
8008 #endif
8009 XDestroyImage (ximg);
8010
8011 #if 0 /* This doesn't seem to be the case. If we free the colors
8012 here, we get a BadAccess later in x_clear_image when
8013 freeing the colors. */
8014 /* We have allocated colors once, but Ghostscript has also
8015 allocated colors on behalf of us. So, to get the
8016 reference counts right, free them once. */
8017 if (img->ncolors)
8018 x_free_colors (f, img->colors, img->ncolors);
8019 #endif
8020 }
8021 else
8022 image_error ("Cannot get X image of `%s'; colors will not be freed",
8023 img->spec, Qnil);
8024
8025 UNBLOCK_INPUT;
8026 }
8027 #endif /* HAVE_X_WINDOWS */
8028
8029 /* Now that we have the pixmap, compute mask and transform the
8030 image if requested. */
8031 BLOCK_INPUT;
8032 postprocess_image (f, img);
8033 UNBLOCK_INPUT;
8034 }
8035
8036 #endif /* HAVE_GHOSTSCRIPT */
8037
8038 \f
8039 /***********************************************************************
8040 Tests
8041 ***********************************************************************/
8042
8043 #if GLYPH_DEBUG
8044
8045 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
8046 doc: /* Value is non-nil if SPEC is a valid image specification. */)
8047 (Lisp_Object spec)
8048 {
8049 return valid_image_p (spec) ? Qt : Qnil;
8050 }
8051
8052
8053 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
8054 (Lisp_Object spec)
8055 {
8056 int id = -1;
8057
8058 if (valid_image_p (spec))
8059 id = lookup_image (SELECTED_FRAME (), spec);
8060
8061 debug_print (spec);
8062 return make_number (id);
8063 }
8064
8065 #endif /* GLYPH_DEBUG != 0 */
8066
8067
8068 /***********************************************************************
8069 Initialization
8070 ***********************************************************************/
8071
8072 #ifdef HAVE_NTGUI
8073 /* Image types that rely on external libraries are loaded dynamically
8074 if the library is available. */
8075 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8076 define_image_type (image_type, init_lib_fn (libraries))
8077 #else
8078 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8079 define_image_type (image_type, 1)
8080 #endif /* HAVE_NTGUI */
8081
8082 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
8083 doc: /* Initialize image library implementing image type TYPE.
8084 Return non-nil if TYPE is a supported image type.
8085
8086 Image types pbm and xbm are prebuilt; other types are loaded here.
8087 Libraries to load are specified in alist LIBRARIES (usually, the value
8088 of `image-library-alist', which see). */)
8089 (Lisp_Object type, Lisp_Object libraries)
8090 {
8091 Lisp_Object tested;
8092
8093 /* Don't try to reload the library. */
8094 tested = Fassq (type, Vimage_type_cache);
8095 if (CONSP (tested))
8096 return XCDR (tested);
8097
8098 #if defined (HAVE_XPM) || defined (HAVE_NS)
8099 if (EQ (type, Qxpm))
8100 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
8101 #endif
8102
8103 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8104 if (EQ (type, Qjpeg))
8105 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
8106 #endif
8107
8108 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8109 if (EQ (type, Qtiff))
8110 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
8111 #endif
8112
8113 #if defined (HAVE_GIF) || defined (HAVE_NS)
8114 if (EQ (type, Qgif))
8115 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
8116 #endif
8117
8118 #if defined (HAVE_PNG) || defined (HAVE_NS)
8119 if (EQ (type, Qpng))
8120 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
8121 #endif
8122
8123 #if defined (HAVE_RSVG)
8124 if (EQ (type, Qsvg))
8125 return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
8126 #endif
8127
8128 #ifdef HAVE_GHOSTSCRIPT
8129 if (EQ (type, Qpostscript))
8130 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
8131 #endif
8132
8133 /* If the type is not recognized, avoid testing it ever again. */
8134 CACHE_IMAGE_TYPE (type, Qnil);
8135 return Qnil;
8136 }
8137
8138 void
8139 syms_of_image (void)
8140 {
8141 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
8142
8143 /* Initialize this only once, since that's what we do with Vimage_types
8144 and they are supposed to be in sync. Initializing here gives correct
8145 operation on GNU/Linux of calling dump-emacs after loading some images. */
8146 image_types = NULL;
8147
8148 /* Must be defined now becase we're going to update it below, while
8149 defining the supported image types. */
8150 DEFVAR_LISP ("image-types", &Vimage_types,
8151 doc: /* List of potentially supported image types.
8152 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8153 To check whether it is really supported, use `image-type-available-p'. */);
8154 Vimage_types = Qnil;
8155
8156 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
8157 doc: /* Alist of image types vs external libraries needed to display them.
8158
8159 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8160 representing a supported image type, and the rest are strings giving
8161 alternate filenames for the corresponding external libraries.
8162
8163 Emacs tries to load the libraries in the order they appear on the
8164 list; if none is loaded, the running session of Emacs won't
8165 support the image type. Types 'pbm and 'xbm don't need to be
8166 listed; they are always supported. */);
8167 Vimage_library_alist = Qnil;
8168 Fput (intern_c_string ("image-library-alist"), Qrisky_local_variable, Qt);
8169
8170 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
8171 doc: /* Maximum size of images.
8172 Emacs will not load an image into memory if its pixel width or
8173 pixel height exceeds this limit.
8174
8175 If the value is an integer, it directly specifies the maximum
8176 image height and width, measured in pixels. If it is a floating
8177 point number, it specifies the maximum image height and width
8178 as a ratio to the frame height and width. If the value is
8179 non-numeric, there is no explicit limit on the size of images. */);
8180 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8181
8182 Vimage_type_cache = Qnil;
8183 staticpro (&Vimage_type_cache);
8184
8185 Qpbm = intern_c_string ("pbm");
8186 staticpro (&Qpbm);
8187 ADD_IMAGE_TYPE (Qpbm);
8188
8189 Qxbm = intern_c_string ("xbm");
8190 staticpro (&Qxbm);
8191 ADD_IMAGE_TYPE (Qxbm);
8192
8193 define_image_type (&xbm_type, 1);
8194 define_image_type (&pbm_type, 1);
8195
8196 Qcount = intern_c_string ("count");
8197 staticpro (&Qcount);
8198 Qextension_data = intern_c_string ("extension-data");
8199 staticpro (&Qextension_data);
8200
8201 QCascent = intern_c_string (":ascent");
8202 staticpro (&QCascent);
8203 QCmargin = intern_c_string (":margin");
8204 staticpro (&QCmargin);
8205 QCrelief = intern_c_string (":relief");
8206 staticpro (&QCrelief);
8207 QCconversion = intern_c_string (":conversion");
8208 staticpro (&QCconversion);
8209 QCcolor_symbols = intern_c_string (":color-symbols");
8210 staticpro (&QCcolor_symbols);
8211 QCheuristic_mask = intern_c_string (":heuristic-mask");
8212 staticpro (&QCheuristic_mask);
8213 QCindex = intern_c_string (":index");
8214 staticpro (&QCindex);
8215 QCmatrix = intern_c_string (":matrix");
8216 staticpro (&QCmatrix);
8217 QCcolor_adjustment = intern_c_string (":color-adjustment");
8218 staticpro (&QCcolor_adjustment);
8219 QCmask = intern_c_string (":mask");
8220 staticpro (&QCmask);
8221
8222 Qlaplace = intern_c_string ("laplace");
8223 staticpro (&Qlaplace);
8224 Qemboss = intern_c_string ("emboss");
8225 staticpro (&Qemboss);
8226 Qedge_detection = intern_c_string ("edge-detection");
8227 staticpro (&Qedge_detection);
8228 Qheuristic = intern_c_string ("heuristic");
8229 staticpro (&Qheuristic);
8230
8231 Qpostscript = intern_c_string ("postscript");
8232 staticpro (&Qpostscript);
8233 #ifdef HAVE_GHOSTSCRIPT
8234 ADD_IMAGE_TYPE (Qpostscript);
8235 QCloader = intern_c_string (":loader");
8236 staticpro (&QCloader);
8237 QCbounding_box = intern_c_string (":bounding-box");
8238 staticpro (&QCbounding_box);
8239 QCpt_width = intern_c_string (":pt-width");
8240 staticpro (&QCpt_width);
8241 QCpt_height = intern_c_string (":pt-height");
8242 staticpro (&QCpt_height);
8243 #endif /* HAVE_GHOSTSCRIPT */
8244
8245 #if defined (HAVE_XPM) || defined (HAVE_NS)
8246 Qxpm = intern_c_string ("xpm");
8247 staticpro (&Qxpm);
8248 ADD_IMAGE_TYPE (Qxpm);
8249 #endif
8250
8251 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8252 Qjpeg = intern_c_string ("jpeg");
8253 staticpro (&Qjpeg);
8254 ADD_IMAGE_TYPE (Qjpeg);
8255 #endif
8256
8257 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8258 Qtiff = intern_c_string ("tiff");
8259 staticpro (&Qtiff);
8260 ADD_IMAGE_TYPE (Qtiff);
8261 #endif
8262
8263 #if defined (HAVE_GIF) || defined (HAVE_NS)
8264 Qgif = intern_c_string ("gif");
8265 staticpro (&Qgif);
8266 ADD_IMAGE_TYPE (Qgif);
8267 #endif
8268
8269 #if defined (HAVE_PNG) || defined (HAVE_NS)
8270 Qpng = intern_c_string ("png");
8271 staticpro (&Qpng);
8272 ADD_IMAGE_TYPE (Qpng);
8273 #endif
8274
8275 #if defined (HAVE_RSVG)
8276 Qsvg = intern_c_string ("svg");
8277 staticpro (&Qsvg);
8278 ADD_IMAGE_TYPE (Qsvg);
8279 #ifdef HAVE_NTGUI
8280 /* Other libraries used directly by svg code. */
8281 Qgdk_pixbuf = intern_c_string ("gdk-pixbuf");
8282 staticpro (&Qgdk_pixbuf);
8283 Qglib = intern_c_string ("glib");
8284 staticpro (&Qglib);
8285 Qgobject = intern_c_string ("gobject");
8286 staticpro (&Qgobject);
8287 #endif /* HAVE_NTGUI */
8288 #endif /* HAVE_RSVG */
8289
8290 defsubr (&Sinit_image_library);
8291 defsubr (&Sclear_image_cache);
8292 defsubr (&Simage_flush);
8293 defsubr (&Simage_size);
8294 defsubr (&Simage_mask_p);
8295 defsubr (&Simage_metadata);
8296
8297 #if GLYPH_DEBUG
8298 defsubr (&Simagep);
8299 defsubr (&Slookup_image);
8300 #endif
8301
8302 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
8303 doc: /* Non-nil means always draw a cross over disabled images.
8304 Disabled images are those having a `:conversion disabled' property.
8305 A cross is always drawn on black & white displays. */);
8306 cross_disabled_images = 0;
8307
8308 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
8309 doc: /* List of directories to search for window system bitmap files. */);
8310 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
8311
8312 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
8313 doc: /* Maximum time after which images are removed from the cache.
8314 When an image has not been displayed this many seconds, Emacs
8315 automatically removes it from the image cache. If the cache contains
8316 a large number of images, the actual eviction time may be shorter.
8317 The value can also be nil, meaning the cache is never cleared.
8318
8319 The function `clear-image-cache' disregards this variable. */);
8320 Vimage_cache_eviction_delay = make_number (300);
8321 }
8322
8323 void
8324 init_image (void)
8325 {
8326 }
8327
8328 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8329 (do not change this comment) */