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