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