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