aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32fns.c
diff options
context:
space:
mode:
authorKim F. Storm2004-03-11 00:26:21 +0000
committerKim F. Storm2004-03-11 00:26:21 +0000
commit8eaae3d4540ab991aecd989e00cf43507fa35c85 (patch)
tree79b6842f18dd410300a78103b52a3b48c0a3b457 /src/w32fns.c
parent7a060cd4ff1e1513d080c0153fb1b7c6508b9070 (diff)
downloademacs-8eaae3d4540ab991aecd989e00cf43507fa35c85.tar.gz
emacs-8eaae3d4540ab991aecd989e00cf43507fa35c85.zip
Image consolidation:
(Vx_bitmap_file_path, Vimage_cache_eviction_delay) (x_bitmap_height, x_bitmap_width, x_bitmap_pixmap) (x_reference_bitmap, x_create_bitmap_from_data) (x_create_bitmap_from_file, x_destroy_bitmap) (x_destroy_all_bitmaps, x_create_bitmap_mask) (QCascent, QCmargin, QCrelief, QCconversion, QCcolor_symbols) (QCheuristic_mask, QCindex, QCmatrix, QCcolor_adjustment, QCmask) (Qlaplace, Qemboss, Qedge_detection, Qheuristic, Qcenter) (define_image_type, lookup_image_type, valid_image_p) (image_error, enum image_value_type, struct image_keyword) (parse_image_spec, image_spec_value, Fimage_size, Fimage_mask_p) (make_image, free_image, prepare_image_for_display, image_ascent) (four_corners_best, image_background, image_background_transparent) (x_clear_image_1, x_clear_image, x_alloc_image_color) (make_image_cache, free_image_cache, clear_image_cache) (Fclear_image_cache, postprocess_image, lookup_image, cache_image) (forall_images_in_image_cache, x_create_x_image_and_pixmap) (x_destroy_x_image, x_put_x_image, x_find_image_file, slurp_file) (struct ct_color, init_color_table, free_color_table) (lookup_rgb_color, lookup_pixel_color, colors_in_color_table) (cross_disabled_images, x_to_xcolors, x_from_xcolors) (x_detect_edges, x_emboss, x_laplace, x_edge_detection) (x_disable_image, x_build_heuristic_mask) (XBM support, XPM support, PBM support, PNG support, JPEG support) (TIFF support, GIF support, Ghostscript support): Merge with image code from xfns.c and macfns.c into image.c. (syms_of_xfns): Move image related symbols to image.c. (init_external_image_libraries, init_xfns): Remove; initialization moved to init_image in image.c.
Diffstat (limited to 'src/w32fns.c')
-rw-r--r--src/w32fns.c5858
1 files changed, 0 insertions, 5858 deletions
diff --git a/src/w32fns.c b/src/w32fns.c
index 015b406db88..f9a81a19992 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -58,7 +58,6 @@ Boston, MA 02111-1307, USA. */
58 58
59void syms_of_w32fns (); 59void syms_of_w32fns ();
60void globals_of_w32fns (); 60void globals_of_w32fns ();
61static void init_external_image_libraries ();
62 61
63extern void free_frame_menubar (); 62extern void free_frame_menubar ();
64extern double atof (); 63extern double atof ();
@@ -171,10 +170,6 @@ Lisp_Object Vx_cursor_fore_pixel;
171 170
172static int w32_in_use; 171static int w32_in_use;
173 172
174/* Search path for bitmap files. */
175
176Lisp_Object Vx_bitmap_file_path;
177
178/* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */ 173/* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
179 174
180Lisp_Object Vx_pixel_size_width_font_regexp; 175Lisp_Object Vx_pixel_size_width_font_regexp;
@@ -200,7 +195,6 @@ Lisp_Object Vw32_charset_info_alist;
200Lisp_Object Qnone; 195Lisp_Object Qnone;
201Lisp_Object Qsuppress_icon; 196Lisp_Object Qsuppress_icon;
202Lisp_Object Qundefined_color; 197Lisp_Object Qundefined_color;
203Lisp_Object Qcenter;
204Lisp_Object Qcancel_timer; 198Lisp_Object Qcancel_timer;
205Lisp_Object Qhyper; 199Lisp_Object Qhyper;
206Lisp_Object Qsuper; 200Lisp_Object Qsuper;
@@ -396,225 +390,6 @@ x_window_to_frame (dpyinfo, wdesc)
396} 390}
397 391
398 392
399
400/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
401 id, which is just an int that this section returns. Bitmaps are
402 reference counted so they can be shared among frames.
403
404 Bitmap indices are guaranteed to be > 0, so a negative number can
405 be used to indicate no bitmap.
406
407 If you use x_create_bitmap_from_data, then you must keep track of
408 the bitmaps yourself. That is, creating a bitmap from the same
409 data more than once will not be caught. */
410
411
412/* Functions to access the contents of a bitmap, given an id. */
413
414int
415x_bitmap_height (f, id)
416 FRAME_PTR f;
417 int id;
418{
419 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].height;
420}
421
422int
423x_bitmap_width (f, id)
424 FRAME_PTR f;
425 int id;
426{
427 return FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].width;
428}
429
430int
431x_bitmap_pixmap (f, id)
432 FRAME_PTR f;
433 int id;
434{
435 return (int) FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
436}
437
438
439/* Allocate a new bitmap record. Returns index of new record. */
440
441static int
442x_allocate_bitmap_record (f)
443 FRAME_PTR f;
444{
445 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
446 int i;
447
448 if (dpyinfo->bitmaps == NULL)
449 {
450 dpyinfo->bitmaps_size = 10;
451 dpyinfo->bitmaps
452 = (struct w32_bitmap_record *) xmalloc (dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
453 dpyinfo->bitmaps_last = 1;
454 return 1;
455 }
456
457 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
458 return ++dpyinfo->bitmaps_last;
459
460 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
461 if (dpyinfo->bitmaps[i].refcount == 0)
462 return i + 1;
463
464 dpyinfo->bitmaps_size *= 2;
465 dpyinfo->bitmaps
466 = (struct w32_bitmap_record *) xrealloc (dpyinfo->bitmaps,
467 dpyinfo->bitmaps_size * sizeof (struct w32_bitmap_record));
468 return ++dpyinfo->bitmaps_last;
469}
470
471/* Add one reference to the reference count of the bitmap with id ID. */
472
473void
474x_reference_bitmap (f, id)
475 FRAME_PTR f;
476 int id;
477{
478 ++FRAME_W32_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
479}
480
481/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
482
483int
484x_create_bitmap_from_data (f, bits, width, height)
485 struct frame *f;
486 char *bits;
487 unsigned int width, height;
488{
489 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
490 Pixmap bitmap;
491 int id;
492
493 bitmap = CreateBitmap (width, height,
494 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_planes,
495 FRAME_W32_DISPLAY_INFO (XFRAME (frame))->n_cbits,
496 bits);
497
498 if (! bitmap)
499 return -1;
500
501 id = x_allocate_bitmap_record (f);
502 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
503 dpyinfo->bitmaps[id - 1].file = NULL;
504 dpyinfo->bitmaps[id - 1].hinst = NULL;
505 dpyinfo->bitmaps[id - 1].refcount = 1;
506 dpyinfo->bitmaps[id - 1].depth = 1;
507 dpyinfo->bitmaps[id - 1].height = height;
508 dpyinfo->bitmaps[id - 1].width = width;
509
510 return id;
511}
512
513/* Create bitmap from file FILE for frame F. */
514
515int
516x_create_bitmap_from_file (f, file)
517 struct frame *f;
518 Lisp_Object file;
519{
520 return -1;
521#if 0 /* TODO : bitmap support */
522 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
523 unsigned int width, height;
524 HBITMAP bitmap;
525 int xhot, yhot, result, id;
526 Lisp_Object found;
527 int fd;
528 char *filename;
529 HINSTANCE hinst;
530
531 /* Look for an existing bitmap with the same name. */
532 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
533 {
534 if (dpyinfo->bitmaps[id].refcount
535 && dpyinfo->bitmaps[id].file
536 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
537 {
538 ++dpyinfo->bitmaps[id].refcount;
539 return id + 1;
540 }
541 }
542
543 /* Search bitmap-file-path for the file, if appropriate. */
544 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
545 if (fd < 0)
546 return -1;
547 emacs_close (fd);
548
549 filename = (char *) SDATA (found);
550
551 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
552
553 if (hinst == NULL)
554 return -1;
555
556
557 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
558 filename, &width, &height, &bitmap, &xhot, &yhot);
559 if (result != BitmapSuccess)
560 return -1;
561
562 id = x_allocate_bitmap_record (f);
563 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
564 dpyinfo->bitmaps[id - 1].refcount = 1;
565 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SCHARS (file) + 1);
566 dpyinfo->bitmaps[id - 1].depth = 1;
567 dpyinfo->bitmaps[id - 1].height = height;
568 dpyinfo->bitmaps[id - 1].width = width;
569 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
570
571 return id;
572#endif /* TODO */
573}
574
575/* Remove reference to bitmap with id number ID. */
576
577void
578x_destroy_bitmap (f, id)
579 FRAME_PTR f;
580 int id;
581{
582 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
583
584 if (id > 0)
585 {
586 --dpyinfo->bitmaps[id - 1].refcount;
587 if (dpyinfo->bitmaps[id - 1].refcount == 0)
588 {
589 BLOCK_INPUT;
590 DeleteObject (dpyinfo->bitmaps[id - 1].pixmap);
591 if (dpyinfo->bitmaps[id - 1].file)
592 {
593 xfree (dpyinfo->bitmaps[id - 1].file);
594 dpyinfo->bitmaps[id - 1].file = NULL;
595 }
596 UNBLOCK_INPUT;
597 }
598 }
599}
600
601/* Free all the bitmaps for the display specified by DPYINFO. */
602
603static void
604x_destroy_all_bitmaps (dpyinfo)
605 struct w32_display_info *dpyinfo;
606{
607 int i;
608 for (i = 0; i < dpyinfo->bitmaps_last; i++)
609 if (dpyinfo->bitmaps[i].refcount > 0)
610 {
611 DeleteObject (dpyinfo->bitmaps[i].pixmap);
612 if (dpyinfo->bitmaps[i].file)
613 xfree (dpyinfo->bitmaps[i].file);
614 }
615 dpyinfo->bitmaps_last = 0;
616}
617
618BOOL my_show_window P_ ((struct frame *, HWND, int)); 393BOOL my_show_window P_ ((struct frame *, HWND, int));
619void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT)); 394void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
620static Lisp_Object unwind_create_frame P_ ((Lisp_Object)); 395static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
@@ -6929,5475 +6704,6 @@ DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
6929 return Qnil; 6704 return Qnil;
6930} 6705}
6931 6706
6932
6933/***********************************************************************
6934 Image types
6935 ***********************************************************************/
6936
6937/* Value is the number of elements of vector VECTOR. */
6938
6939#define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
6940
6941/* List of supported image types. Use define_image_type to add new
6942 types. Use lookup_image_type to find a type for a given symbol. */
6943
6944static struct image_type *image_types;
6945
6946/* The symbol `xbm' which is used as the type symbol for XBM images. */
6947
6948Lisp_Object Qxbm;
6949
6950/* Keywords. */
6951
6952extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
6953extern Lisp_Object QCdata, QCtype;
6954Lisp_Object QCascent, QCmargin, QCrelief;
6955Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
6956Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
6957
6958/* Other symbols. */
6959
6960Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
6961
6962/* Time in seconds after which images should be removed from the cache
6963 if not displayed. */
6964
6965Lisp_Object Vimage_cache_eviction_delay;
6966
6967/* Function prototypes. */
6968
6969static void define_image_type P_ ((struct image_type *type));
6970static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
6971static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
6972static void x_laplace P_ ((struct frame *, struct image *));
6973static void x_emboss P_ ((struct frame *, struct image *));
6974static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
6975 Lisp_Object));
6976
6977
6978/* Define a new image type from TYPE. This adds a copy of TYPE to
6979 image_types and adds the symbol *TYPE->type to Vimage_types. */
6980
6981static void
6982define_image_type (type)
6983 struct image_type *type;
6984{
6985 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
6986 The initialized data segment is read-only. */
6987 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
6988 bcopy (type, p, sizeof *p);
6989 p->next = image_types;
6990 image_types = p;
6991 Vimage_types = Fcons (*p->type, Vimage_types);
6992}
6993
6994
6995/* Look up image type SYMBOL, and return a pointer to its image_type
6996 structure. Value is null if SYMBOL is not a known image type. */
6997
6998static INLINE struct image_type *
6999lookup_image_type (symbol)
7000 Lisp_Object symbol;
7001{
7002 struct image_type *type;
7003
7004 for (type = image_types; type; type = type->next)
7005 if (EQ (symbol, *type->type))
7006 break;
7007
7008 return type;
7009}
7010
7011
7012/* Value is non-zero if OBJECT is a valid Lisp image specification. A
7013 valid image specification is a list whose car is the symbol
7014 `image', and whose rest is a property list. The property list must
7015 contain a value for key `:type'. That value must be the name of a
7016 supported image type. The rest of the property list depends on the
7017 image type. */
7018
7019int
7020valid_image_p (object)
7021 Lisp_Object object;
7022{
7023 int valid_p = 0;
7024
7025 if (IMAGEP (object))
7026 {
7027 Lisp_Object tem;
7028
7029 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
7030 if (EQ (XCAR (tem), QCtype))
7031 {
7032 tem = XCDR (tem);
7033 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
7034 {
7035 struct image_type *type;
7036 type = lookup_image_type (XCAR (tem));
7037 if (type)
7038 valid_p = type->valid_p (object);
7039 }
7040
7041 break;
7042 }
7043 }
7044
7045 return valid_p;
7046}
7047
7048
7049/* Log error message with format string FORMAT and argument ARG.
7050 Signaling an error, e.g. when an image cannot be loaded, is not a
7051 good idea because this would interrupt redisplay, and the error
7052 message display would lead to another redisplay. This function
7053 therefore simply displays a message. */
7054
7055static void
7056image_error (format, arg1, arg2)
7057 char *format;
7058 Lisp_Object arg1, arg2;
7059{
7060 add_to_log (format, arg1, arg2);
7061}
7062
7063
7064
7065/***********************************************************************
7066 Image specifications
7067 ***********************************************************************/
7068
7069enum image_value_type
7070{
7071 IMAGE_DONT_CHECK_VALUE_TYPE,
7072 IMAGE_STRING_VALUE,
7073 IMAGE_STRING_OR_NIL_VALUE,
7074 IMAGE_SYMBOL_VALUE,
7075 IMAGE_POSITIVE_INTEGER_VALUE,
7076 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
7077 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
7078 IMAGE_ASCENT_VALUE,
7079 IMAGE_INTEGER_VALUE,
7080 IMAGE_FUNCTION_VALUE,
7081 IMAGE_NUMBER_VALUE,
7082 IMAGE_BOOL_VALUE
7083};
7084
7085/* Structure used when parsing image specifications. */
7086
7087struct image_keyword
7088{
7089 /* Name of keyword. */
7090 char *name;
7091
7092 /* The type of value allowed. */
7093 enum image_value_type type;
7094
7095 /* Non-zero means key must be present. */
7096 int mandatory_p;
7097
7098 /* Used to recognize duplicate keywords in a property list. */
7099 int count;
7100
7101 /* The value that was found. */
7102 Lisp_Object value;
7103};
7104
7105
7106static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
7107 int, Lisp_Object));
7108static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
7109
7110
7111/* Parse image spec SPEC according to KEYWORDS. A valid image spec
7112 has the format (image KEYWORD VALUE ...). One of the keyword/
7113 value pairs must be `:type TYPE'. KEYWORDS is a vector of
7114 image_keywords structures of size NKEYWORDS describing other
7115 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
7116
7117static int
7118parse_image_spec (spec, keywords, nkeywords, type)
7119 Lisp_Object spec;
7120 struct image_keyword *keywords;
7121 int nkeywords;
7122 Lisp_Object type;
7123{
7124 int i;
7125 Lisp_Object plist;
7126
7127 if (!IMAGEP (spec))
7128 return 0;
7129
7130 plist = XCDR (spec);
7131 while (CONSP (plist))
7132 {
7133 Lisp_Object key, value;
7134
7135 /* First element of a pair must be a symbol. */
7136 key = XCAR (plist);
7137 plist = XCDR (plist);
7138 if (!SYMBOLP (key))
7139 return 0;
7140
7141 /* There must follow a value. */
7142 if (!CONSP (plist))
7143 return 0;
7144 value = XCAR (plist);
7145 plist = XCDR (plist);
7146
7147 /* Find key in KEYWORDS. Error if not found. */
7148 for (i = 0; i < nkeywords; ++i)
7149 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
7150 break;
7151
7152 if (i == nkeywords)
7153 continue;
7154
7155 /* Record that we recognized the keyword. If a keywords
7156 was found more than once, it's an error. */
7157 keywords[i].value = value;
7158 ++keywords[i].count;
7159
7160 if (keywords[i].count > 1)
7161 return 0;
7162
7163 /* Check type of value against allowed type. */
7164 switch (keywords[i].type)
7165 {
7166 case IMAGE_STRING_VALUE:
7167 if (!STRINGP (value))
7168 return 0;
7169 break;
7170
7171 case IMAGE_STRING_OR_NIL_VALUE:
7172 if (!STRINGP (value) && !NILP (value))
7173 return 0;
7174 break;
7175
7176 case IMAGE_SYMBOL_VALUE:
7177 if (!SYMBOLP (value))
7178 return 0;
7179 break;
7180
7181 case IMAGE_POSITIVE_INTEGER_VALUE:
7182 if (!INTEGERP (value) || XINT (value) <= 0)
7183 return 0;
7184 break;
7185
7186 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
7187 if (INTEGERP (value) && XINT (value) >= 0)
7188 break;
7189 if (CONSP (value)
7190 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
7191 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
7192 break;
7193 return 0;
7194
7195 case IMAGE_ASCENT_VALUE:
7196 if (SYMBOLP (value) && EQ (value, Qcenter))
7197 break;
7198 else if (INTEGERP (value)
7199 && XINT (value) >= 0
7200 && XINT (value) <= 100)
7201 break;
7202 return 0;
7203
7204 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
7205 if (!INTEGERP (value) || XINT (value) < 0)
7206 return 0;
7207 break;
7208
7209 case IMAGE_DONT_CHECK_VALUE_TYPE:
7210 break;
7211
7212 case IMAGE_FUNCTION_VALUE:
7213 value = indirect_function (value);
7214 if (SUBRP (value)
7215 || COMPILEDP (value)
7216 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
7217 break;
7218 return 0;
7219
7220 case IMAGE_NUMBER_VALUE:
7221 if (!INTEGERP (value) && !FLOATP (value))
7222 return 0;
7223 break;
7224
7225 case IMAGE_INTEGER_VALUE:
7226 if (!INTEGERP (value))
7227 return 0;
7228 break;
7229
7230 case IMAGE_BOOL_VALUE:
7231 if (!NILP (value) && !EQ (value, Qt))
7232 return 0;
7233 break;
7234
7235 default:
7236 abort ();
7237 break;
7238 }
7239
7240 if (EQ (key, QCtype) && !EQ (type, value))
7241 return 0;
7242 }
7243
7244 /* Check that all mandatory fields are present. */
7245 for (i = 0; i < nkeywords; ++i)
7246 if (keywords[i].mandatory_p && keywords[i].count == 0)
7247 return 0;
7248
7249 return NILP (plist);
7250}
7251
7252
7253/* Return the value of KEY in image specification SPEC. Value is nil
7254 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
7255 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
7256
7257static Lisp_Object
7258image_spec_value (spec, key, found)
7259 Lisp_Object spec, key;
7260 int *found;
7261{
7262 Lisp_Object tail;
7263
7264 xassert (valid_image_p (spec));
7265
7266 for (tail = XCDR (spec);
7267 CONSP (tail) && CONSP (XCDR (tail));
7268 tail = XCDR (XCDR (tail)))
7269 {
7270 if (EQ (XCAR (tail), key))
7271 {
7272 if (found)
7273 *found = 1;
7274 return XCAR (XCDR (tail));
7275 }
7276 }
7277
7278 if (found)
7279 *found = 0;
7280 return Qnil;
7281}
7282
7283
7284DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
7285 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
7286PIXELS non-nil means return the size in pixels, otherwise return the
7287size in canonical character units.
7288FRAME is the frame on which the image will be displayed. FRAME nil
7289or omitted means use the selected frame. */)
7290 (spec, pixels, frame)
7291 Lisp_Object spec, pixels, frame;
7292{
7293 Lisp_Object size;
7294
7295 size = Qnil;
7296 if (valid_image_p (spec))
7297 {
7298 struct frame *f = check_x_frame (frame);
7299 int id = lookup_image (f, spec);
7300 struct image *img = IMAGE_FROM_ID (f, id);
7301 int width = img->width + 2 * img->hmargin;
7302 int height = img->height + 2 * img->vmargin;
7303
7304 if (NILP (pixels))
7305 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
7306 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
7307 else
7308 size = Fcons (make_number (width), make_number (height));
7309 }
7310 else
7311 error ("Invalid image specification");
7312
7313 return size;
7314}
7315
7316
7317DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
7318 doc: /* Return t if image SPEC has a mask bitmap.
7319FRAME is the frame on which the image will be displayed. FRAME nil
7320or omitted means use the selected frame. */)
7321 (spec, frame)
7322 Lisp_Object spec, frame;
7323{
7324 Lisp_Object mask;
7325
7326 mask = Qnil;
7327 if (valid_image_p (spec))
7328 {
7329 struct frame *f = check_x_frame (frame);
7330 int id = lookup_image (f, spec);
7331 struct image *img = IMAGE_FROM_ID (f, id);
7332 if (img->mask)
7333 mask = Qt;
7334 }
7335 else
7336 error ("Invalid image specification");
7337
7338 return mask;
7339}
7340
7341
7342/***********************************************************************
7343 Image type independent image structures
7344 ***********************************************************************/
7345
7346static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
7347static void free_image P_ ((struct frame *f, struct image *img));
7348static void x_destroy_x_image P_ ((XImage *));
7349
7350
7351/* Allocate and return a new image structure for image specification
7352 SPEC. SPEC has a hash value of HASH. */
7353
7354static struct image *
7355make_image (spec, hash)
7356 Lisp_Object spec;
7357 unsigned hash;
7358{
7359 struct image *img = (struct image *) xmalloc (sizeof *img);
7360
7361 xassert (valid_image_p (spec));
7362 bzero (img, sizeof *img);
7363 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
7364 xassert (img->type != NULL);
7365 img->spec = spec;
7366 img->data.lisp_val = Qnil;
7367 img->ascent = DEFAULT_IMAGE_ASCENT;
7368 img->hash = hash;
7369 return img;
7370}
7371
7372
7373/* Free image IMG which was used on frame F, including its resources. */
7374
7375static void
7376free_image (f, img)
7377 struct frame *f;
7378 struct image *img;
7379{
7380 if (img)
7381 {
7382 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
7383
7384 /* Remove IMG from the hash table of its cache. */
7385 if (img->prev)
7386 img->prev->next = img->next;
7387 else
7388 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
7389
7390 if (img->next)
7391 img->next->prev = img->prev;
7392
7393 c->images[img->id] = NULL;
7394
7395 /* Free resources, then free IMG. */
7396 img->type->free (f, img);
7397 xfree (img);
7398 }
7399}
7400
7401
7402/* Prepare image IMG for display on frame F. Must be called before
7403 drawing an image. */
7404
7405void
7406prepare_image_for_display (f, img)
7407 struct frame *f;
7408 struct image *img;
7409{
7410 EMACS_TIME t;
7411
7412 /* We're about to display IMG, so set its timestamp to `now'. */
7413 EMACS_GET_TIME (t);
7414 img->timestamp = EMACS_SECS (t);
7415
7416 /* If IMG doesn't have a pixmap yet, load it now, using the image
7417 type dependent loader function. */
7418 if (img->pixmap == 0 && !img->load_failed_p)
7419 img->load_failed_p = img->type->load (f, img) == 0;
7420}
7421
7422
7423/* Value is the number of pixels for the ascent of image IMG when
7424 drawn in face FACE. */
7425
7426int
7427image_ascent (img, face)
7428 struct image *img;
7429 struct face *face;
7430{
7431 int height = img->height + img->vmargin;
7432 int ascent;
7433
7434 if (img->ascent == CENTERED_IMAGE_ASCENT)
7435 {
7436 if (face->font)
7437 ascent = height / 2 - (FONT_DESCENT(face->font)
7438 - FONT_BASE(face->font)) / 2;
7439 else
7440 ascent = height / 2;
7441 }
7442 else
7443 ascent = (int) (height * img->ascent / 100.0);
7444
7445 return ascent;
7446}
7447
7448
7449
7450/* Image background colors. */
7451
7452/* Find the "best" corner color of a bitmap. XIMG is assumed to a device
7453 context with the bitmap selected. */
7454static COLORREF
7455four_corners_best (img_dc, width, height)
7456 HDC img_dc;
7457 unsigned long width, height;
7458{
7459 COLORREF corners[4], best;
7460 int i, best_count;
7461
7462 /* Get the colors at the corners of img_dc. */
7463 corners[0] = GetPixel (img_dc, 0, 0);
7464 corners[1] = GetPixel (img_dc, width - 1, 0);
7465 corners[2] = GetPixel (img_dc, width - 1, height - 1);
7466 corners[3] = GetPixel (img_dc, 0, height - 1);
7467
7468 /* Choose the most frequently found color as background. */
7469 for (i = best_count = 0; i < 4; ++i)
7470 {
7471 int j, n;
7472
7473 for (j = n = 0; j < 4; ++j)
7474 if (corners[i] == corners[j])
7475 ++n;
7476
7477 if (n > best_count)
7478 best = corners[i], best_count = n;
7479 }
7480
7481 return best;
7482}
7483
7484/* Return the `background' field of IMG. If IMG doesn't have one yet,
7485 it is guessed heuristically. If non-zero, IMG_DC is an existing
7486 device context with the image selected to use for the heuristic. */
7487
7488unsigned long
7489image_background (img, f, img_dc)
7490 struct image *img;
7491 struct frame *f;
7492 HDC img_dc;
7493{
7494 if (! img->background_valid)
7495 /* IMG doesn't have a background yet, try to guess a reasonable value. */
7496 {
7497 int free_ximg = !img_dc;
7498 HGDIOBJ prev;
7499
7500 if (free_ximg)
7501 {
7502 HDC frame_dc = get_frame_dc (f);
7503 img_dc = CreateCompatibleDC (frame_dc);
7504 release_frame_dc (f, frame_dc);
7505
7506 prev = SelectObject (img_dc, img->pixmap);
7507 }
7508
7509 img->background = four_corners_best (img_dc, img->width, img->height);
7510
7511 if (free_ximg)
7512 {
7513 SelectObject (img_dc, prev);
7514 DeleteDC (img_dc);
7515 }
7516
7517 img->background_valid = 1;
7518 }
7519
7520 return img->background;
7521}
7522
7523/* Return the `background_transparent' field of IMG. If IMG doesn't
7524 have one yet, it is guessed heuristically. If non-zero, MASK is an
7525 existing XImage object to use for the heuristic. */
7526
7527int
7528image_background_transparent (img, f, mask)
7529 struct image *img;
7530 struct frame *f;
7531 HDC mask;
7532{
7533 if (! img->background_transparent_valid)
7534 /* IMG doesn't have a background yet, try to guess a reasonable value. */
7535 {
7536 if (img->mask)
7537 {
7538 int free_mask = !mask;
7539 HGDIOBJ prev;
7540
7541 if (free_mask)
7542 {
7543 HDC frame_dc = get_frame_dc (f);
7544 mask = CreateCompatibleDC (frame_dc);
7545 release_frame_dc (f, frame_dc);
7546
7547 prev = SelectObject (mask, img->mask);
7548 }
7549
7550 img->background_transparent
7551 = !four_corners_best (mask, img->width, img->height);
7552
7553 if (free_mask)
7554 {
7555 SelectObject (mask, prev);
7556 DeleteDC (mask);
7557 }
7558 }
7559 else
7560 img->background_transparent = 0;
7561
7562 img->background_transparent_valid = 1;
7563 }
7564
7565 return img->background_transparent;
7566}
7567
7568
7569/***********************************************************************
7570 Helper functions for X image types
7571 ***********************************************************************/
7572
7573static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
7574 int, int));
7575static void x_clear_image P_ ((struct frame *f, struct image *img));
7576static unsigned long x_alloc_image_color P_ ((struct frame *f,
7577 struct image *img,
7578 Lisp_Object color_name,
7579 unsigned long dflt));
7580
7581
7582/* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
7583 free the pixmap if any. MASK_P non-zero means clear the mask
7584 pixmap if any. COLORS_P non-zero means free colors allocated for
7585 the image, if any. */
7586
7587static void
7588x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
7589 struct frame *f;
7590 struct image *img;
7591 int pixmap_p, mask_p, colors_p;
7592{
7593 if (pixmap_p && img->pixmap)
7594 {
7595 DeleteObject (img->pixmap);
7596 img->pixmap = NULL;
7597 img->background_valid = 0;
7598 }
7599
7600 if (mask_p && img->mask)
7601 {
7602 DeleteObject (img->mask);
7603 img->mask = NULL;
7604 img->background_transparent_valid = 0;
7605 }
7606
7607 if (colors_p && img->ncolors)
7608 {
7609#if 0 /* TODO: color table support. */
7610 x_free_colors (f, img->colors, img->ncolors);
7611#endif
7612 xfree (img->colors);
7613 img->colors = NULL;
7614 img->ncolors = 0;
7615 }
7616}
7617
7618/* Free X resources of image IMG which is used on frame F. */
7619
7620static void
7621x_clear_image (f, img)
7622 struct frame *f;
7623 struct image *img;
7624{
7625 if (img->pixmap)
7626 {
7627 BLOCK_INPUT;
7628 DeleteObject (img->pixmap);
7629 img->pixmap = 0;
7630 UNBLOCK_INPUT;
7631 }
7632
7633 if (img->ncolors)
7634 {
7635#if 0 /* TODO: color table support */
7636
7637 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
7638
7639 /* If display has an immutable color map, freeing colors is not
7640 necessary and some servers don't allow it. So don't do it. */
7641 if (class != StaticColor
7642 && class != StaticGray
7643 && class != TrueColor)
7644 {
7645 Colormap cmap;
7646 BLOCK_INPUT;
7647 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
7648 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
7649 img->ncolors, 0);
7650 UNBLOCK_INPUT;
7651 }
7652#endif
7653
7654 xfree (img->colors);
7655 img->colors = NULL;
7656 img->ncolors = 0;
7657 }
7658}
7659
7660
7661/* Allocate color COLOR_NAME for image IMG on frame F. If color
7662 cannot be allocated, use DFLT. Add a newly allocated color to
7663 IMG->colors, so that it can be freed again. Value is the pixel
7664 color. */
7665
7666static unsigned long
7667x_alloc_image_color (f, img, color_name, dflt)
7668 struct frame *f;
7669 struct image *img;
7670 Lisp_Object color_name;
7671 unsigned long dflt;
7672{
7673 XColor color;
7674 unsigned long result;
7675
7676 xassert (STRINGP (color_name));
7677
7678 if (w32_defined_color (f, SDATA (color_name), &color, 1))
7679 {
7680 /* This isn't called frequently so we get away with simply
7681 reallocating the color vector to the needed size, here. */
7682 ++img->ncolors;
7683 img->colors =
7684 (unsigned long *) xrealloc (img->colors,
7685 img->ncolors * sizeof *img->colors);
7686 img->colors[img->ncolors - 1] = color.pixel;
7687 result = color.pixel;
7688 }
7689 else
7690 result = dflt;
7691 return result;
7692}
7693
7694
7695
7696/***********************************************************************
7697 Image Cache
7698 ***********************************************************************/
7699
7700static void cache_image P_ ((struct frame *f, struct image *img));
7701static void postprocess_image P_ ((struct frame *, struct image *));
7702static void x_disable_image P_ ((struct frame *, struct image *));
7703
7704
7705/* Return a new, initialized image cache that is allocated from the
7706 heap. Call free_image_cache to free an image cache. */
7707
7708struct image_cache *
7709make_image_cache ()
7710{
7711 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
7712 int size;
7713
7714 bzero (c, sizeof *c);
7715 c->size = 50;
7716 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
7717 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
7718 c->buckets = (struct image **) xmalloc (size);
7719 bzero (c->buckets, size);
7720 return c;
7721}
7722
7723
7724/* Free image cache of frame F. Be aware that X frames share images
7725 caches. */
7726
7727void
7728free_image_cache (f)
7729 struct frame *f;
7730{
7731 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
7732 if (c)
7733 {
7734 int i;
7735
7736 /* Cache should not be referenced by any frame when freed. */
7737 xassert (c->refcount == 0);
7738
7739 for (i = 0; i < c->used; ++i)
7740 free_image (f, c->images[i]);
7741 xfree (c->images);
7742 xfree (c);
7743 xfree (c->buckets);
7744 FRAME_X_IMAGE_CACHE (f) = NULL;
7745 }
7746}
7747
7748
7749/* Clear image cache of frame F. FORCE_P non-zero means free all
7750 images. FORCE_P zero means clear only images that haven't been
7751 displayed for some time. Should be called from time to time to
7752 reduce the number of loaded images. If image-eviction-seconds is
7753 non-nil, this frees images in the cache which weren't displayed for
7754 at least that many seconds. */
7755
7756void
7757clear_image_cache (f, force_p)
7758 struct frame *f;
7759 int force_p;
7760{
7761 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
7762
7763 if (c && INTEGERP (Vimage_cache_eviction_delay))
7764 {
7765 EMACS_TIME t;
7766 unsigned long old;
7767 int i, nfreed;
7768
7769 EMACS_GET_TIME (t);
7770 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
7771
7772 /* Block input so that we won't be interrupted by a SIGIO
7773 while being in an inconsistent state. */
7774 BLOCK_INPUT;
7775
7776 for (i = nfreed = 0; i < c->used; ++i)
7777 {
7778 struct image *img = c->images[i];
7779 if (img != NULL
7780 && (force_p || (img->timestamp < old)))
7781 {
7782 free_image (f, img);
7783 ++nfreed;
7784 }
7785 }
7786
7787 /* We may be clearing the image cache because, for example,
7788 Emacs was iconified for a longer period of time. In that
7789 case, current matrices may still contain references to
7790 images freed above. So, clear these matrices. */
7791 if (nfreed)
7792 {
7793 Lisp_Object tail, frame;
7794
7795 FOR_EACH_FRAME (tail, frame)
7796 {
7797 struct frame *f = XFRAME (frame);
7798 if (FRAME_W32_P (f)
7799 && FRAME_X_IMAGE_CACHE (f) == c)
7800 clear_current_matrices (f);
7801 }
7802
7803 ++windows_or_buffers_changed;
7804 }
7805
7806 UNBLOCK_INPUT;
7807 }
7808}
7809
7810
7811DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
7812 0, 1, 0,
7813 doc: /* Clear the image cache of FRAME.
7814FRAME nil or omitted means use the selected frame.
7815FRAME t means clear the image caches of all frames. */)
7816 (frame)
7817 Lisp_Object frame;
7818{
7819 if (EQ (frame, Qt))
7820 {
7821 Lisp_Object tail;
7822
7823 FOR_EACH_FRAME (tail, frame)
7824 if (FRAME_W32_P (XFRAME (frame)))
7825 clear_image_cache (XFRAME (frame), 1);
7826 }
7827 else
7828 clear_image_cache (check_x_frame (frame), 1);
7829
7830 return Qnil;
7831}
7832
7833
7834/* Compute masks and transform image IMG on frame F, as specified
7835 by the image's specification, */
7836
7837static void
7838postprocess_image (f, img)
7839 struct frame *f;
7840 struct image *img;
7841{
7842 /* Manipulation of the image's mask. */
7843 if (img->pixmap)
7844 {
7845 Lisp_Object conversion, spec;
7846 Lisp_Object mask;
7847
7848 spec = img->spec;
7849
7850 /* `:heuristic-mask t'
7851 `:mask heuristic'
7852 means build a mask heuristically.
7853 `:heuristic-mask (R G B)'
7854 `:mask (heuristic (R G B))'
7855 means build a mask from color (R G B) in the
7856 image.
7857 `:mask nil'
7858 means remove a mask, if any. */
7859
7860 mask = image_spec_value (spec, QCheuristic_mask, NULL);
7861 if (!NILP (mask))
7862 x_build_heuristic_mask (f, img, mask);
7863 else
7864 {
7865 int found_p;
7866
7867 mask = image_spec_value (spec, QCmask, &found_p);
7868
7869 if (EQ (mask, Qheuristic))
7870 x_build_heuristic_mask (f, img, Qt);
7871 else if (CONSP (mask)
7872 && EQ (XCAR (mask), Qheuristic))
7873 {
7874 if (CONSP (XCDR (mask)))
7875 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
7876 else
7877 x_build_heuristic_mask (f, img, XCDR (mask));
7878 }
7879 else if (NILP (mask) && found_p && img->mask)
7880 {
7881 DeleteObject (img->mask);
7882 img->mask = NULL;
7883 }
7884 }
7885
7886
7887 /* Should we apply an image transformation algorithm? */
7888 conversion = image_spec_value (spec, QCconversion, NULL);
7889 if (EQ (conversion, Qdisabled))
7890 x_disable_image (f, img);
7891 else if (EQ (conversion, Qlaplace))
7892 x_laplace (f, img);
7893 else if (EQ (conversion, Qemboss))
7894 x_emboss (f, img);
7895 else if (CONSP (conversion)
7896 && EQ (XCAR (conversion), Qedge_detection))
7897 {
7898 Lisp_Object tem;
7899 tem = XCDR (conversion);
7900 if (CONSP (tem))
7901 x_edge_detection (f, img,
7902 Fplist_get (tem, QCmatrix),
7903 Fplist_get (tem, QCcolor_adjustment));
7904 }
7905 }
7906}
7907
7908
7909/* Return the id of image with Lisp specification SPEC on frame F.
7910 SPEC must be a valid Lisp image specification (see valid_image_p). */
7911
7912int
7913lookup_image (f, spec)
7914 struct frame *f;
7915 Lisp_Object spec;
7916{
7917 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
7918 struct image *img;
7919 int i;
7920 unsigned hash;
7921 struct gcpro gcpro1;
7922 EMACS_TIME now;
7923
7924 /* F must be a window-system frame, and SPEC must be a valid image
7925 specification. */
7926 xassert (FRAME_WINDOW_P (f));
7927 xassert (valid_image_p (spec));
7928
7929 GCPRO1 (spec);
7930
7931 /* Look up SPEC in the hash table of the image cache. */
7932 hash = sxhash (spec, 0);
7933 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
7934
7935 for (img = c->buckets[i]; img; img = img->next)
7936 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
7937 break;
7938
7939 /* If not found, create a new image and cache it. */
7940 if (img == NULL)
7941 {
7942 extern Lisp_Object Qpostscript;
7943
7944 BLOCK_INPUT;
7945 img = make_image (spec, hash);
7946 cache_image (f, img);
7947 img->load_failed_p = img->type->load (f, img) == 0;
7948
7949 /* If we can't load the image, and we don't have a width and
7950 height, use some arbitrary width and height so that we can
7951 draw a rectangle for it. */
7952 if (img->load_failed_p)
7953 {
7954 Lisp_Object value;
7955
7956 value = image_spec_value (spec, QCwidth, NULL);
7957 img->width = (INTEGERP (value)
7958 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
7959 value = image_spec_value (spec, QCheight, NULL);
7960 img->height = (INTEGERP (value)
7961 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
7962 }
7963 else
7964 {
7965 /* Handle image type independent image attributes
7966 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
7967 `:background COLOR'. */
7968 Lisp_Object ascent, margin, relief, bg;
7969
7970 ascent = image_spec_value (spec, QCascent, NULL);
7971 if (INTEGERP (ascent))
7972 img->ascent = XFASTINT (ascent);
7973 else if (EQ (ascent, Qcenter))
7974 img->ascent = CENTERED_IMAGE_ASCENT;
7975
7976 margin = image_spec_value (spec, QCmargin, NULL);
7977 if (INTEGERP (margin) && XINT (margin) >= 0)
7978 img->vmargin = img->hmargin = XFASTINT (margin);
7979 else if (CONSP (margin) && INTEGERP (XCAR (margin))
7980 && INTEGERP (XCDR (margin)))
7981 {
7982 if (XINT (XCAR (margin)) > 0)
7983 img->hmargin = XFASTINT (XCAR (margin));
7984 if (XINT (XCDR (margin)) > 0)
7985 img->vmargin = XFASTINT (XCDR (margin));
7986 }
7987
7988 relief = image_spec_value (spec, QCrelief, NULL);
7989 if (INTEGERP (relief))
7990 {
7991 img->relief = XINT (relief);
7992 img->hmargin += abs (img->relief);
7993 img->vmargin += abs (img->relief);
7994 }
7995
7996 if (! img->background_valid)
7997 {
7998 bg = image_spec_value (img->spec, QCbackground, NULL);
7999 if (!NILP (bg))
8000 {
8001 img->background
8002 = x_alloc_image_color (f, img, bg,
8003 FRAME_BACKGROUND_PIXEL (f));
8004 img->background_valid = 1;
8005 }
8006 }
8007
8008 /* Do image transformations and compute masks, unless we
8009 don't have the image yet. */
8010 if (!EQ (*img->type->type, Qpostscript))
8011 postprocess_image (f, img);
8012 }
8013
8014 UNBLOCK_INPUT;
8015 xassert (!interrupt_input_blocked);
8016 }
8017
8018 /* We're using IMG, so set its timestamp to `now'. */
8019 EMACS_GET_TIME (now);
8020 img->timestamp = EMACS_SECS (now);
8021
8022 UNGCPRO;
8023
8024 /* Value is the image id. */
8025 return img->id;
8026}
8027
8028
8029/* Cache image IMG in the image cache of frame F. */
8030
8031static void
8032cache_image (f, img)
8033 struct frame *f;
8034 struct image *img;
8035{
8036 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8037 int i;
8038
8039 /* Find a free slot in c->images. */
8040 for (i = 0; i < c->used; ++i)
8041 if (c->images[i] == NULL)
8042 break;
8043
8044 /* If no free slot found, maybe enlarge c->images. */
8045 if (i == c->used && c->used == c->size)
8046 {
8047 c->size *= 2;
8048 c->images = (struct image **) xrealloc (c->images,
8049 c->size * sizeof *c->images);
8050 }
8051
8052 /* Add IMG to c->images, and assign IMG an id. */
8053 c->images[i] = img;
8054 img->id = i;
8055 if (i == c->used)
8056 ++c->used;
8057
8058 /* Add IMG to the cache's hash table. */
8059 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
8060 img->next = c->buckets[i];
8061 if (img->next)
8062 img->next->prev = img;
8063 img->prev = NULL;
8064 c->buckets[i] = img;
8065}
8066
8067
8068/* Call FN on every image in the image cache of frame F. Used to mark
8069 Lisp Objects in the image cache. */
8070
8071void
8072forall_images_in_image_cache (f, fn)
8073 struct frame *f;
8074 void (*fn) P_ ((struct image *img));
8075{
8076 if (FRAME_LIVE_P (f) && FRAME_W32_P (f))
8077 {
8078 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8079 if (c)
8080 {
8081 int i;
8082 for (i = 0; i < c->used; ++i)
8083 if (c->images[i])
8084 fn (c->images[i]);
8085 }
8086 }
8087}
8088
8089
8090
8091/***********************************************************************
8092 W32 support code
8093 ***********************************************************************/
8094
8095/* Macro for defining functions that will be loaded from image DLLs. */
8096#define DEF_IMGLIB_FN(func) FARPROC fn_##func
8097
8098/* Macro for loading those image functions from the library. */
8099#define LOAD_IMGLIB_FN(lib,func) { \
8100 fn_##func = (void *) GetProcAddress (lib, #func); \
8101 if (!fn_##func) return 0; \
8102 }
8103
8104static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
8105 XImage **, Pixmap *));
8106static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
8107
8108
8109/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
8110 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
8111 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
8112 via xmalloc. DEPTH of zero signifies a 24 bit image, otherwise
8113 DEPTH should indicate the bit depth of the image. Print error
8114 messages via image_error if an error occurs. Value is non-zero if
8115 successful. */
8116
8117static int
8118x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
8119 struct frame *f;
8120 int width, height, depth;
8121 XImage **ximg;
8122 Pixmap *pixmap;
8123{
8124 BITMAPINFOHEADER *header;
8125 HDC hdc;
8126 int scanline_width_bits;
8127 int remainder;
8128 int palette_colors = 0;
8129
8130 if (depth == 0)
8131 depth = 24;
8132
8133 if (depth != 1 && depth != 4 && depth != 8
8134 && depth != 16 && depth != 24 && depth != 32)
8135 {
8136 image_error ("Invalid image bit depth specified", Qnil, Qnil);
8137 return 0;
8138 }
8139
8140 scanline_width_bits = width * depth;
8141 remainder = scanline_width_bits % 32;
8142
8143 if (remainder)
8144 scanline_width_bits += 32 - remainder;
8145
8146 /* Bitmaps with a depth less than 16 need a palette. */
8147 /* BITMAPINFO structure already contains the first RGBQUAD. */
8148 if (depth < 16)
8149 palette_colors = 1 << depth - 1;
8150
8151 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
8152 if (*ximg == NULL)
8153 {
8154 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
8155 return 0;
8156 }
8157
8158 header = &((*ximg)->info.bmiHeader);
8159 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
8160 header->biSize = sizeof (*header);
8161 header->biWidth = width;
8162 header->biHeight = -height; /* negative indicates a top-down bitmap. */
8163 header->biPlanes = 1;
8164 header->biBitCount = depth;
8165 header->biCompression = BI_RGB;
8166 header->biClrUsed = palette_colors;
8167
8168 /* TODO: fill in palette. */
8169 if (depth == 1)
8170 {
8171 (*ximg)->info.bmiColors[0].rgbBlue = 0;
8172 (*ximg)->info.bmiColors[0].rgbGreen = 0;
8173 (*ximg)->info.bmiColors[0].rgbRed = 0;
8174 (*ximg)->info.bmiColors[0].rgbReserved = 0;
8175 (*ximg)->info.bmiColors[1].rgbBlue = 255;
8176 (*ximg)->info.bmiColors[1].rgbGreen = 255;
8177 (*ximg)->info.bmiColors[1].rgbRed = 255;
8178 (*ximg)->info.bmiColors[1].rgbReserved = 0;
8179 }
8180
8181 hdc = get_frame_dc (f);
8182
8183 /* Create a DIBSection and raster array for the bitmap,
8184 and store its handle in *pixmap. */
8185 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
8186 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
8187 &((*ximg)->data), NULL, 0);
8188
8189 /* Realize display palette and garbage all frames. */
8190 release_frame_dc (f, hdc);
8191
8192 if (*pixmap == NULL)
8193 {
8194 DWORD err = GetLastError();
8195 Lisp_Object errcode;
8196 /* All system errors are < 10000, so the following is safe. */
8197 XSETINT (errcode, (int) err);
8198 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
8199 x_destroy_x_image (*ximg);
8200 return 0;
8201 }
8202
8203 return 1;
8204}
8205
8206
8207/* Destroy XImage XIMG. Free XIMG->data. */
8208
8209static void
8210x_destroy_x_image (ximg)
8211 XImage *ximg;
8212{
8213 xassert (interrupt_input_blocked);
8214 if (ximg)
8215 {
8216 /* Data will be freed by DestroyObject. */
8217 ximg->data = NULL;
8218 xfree (ximg);
8219 }
8220}
8221
8222
8223/* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
8224 are width and height of both the image and pixmap. */
8225
8226static void
8227x_put_x_image (f, ximg, pixmap, width, height)
8228 struct frame *f;
8229 XImage *ximg;
8230 Pixmap pixmap;
8231 int width, height;
8232{
8233#if 0 /* I don't think this is necessary looking at where it is used. */
8234 HDC hdc = get_frame_dc (f);
8235 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
8236 release_frame_dc (f, hdc);
8237#endif
8238}
8239
8240
8241/***********************************************************************
8242 File Handling
8243 ***********************************************************************/
8244
8245static Lisp_Object x_find_image_file P_ ((Lisp_Object));
8246static unsigned char *slurp_file P_ ((char *, int *));
8247
8248
8249/* Find image file FILE. Look in data-directory, then
8250 x-bitmap-file-path. Value is the full name of the file found, or
8251 nil if not found. */
8252
8253static Lisp_Object
8254x_find_image_file (file)
8255 Lisp_Object file;
8256{
8257 Lisp_Object file_found, search_path;
8258 struct gcpro gcpro1, gcpro2;
8259 int fd;
8260
8261 file_found = Qnil;
8262 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
8263 GCPRO2 (file_found, search_path);
8264
8265 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
8266 fd = openp (search_path, file, Qnil, &file_found, Qnil);
8267
8268 if (fd == -1)
8269 file_found = Qnil;
8270 else
8271 close (fd);
8272
8273 UNGCPRO;
8274 return file_found;
8275}
8276
8277
8278/* Read FILE into memory. Value is a pointer to a buffer allocated
8279 with xmalloc holding FILE's contents. Value is null if an error
8280 occurred. *SIZE is set to the size of the file. */
8281
8282static unsigned char *
8283slurp_file (file, size)
8284 char *file;
8285 int *size;
8286{
8287 FILE *fp = NULL;
8288 unsigned char *buf = NULL;
8289 struct stat st;
8290
8291 if (stat (file, &st) == 0
8292 && (fp = fopen (file, "rb")) != NULL
8293 && (buf = (char *) xmalloc (st.st_size),
8294 fread (buf, 1, st.st_size, fp) == st.st_size))
8295 {
8296 *size = st.st_size;
8297 fclose (fp);
8298 }
8299 else
8300 {
8301 if (fp)
8302 fclose (fp);
8303 if (buf)
8304 {
8305 xfree (buf);
8306 buf = NULL;
8307 }
8308 }
8309
8310 return buf;
8311}
8312
8313
8314
8315/***********************************************************************
8316 XBM images
8317 ***********************************************************************/
8318
8319static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
8320static int xbm_load P_ ((struct frame *f, struct image *img));
8321static int xbm_load_image P_ ((struct frame *f, struct image *img,
8322 unsigned char *, unsigned char *));
8323static int xbm_image_p P_ ((Lisp_Object object));
8324static int xbm_read_bitmap_data P_ ((unsigned char *, unsigned char *,
8325 int *, int *, unsigned char **));
8326static int xbm_file_p P_ ((Lisp_Object));
8327
8328
8329/* Indices of image specification fields in xbm_format, below. */
8330
8331enum xbm_keyword_index
8332{
8333 XBM_TYPE,
8334 XBM_FILE,
8335 XBM_WIDTH,
8336 XBM_HEIGHT,
8337 XBM_DATA,
8338 XBM_FOREGROUND,
8339 XBM_BACKGROUND,
8340 XBM_ASCENT,
8341 XBM_MARGIN,
8342 XBM_RELIEF,
8343 XBM_ALGORITHM,
8344 XBM_HEURISTIC_MASK,
8345 XBM_MASK,
8346 XBM_LAST
8347};
8348
8349/* Vector of image_keyword structures describing the format
8350 of valid XBM image specifications. */
8351
8352static struct image_keyword xbm_format[XBM_LAST] =
8353{
8354 {":type", IMAGE_SYMBOL_VALUE, 1},
8355 {":file", IMAGE_STRING_VALUE, 0},
8356 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8357 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
8358 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8359 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
8360 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
8361 {":ascent", IMAGE_ASCENT_VALUE, 0},
8362 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8363 {":relief", IMAGE_INTEGER_VALUE, 0},
8364 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8365 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8366 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
8367};
8368
8369/* Structure describing the image type XBM. */
8370
8371static struct image_type xbm_type =
8372{
8373 &Qxbm,
8374 xbm_image_p,
8375 xbm_load,
8376 x_clear_image,
8377 NULL
8378};
8379
8380/* Tokens returned from xbm_scan. */
8381
8382enum xbm_token
8383{
8384 XBM_TK_IDENT = 256,
8385 XBM_TK_NUMBER
8386};
8387
8388
8389/* Return non-zero if OBJECT is a valid XBM-type image specification.
8390 A valid specification is a list starting with the symbol `image'
8391 The rest of the list is a property list which must contain an
8392 entry `:type xbm..
8393
8394 If the specification specifies a file to load, it must contain
8395 an entry `:file FILENAME' where FILENAME is a string.
8396
8397 If the specification is for a bitmap loaded from memory it must
8398 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
8399 WIDTH and HEIGHT are integers > 0. DATA may be:
8400
8401 1. a string large enough to hold the bitmap data, i.e. it must
8402 have a size >= (WIDTH + 7) / 8 * HEIGHT
8403
8404 2. a bool-vector of size >= WIDTH * HEIGHT
8405
8406 3. a vector of strings or bool-vectors, one for each line of the
8407 bitmap.
8408
8409 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
8410 may not be specified in this case because they are defined in the
8411 XBM file.
8412
8413 Both the file and data forms may contain the additional entries
8414 `:background COLOR' and `:foreground COLOR'. If not present,
8415 foreground and background of the frame on which the image is
8416 displayed is used. */
8417
8418static int
8419xbm_image_p (object)
8420 Lisp_Object object;
8421{
8422 struct image_keyword kw[XBM_LAST];
8423
8424 bcopy (xbm_format, kw, sizeof kw);
8425 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
8426 return 0;
8427
8428 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
8429
8430 if (kw[XBM_FILE].count)
8431 {
8432 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
8433 return 0;
8434 }
8435 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
8436 {
8437 /* In-memory XBM file. */
8438 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
8439 return 0;
8440 }
8441 else
8442 {
8443 Lisp_Object data;
8444 int width, height;
8445
8446 /* Entries for `:width', `:height' and `:data' must be present. */
8447 if (!kw[XBM_WIDTH].count
8448 || !kw[XBM_HEIGHT].count
8449 || !kw[XBM_DATA].count)
8450 return 0;
8451
8452 data = kw[XBM_DATA].value;
8453 width = XFASTINT (kw[XBM_WIDTH].value);
8454 height = XFASTINT (kw[XBM_HEIGHT].value);
8455
8456 /* Check type of data, and width and height against contents of
8457 data. */
8458 if (VECTORP (data))
8459 {
8460 int i;
8461
8462 /* Number of elements of the vector must be >= height. */
8463 if (XVECTOR (data)->size < height)
8464 return 0;
8465
8466 /* Each string or bool-vector in data must be large enough
8467 for one line of the image. */
8468 for (i = 0; i < height; ++i)
8469 {
8470 Lisp_Object elt = XVECTOR (data)->contents[i];
8471
8472 if (STRINGP (elt))
8473 {
8474 if (SCHARS (elt)
8475 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
8476 return 0;
8477 }
8478 else if (BOOL_VECTOR_P (elt))
8479 {
8480 if (XBOOL_VECTOR (elt)->size < width)
8481 return 0;
8482 }
8483 else
8484 return 0;
8485 }
8486 }
8487 else if (STRINGP (data))
8488 {
8489 if (SCHARS (data)
8490 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
8491 return 0;
8492 }
8493 else if (BOOL_VECTOR_P (data))
8494 {
8495 if (XBOOL_VECTOR (data)->size < width * height)
8496 return 0;
8497 }
8498 else
8499 return 0;
8500 }
8501
8502 return 1;
8503}
8504
8505
8506/* Scan a bitmap file. FP is the stream to read from. Value is
8507 either an enumerator from enum xbm_token, or a character for a
8508 single-character token, or 0 at end of file. If scanning an
8509 identifier, store the lexeme of the identifier in SVAL. If
8510 scanning a number, store its value in *IVAL. */
8511
8512static int
8513xbm_scan (s, end, sval, ival)
8514 unsigned char **s, *end;
8515 char *sval;
8516 int *ival;
8517{
8518 unsigned int c;
8519
8520 loop:
8521
8522 /* Skip white space. */
8523 while (*s < end && (c = *(*s)++, isspace (c)))
8524 ;
8525
8526 if (*s >= end)
8527 c = 0;
8528 else if (isdigit (c))
8529 {
8530 int value = 0, digit;
8531
8532 if (c == '0' && *s < end)
8533 {
8534 c = *(*s)++;
8535 if (c == 'x' || c == 'X')
8536 {
8537 while (*s < end)
8538 {
8539 c = *(*s)++;
8540 if (isdigit (c))
8541 digit = c - '0';
8542 else if (c >= 'a' && c <= 'f')
8543 digit = c - 'a' + 10;
8544 else if (c >= 'A' && c <= 'F')
8545 digit = c - 'A' + 10;
8546 else
8547 break;
8548 value = 16 * value + digit;
8549 }
8550 }
8551 else if (isdigit (c))
8552 {
8553 value = c - '0';
8554 while (*s < end
8555 && (c = *(*s)++, isdigit (c)))
8556 value = 8 * value + c - '0';
8557 }
8558 }
8559 else
8560 {
8561 value = c - '0';
8562 while (*s < end
8563 && (c = *(*s)++, isdigit (c)))
8564 value = 10 * value + c - '0';
8565 }
8566
8567 if (*s < end)
8568 *s = *s - 1;
8569 *ival = value;
8570 c = XBM_TK_NUMBER;
8571 }
8572 else if (isalpha (c) || c == '_')
8573 {
8574 *sval++ = c;
8575 while (*s < end
8576 && (c = *(*s)++, (isalnum (c) || c == '_')))
8577 *sval++ = c;
8578 *sval = 0;
8579 if (*s < end)
8580 *s = *s - 1;
8581 c = XBM_TK_IDENT;
8582 }
8583 else if (c == '/' && **s == '*')
8584 {
8585 /* C-style comment. */
8586 ++*s;
8587 while (**s && (**s != '*' || *(*s + 1) != '/'))
8588 ++*s;
8589 if (**s)
8590 {
8591 *s += 2;
8592 goto loop;
8593 }
8594 }
8595
8596 return c;
8597}
8598
8599
8600/* XBM bits seem to be backward within bytes compared with how
8601 Windows does things. */
8602static unsigned char reflect_byte (unsigned char orig)
8603{
8604 int i;
8605 unsigned char reflected = 0x00;
8606 for (i = 0; i < 8; i++)
8607 {
8608 if (orig & (0x01 << i))
8609 reflected |= 0x80 >> i;
8610 }
8611 return reflected;
8612}
8613
8614
8615/* Create a Windows bitmap from X bitmap data. */
8616static HBITMAP
8617w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
8618{
8619 int i, j, w1, w2;
8620 char *bits, *p;
8621 HBITMAP bmp;
8622
8623 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
8624 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
8625 bits = (char *) alloca (height * w2);
8626 bzero (bits, height * w2);
8627 for (i = 0; i < height; i++)
8628 {
8629 p = bits + i*w2;
8630 for (j = 0; j < w1; j++)
8631 *p++ = reflect_byte(*data++);
8632 }
8633 bmp = CreateBitmap (width, height, 1, 1, bits);
8634
8635 return bmp;
8636}
8637
8638
8639/* Replacement for XReadBitmapFileData which isn't available under old
8640 X versions. CONTENTS is a pointer to a buffer to parse; END is the
8641 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
8642 the image. Return in *DATA the bitmap data allocated with xmalloc.
8643 Value is non-zero if successful. DATA null means just test if
8644 CONTENTS looks like an in-memory XBM file. */
8645
8646static int
8647xbm_read_bitmap_data (contents, end, width, height, data)
8648 unsigned char *contents, *end;
8649 int *width, *height;
8650 unsigned char **data;
8651{
8652 unsigned char *s = contents;
8653 char buffer[BUFSIZ];
8654 int padding_p = 0;
8655 int v10 = 0;
8656 int bytes_per_line, i, nbytes;
8657 unsigned char *p;
8658 int value;
8659 int LA1;
8660
8661#define match() \
8662 LA1 = xbm_scan (&s, end, buffer, &value)
8663
8664#define expect(TOKEN) \
8665 if (LA1 != (TOKEN)) \
8666 goto failure; \
8667 else \
8668 match ()
8669
8670#define expect_ident(IDENT) \
8671 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
8672 match (); \
8673 else \
8674 goto failure
8675
8676 *width = *height = -1;
8677 if (data)
8678 *data = NULL;
8679 LA1 = xbm_scan (&s, end, buffer, &value);
8680
8681 /* Parse defines for width, height and hot-spots. */
8682 while (LA1 == '#')
8683 {
8684 match ();
8685 expect_ident ("define");
8686 expect (XBM_TK_IDENT);
8687
8688 if (LA1 == XBM_TK_NUMBER);
8689 {
8690 char *p = strrchr (buffer, '_');
8691 p = p ? p + 1 : buffer;
8692 if (strcmp (p, "width") == 0)
8693 *width = value;
8694 else if (strcmp (p, "height") == 0)
8695 *height = value;
8696 }
8697 expect (XBM_TK_NUMBER);
8698 }
8699
8700 if (*width < 0 || *height < 0)
8701 goto failure;
8702 else if (data == NULL)
8703 goto success;
8704
8705 /* Parse bits. Must start with `static'. */
8706 expect_ident ("static");
8707 if (LA1 == XBM_TK_IDENT)
8708 {
8709 if (strcmp (buffer, "unsigned") == 0)
8710 {
8711 match ();
8712 expect_ident ("char");
8713 }
8714 else if (strcmp (buffer, "short") == 0)
8715 {
8716 match ();
8717 v10 = 1;
8718 if (*width % 16 && *width % 16 < 9)
8719 padding_p = 1;
8720 }
8721 else if (strcmp (buffer, "char") == 0)
8722 match ();
8723 else
8724 goto failure;
8725 }
8726 else
8727 goto failure;
8728
8729 expect (XBM_TK_IDENT);
8730 expect ('[');
8731 expect (']');
8732 expect ('=');
8733 expect ('{');
8734
8735 bytes_per_line = (*width + 7) / 8 + padding_p;
8736 nbytes = bytes_per_line * *height;
8737 p = *data = (char *) xmalloc (nbytes);
8738
8739 if (v10)
8740 {
8741 for (i = 0; i < nbytes; i += 2)
8742 {
8743 int val = value;
8744 expect (XBM_TK_NUMBER);
8745
8746 *p++ = ~ val;
8747 if (!padding_p || ((i + 2) % bytes_per_line))
8748 *p++ = ~ (value >> 8);
8749
8750 if (LA1 == ',' || LA1 == '}')
8751 match ();
8752 else
8753 goto failure;
8754 }
8755 }
8756 else
8757 {
8758 for (i = 0; i < nbytes; ++i)
8759 {
8760 int val = value;
8761 expect (XBM_TK_NUMBER);
8762
8763 *p++ = ~ val;
8764
8765 if (LA1 == ',' || LA1 == '}')
8766 match ();
8767 else
8768 goto failure;
8769 }
8770 }
8771
8772 success:
8773 return 1;
8774
8775 failure:
8776
8777 if (data && *data)
8778 {
8779 xfree (*data);
8780 *data = NULL;
8781 }
8782 return 0;
8783
8784#undef match
8785#undef expect
8786#undef expect_ident
8787}
8788
8789static void convert_mono_to_color_image (f, img, foreground, background)
8790 struct frame *f;
8791 struct image *img;
8792 COLORREF foreground, background;
8793{
8794 HDC hdc, old_img_dc, new_img_dc;
8795 HGDIOBJ old_prev, new_prev;
8796 HBITMAP new_pixmap;
8797
8798 hdc = get_frame_dc (f);
8799 old_img_dc = CreateCompatibleDC (hdc);
8800 new_img_dc = CreateCompatibleDC (hdc);
8801 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
8802 release_frame_dc (f, hdc);
8803 old_prev = SelectObject (old_img_dc, img->pixmap);
8804 new_prev = SelectObject (new_img_dc, new_pixmap);
8805 SetTextColor (new_img_dc, foreground);
8806 SetBkColor (new_img_dc, background);
8807
8808 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
8809 0, 0, SRCCOPY);
8810
8811 SelectObject (old_img_dc, old_prev);
8812 SelectObject (new_img_dc, new_prev);
8813 DeleteDC (old_img_dc);
8814 DeleteDC (new_img_dc);
8815 DeleteObject (img->pixmap);
8816 if (new_pixmap == 0)
8817 fprintf (stderr, "Failed to convert image to color.\n");
8818 else
8819 img->pixmap = new_pixmap;
8820}
8821
8822/* Load XBM image IMG which will be displayed on frame F from buffer
8823 CONTENTS. END is the end of the buffer. Value is non-zero if
8824 successful. */
8825
8826static int
8827xbm_load_image (f, img, contents, end)
8828 struct frame *f;
8829 struct image *img;
8830 unsigned char *contents, *end;
8831{
8832 int rc;
8833 unsigned char *data;
8834 int success_p = 0;
8835
8836 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
8837 if (rc)
8838 {
8839 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
8840 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
8841 int non_default_colors = 0;
8842 Lisp_Object value;
8843
8844 xassert (img->width > 0 && img->height > 0);
8845
8846 /* Get foreground and background colors, maybe allocate colors. */
8847 value = image_spec_value (img->spec, QCforeground, NULL);
8848 if (!NILP (value))
8849 {
8850 foreground = x_alloc_image_color (f, img, value, foreground);
8851 non_default_colors = 1;
8852 }
8853 value = image_spec_value (img->spec, QCbackground, NULL);
8854 if (!NILP (value))
8855 {
8856 background = x_alloc_image_color (f, img, value, background);
8857 img->background = background;
8858 img->background_valid = 1;
8859 non_default_colors = 1;
8860 }
8861 img->pixmap
8862 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
8863
8864 /* If colors were specified, transfer the bitmap to a color one. */
8865 if (non_default_colors)
8866 convert_mono_to_color_image (f, img, foreground, background);
8867
8868 xfree (data);
8869
8870 if (img->pixmap == 0)
8871 {
8872 x_clear_image (f, img);
8873 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
8874 }
8875 else
8876 success_p = 1;
8877 }
8878 else
8879 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
8880
8881 return success_p;
8882}
8883
8884
8885/* Value is non-zero if DATA looks like an in-memory XBM file. */
8886
8887static int
8888xbm_file_p (data)
8889 Lisp_Object data;
8890{
8891 int w, h;
8892 return (STRINGP (data)
8893 && xbm_read_bitmap_data (SDATA (data),
8894 (SDATA (data)
8895 + SBYTES (data)),
8896 &w, &h, NULL));
8897}
8898
8899
8900/* Fill image IMG which is used on frame F with pixmap data. Value is
8901 non-zero if successful. */
8902
8903static int
8904xbm_load (f, img)
8905 struct frame *f;
8906 struct image *img;
8907{
8908 int success_p = 0;
8909 Lisp_Object file_name;
8910
8911 xassert (xbm_image_p (img->spec));
8912
8913 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8914 file_name = image_spec_value (img->spec, QCfile, NULL);
8915 if (STRINGP (file_name))
8916 {
8917 Lisp_Object file;
8918 unsigned char *contents;
8919 int size;
8920 struct gcpro gcpro1;
8921
8922 file = x_find_image_file (file_name);
8923 GCPRO1 (file);
8924 if (!STRINGP (file))
8925 {
8926 image_error ("Cannot find image file `%s'", file_name, Qnil);
8927 UNGCPRO;
8928 return 0;
8929 }
8930
8931 contents = slurp_file (SDATA (file), &size);
8932 if (contents == NULL)
8933 {
8934 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
8935 UNGCPRO;
8936 return 0;
8937 }
8938
8939 success_p = xbm_load_image (f, img, contents, contents + size);
8940 UNGCPRO;
8941 }
8942 else
8943 {
8944 struct image_keyword fmt[XBM_LAST];
8945 Lisp_Object data;
8946 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
8947 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
8948 int non_default_colors = 0;
8949 char *bits;
8950 int parsed_p;
8951 int in_memory_file_p = 0;
8952
8953 /* See if data looks like an in-memory XBM file. */
8954 data = image_spec_value (img->spec, QCdata, NULL);
8955 in_memory_file_p = xbm_file_p (data);
8956
8957 /* Parse the image specification. */
8958 bcopy (xbm_format, fmt, sizeof fmt);
8959 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
8960 xassert (parsed_p);
8961
8962 /* Get specified width, and height. */
8963 if (!in_memory_file_p)
8964 {
8965 img->width = XFASTINT (fmt[XBM_WIDTH].value);
8966 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
8967 xassert (img->width > 0 && img->height > 0);
8968 }
8969
8970 /* Get foreground and background colors, maybe allocate colors. */
8971 if (fmt[XBM_FOREGROUND].count
8972 && STRINGP (fmt[XBM_FOREGROUND].value))
8973 {
8974 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
8975 foreground);
8976 non_default_colors = 1;
8977 }
8978
8979 if (fmt[XBM_BACKGROUND].count
8980 && STRINGP (fmt[XBM_BACKGROUND].value))
8981 {
8982 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
8983 background);
8984 non_default_colors = 1;
8985 }
8986
8987 if (in_memory_file_p)
8988 success_p = xbm_load_image (f, img, SDATA (data),
8989 (SDATA (data)
8990 + SBYTES (data)));
8991 else
8992 {
8993 if (VECTORP (data))
8994 {
8995 int i;
8996 char *p;
8997 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
8998
8999 p = bits = (char *) alloca (nbytes * img->height);
9000 for (i = 0; i < img->height; ++i, p += nbytes)
9001 {
9002 Lisp_Object line = XVECTOR (data)->contents[i];
9003 if (STRINGP (line))
9004 bcopy (SDATA (line), p, nbytes);
9005 else
9006 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
9007 }
9008 }
9009 else if (STRINGP (data))
9010 bits = SDATA (data);
9011 else
9012 bits = XBOOL_VECTOR (data)->data;
9013
9014 /* Create the pixmap. */
9015 img->pixmap
9016 = w32_create_pixmap_from_bitmap_data (img->width, img->height,
9017 bits);
9018
9019 /* If colors were specified, transfer the bitmap to a color one. */
9020 if (non_default_colors)
9021 convert_mono_to_color_image (f, img, foreground, background);
9022
9023 if (img->pixmap)
9024 success_p = 1;
9025 else
9026 {
9027 image_error ("Unable to create pixmap for XBM image `%s'",
9028 img->spec, Qnil);
9029 x_clear_image (f, img);
9030 }
9031 }
9032 }
9033
9034 return success_p;
9035}
9036
9037
9038
9039/***********************************************************************
9040 XPM images
9041 ***********************************************************************/
9042
9043#if HAVE_XPM
9044
9045static int xpm_image_p P_ ((Lisp_Object object));
9046static int xpm_load P_ ((struct frame *f, struct image *img));
9047static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
9048
9049/* Indicate to xpm.h that we don't have Xlib. */
9050#define FOR_MSW
9051/* simx.h in xpm defines XColor and XImage differently than Emacs. */
9052#define XColor xpm_XColor
9053#define XImage xpm_XImage
9054#define PIXEL_ALREADY_TYPEDEFED
9055#include "X11/xpm.h"
9056#undef FOR_MSW
9057#undef XColor
9058#undef XImage
9059#undef PIXEL_ALREADY_TYPEDEFED
9060
9061/* The symbol `xpm' identifying XPM-format images. */
9062
9063Lisp_Object Qxpm;
9064
9065/* Indices of image specification fields in xpm_format, below. */
9066
9067enum xpm_keyword_index
9068{
9069 XPM_TYPE,
9070 XPM_FILE,
9071 XPM_DATA,
9072 XPM_ASCENT,
9073 XPM_MARGIN,
9074 XPM_RELIEF,
9075 XPM_ALGORITHM,
9076 XPM_HEURISTIC_MASK,
9077 XPM_MASK,
9078 XPM_COLOR_SYMBOLS,
9079 XPM_BACKGROUND,
9080 XPM_LAST
9081};
9082
9083/* Vector of image_keyword structures describing the format
9084 of valid XPM image specifications. */
9085
9086static struct image_keyword xpm_format[XPM_LAST] =
9087{
9088 {":type", IMAGE_SYMBOL_VALUE, 1},
9089 {":file", IMAGE_STRING_VALUE, 0},
9090 {":data", IMAGE_STRING_VALUE, 0},
9091 {":ascent", IMAGE_ASCENT_VALUE, 0},
9092 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9093 {":relief", IMAGE_INTEGER_VALUE, 0},
9094 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9095 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9096 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9097 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9098 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9099};
9100
9101/* Structure describing the image type XPM. */
9102
9103static struct image_type xpm_type =
9104{
9105 &Qxpm,
9106 xpm_image_p,
9107 xpm_load,
9108 x_clear_image,
9109 NULL
9110};
9111
9112
9113/* XPM library details. */
9114
9115DEF_IMGLIB_FN (XpmFreeAttributes);
9116DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
9117DEF_IMGLIB_FN (XpmReadFileToImage);
9118DEF_IMGLIB_FN (XImageFree);
9119
9120
9121static int
9122init_xpm_functions (library)
9123 HMODULE library;
9124{
9125 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
9126 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
9127 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
9128 LOAD_IMGLIB_FN (library, XImageFree);
9129
9130 return 1;
9131}
9132
9133/* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
9134 for XPM images. Such a list must consist of conses whose car and
9135 cdr are strings. */
9136
9137static int
9138xpm_valid_color_symbols_p (color_symbols)
9139 Lisp_Object color_symbols;
9140{
9141 while (CONSP (color_symbols))
9142 {
9143 Lisp_Object sym = XCAR (color_symbols);
9144 if (!CONSP (sym)
9145 || !STRINGP (XCAR (sym))
9146 || !STRINGP (XCDR (sym)))
9147 break;
9148 color_symbols = XCDR (color_symbols);
9149 }
9150
9151 return NILP (color_symbols);
9152}
9153
9154
9155/* Value is non-zero if OBJECT is a valid XPM image specification. */
9156
9157static int
9158xpm_image_p (object)
9159 Lisp_Object object;
9160{
9161 struct image_keyword fmt[XPM_LAST];
9162 bcopy (xpm_format, fmt, sizeof fmt);
9163 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
9164 /* Either `:file' or `:data' must be present. */
9165 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
9166 /* Either no `:color-symbols' or it's a list of conses
9167 whose car and cdr are strings. */
9168 && (fmt[XPM_COLOR_SYMBOLS].count == 0
9169 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
9170}
9171
9172
9173/* Load image IMG which will be displayed on frame F. Value is
9174 non-zero if successful. */
9175
9176static int
9177xpm_load (f, img)
9178 struct frame *f;
9179 struct image *img;
9180{
9181 HDC hdc;
9182 int rc;
9183 XpmAttributes attrs;
9184 Lisp_Object specified_file, color_symbols;
9185 xpm_XImage * xpm_image, * xpm_mask;
9186
9187 /* Configure the XPM lib. Use the visual of frame F. Allocate
9188 close colors. Return colors allocated. */
9189 bzero (&attrs, sizeof attrs);
9190 xpm_image = xpm_mask = NULL;
9191
9192#if 0
9193 attrs.visual = FRAME_X_VISUAL (f);
9194 attrs.colormap = FRAME_X_COLORMAP (f);
9195 attrs.valuemask |= XpmVisual;
9196 attrs.valuemask |= XpmColormap;
9197#endif
9198 attrs.valuemask |= XpmReturnAllocPixels;
9199#ifdef XpmAllocCloseColors
9200 attrs.alloc_close_colors = 1;
9201 attrs.valuemask |= XpmAllocCloseColors;
9202#else
9203 attrs.closeness = 600;
9204 attrs.valuemask |= XpmCloseness;
9205#endif
9206
9207 /* If image specification contains symbolic color definitions, add
9208 these to `attrs'. */
9209 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
9210 if (CONSP (color_symbols))
9211 {
9212 Lisp_Object tail;
9213 XpmColorSymbol *xpm_syms;
9214 int i, size;
9215
9216 attrs.valuemask |= XpmColorSymbols;
9217
9218 /* Count number of symbols. */
9219 attrs.numsymbols = 0;
9220 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
9221 ++attrs.numsymbols;
9222
9223 /* Allocate an XpmColorSymbol array. */
9224 size = attrs.numsymbols * sizeof *xpm_syms;
9225 xpm_syms = (XpmColorSymbol *) alloca (size);
9226 bzero (xpm_syms, size);
9227 attrs.colorsymbols = xpm_syms;
9228
9229 /* Fill the color symbol array. */
9230 for (tail = color_symbols, i = 0;
9231 CONSP (tail);
9232 ++i, tail = XCDR (tail))
9233 {
9234 Lisp_Object name = XCAR (XCAR (tail));
9235 Lisp_Object color = XCDR (XCAR (tail));
9236 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
9237 strcpy (xpm_syms[i].name, SDATA (name));
9238 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
9239 strcpy (xpm_syms[i].value, SDATA (color));
9240 }
9241 }
9242
9243 /* Create a pixmap for the image, either from a file, or from a
9244 string buffer containing data in the same format as an XPM file. */
9245
9246 specified_file = image_spec_value (img->spec, QCfile, NULL);
9247
9248 {
9249 HDC frame_dc = get_frame_dc (f);
9250 hdc = CreateCompatibleDC (frame_dc);
9251 release_frame_dc (f, frame_dc);
9252 }
9253
9254 if (STRINGP (specified_file))
9255 {
9256 Lisp_Object file = x_find_image_file (specified_file);
9257 if (!STRINGP (file))
9258 {
9259 image_error ("Cannot find image file `%s'", specified_file, Qnil);
9260 return 0;
9261 }
9262
9263 /* XpmReadFileToPixmap is not available in the Windows port of
9264 libxpm. But XpmReadFileToImage almost does what we want. */
9265 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
9266 &xpm_image, &xpm_mask,
9267 &attrs);
9268 }
9269 else
9270 {
9271 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
9272 /* XpmCreatePixmapFromBuffer is not available in the Windows port
9273 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
9274 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
9275 &xpm_image, &xpm_mask,
9276 &attrs);
9277 }
9278
9279 if (rc == XpmSuccess)
9280 {
9281 int i;
9282
9283 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
9284 plus some duplicate attributes. */
9285 if (xpm_image && xpm_image->bitmap)
9286 {
9287 img->pixmap = xpm_image->bitmap;
9288 /* XImageFree in libXpm frees XImage struct without destroying
9289 the bitmap, which is what we want. */
9290 fn_XImageFree (xpm_image);
9291 }
9292 if (xpm_mask && xpm_mask->bitmap)
9293 {
9294 /* The mask appears to be inverted compared with what we expect.
9295 TODO: invert our expectations. See other places where we
9296 have to invert bits because our idea of masks is backwards. */
9297 HGDIOBJ old_obj;
9298 old_obj = SelectObject (hdc, xpm_mask->bitmap);
9299
9300 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
9301 SelectObject (hdc, old_obj);
9302
9303 img->mask = xpm_mask->bitmap;
9304 fn_XImageFree (xpm_mask);
9305 DeleteDC (hdc);
9306 }
9307
9308 DeleteDC (hdc);
9309
9310 /* Remember allocated colors. */
9311 img->ncolors = attrs.nalloc_pixels;
9312 img->colors = (unsigned long *) xmalloc (img->ncolors
9313 * sizeof *img->colors);
9314 for (i = 0; i < attrs.nalloc_pixels; ++i)
9315 img->colors[i] = attrs.alloc_pixels[i];
9316
9317 img->width = attrs.width;
9318 img->height = attrs.height;
9319 xassert (img->width > 0 && img->height > 0);
9320
9321 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
9322 fn_XpmFreeAttributes (&attrs);
9323 }
9324 else
9325 {
9326 DeleteDC (hdc);
9327
9328 switch (rc)
9329 {
9330 case XpmOpenFailed:
9331 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
9332 break;
9333
9334 case XpmFileInvalid:
9335 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
9336 break;
9337
9338 case XpmNoMemory:
9339 image_error ("Out of memory (%s)", img->spec, Qnil);
9340 break;
9341
9342 case XpmColorFailed:
9343 image_error ("Color allocation error (%s)", img->spec, Qnil);
9344 break;
9345
9346 default:
9347 image_error ("Unknown error (%s)", img->spec, Qnil);
9348 break;
9349 }
9350 }
9351
9352 return rc == XpmSuccess;
9353}
9354
9355#endif /* HAVE_XPM != 0 */
9356
9357
9358#if 0 /* TODO : Color tables on W32. */
9359/***********************************************************************
9360 Color table
9361 ***********************************************************************/
9362
9363/* An entry in the color table mapping an RGB color to a pixel color. */
9364
9365struct ct_color
9366{
9367 int r, g, b;
9368 unsigned long pixel;
9369
9370 /* Next in color table collision list. */
9371 struct ct_color *next;
9372};
9373
9374/* The bucket vector size to use. Must be prime. */
9375
9376#define CT_SIZE 101
9377
9378/* Value is a hash of the RGB color given by R, G, and B. */
9379
9380#define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
9381
9382/* The color hash table. */
9383
9384struct ct_color **ct_table;
9385
9386/* Number of entries in the color table. */
9387
9388int ct_colors_allocated;
9389
9390/* Function prototypes. */
9391
9392static void init_color_table P_ ((void));
9393static void free_color_table P_ ((void));
9394static unsigned long *colors_in_color_table P_ ((int *n));
9395static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
9396static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
9397
9398
9399/* Initialize the color table. */
9400
9401static void
9402init_color_table ()
9403{
9404 int size = CT_SIZE * sizeof (*ct_table);
9405 ct_table = (struct ct_color **) xmalloc (size);
9406 bzero (ct_table, size);
9407 ct_colors_allocated = 0;
9408}
9409
9410
9411/* Free memory associated with the color table. */
9412
9413static void
9414free_color_table ()
9415{
9416 int i;
9417 struct ct_color *p, *next;
9418
9419 for (i = 0; i < CT_SIZE; ++i)
9420 for (p = ct_table[i]; p; p = next)
9421 {
9422 next = p->next;
9423 xfree (p);
9424 }
9425
9426 xfree (ct_table);
9427 ct_table = NULL;
9428}
9429
9430
9431/* Value is a pixel color for RGB color R, G, B on frame F. If an
9432 entry for that color already is in the color table, return the
9433 pixel color of that entry. Otherwise, allocate a new color for R,
9434 G, B, and make an entry in the color table. */
9435
9436static unsigned long
9437lookup_rgb_color (f, r, g, b)
9438 struct frame *f;
9439 int r, g, b;
9440{
9441 unsigned hash = CT_HASH_RGB (r, g, b);
9442 int i = hash % CT_SIZE;
9443 struct ct_color *p;
9444
9445 for (p = ct_table[i]; p; p = p->next)
9446 if (p->r == r && p->g == g && p->b == b)
9447 break;
9448
9449 if (p == NULL)
9450 {
9451 COLORREF color;
9452 Colormap cmap;
9453 int rc;
9454
9455 color = PALETTERGB (r, g, b);
9456
9457 ++ct_colors_allocated;
9458
9459 p = (struct ct_color *) xmalloc (sizeof *p);
9460 p->r = r;
9461 p->g = g;
9462 p->b = b;
9463 p->pixel = color;
9464 p->next = ct_table[i];
9465 ct_table[i] = p;
9466 }
9467
9468 return p->pixel;
9469}
9470
9471
9472/* Look up pixel color PIXEL which is used on frame F in the color
9473 table. If not already present, allocate it. Value is PIXEL. */
9474
9475static unsigned long
9476lookup_pixel_color (f, pixel)
9477 struct frame *f;
9478 unsigned long pixel;
9479{
9480 int i = pixel % CT_SIZE;
9481 struct ct_color *p;
9482
9483 for (p = ct_table[i]; p; p = p->next)
9484 if (p->pixel == pixel)
9485 break;
9486
9487 if (p == NULL)
9488 {
9489 XColor color;
9490 Colormap cmap;
9491 int rc;
9492
9493 BLOCK_INPUT;
9494
9495 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
9496 color.pixel = pixel;
9497 XQueryColor (NULL, cmap, &color);
9498 rc = x_alloc_nearest_color (f, cmap, &color);
9499 UNBLOCK_INPUT;
9500
9501 if (rc)
9502 {
9503 ++ct_colors_allocated;
9504
9505 p = (struct ct_color *) xmalloc (sizeof *p);
9506 p->r = color.red;
9507 p->g = color.green;
9508 p->b = color.blue;
9509 p->pixel = pixel;
9510 p->next = ct_table[i];
9511 ct_table[i] = p;
9512 }
9513 else
9514 return FRAME_FOREGROUND_PIXEL (f);
9515 }
9516 return p->pixel;
9517}
9518
9519
9520/* Value is a vector of all pixel colors contained in the color table,
9521 allocated via xmalloc. Set *N to the number of colors. */
9522
9523static unsigned long *
9524colors_in_color_table (n)
9525 int *n;
9526{
9527 int i, j;
9528 struct ct_color *p;
9529 unsigned long *colors;
9530
9531 if (ct_colors_allocated == 0)
9532 {
9533 *n = 0;
9534 colors = NULL;
9535 }
9536 else
9537 {
9538 colors = (unsigned long *) xmalloc (ct_colors_allocated
9539 * sizeof *colors);
9540 *n = ct_colors_allocated;
9541
9542 for (i = j = 0; i < CT_SIZE; ++i)
9543 for (p = ct_table[i]; p; p = p->next)
9544 colors[j++] = p->pixel;
9545 }
9546
9547 return colors;
9548}
9549
9550#endif /* TODO */
9551
9552
9553/***********************************************************************
9554 Algorithms
9555 ***********************************************************************/
9556static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
9557static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
9558static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
9559static void XPutPixel (XImage *, int, int, COLORREF);
9560
9561/* Non-zero means draw a cross on images having `:conversion
9562 disabled'. */
9563
9564int cross_disabled_images;
9565
9566/* Edge detection matrices for different edge-detection
9567 strategies. */
9568
9569static int emboss_matrix[9] = {
9570 /* x - 1 x x + 1 */
9571 2, -1, 0, /* y - 1 */
9572 -1, 0, 1, /* y */
9573 0, 1, -2 /* y + 1 */
9574};
9575
9576static int laplace_matrix[9] = {
9577 /* x - 1 x x + 1 */
9578 1, 0, 0, /* y - 1 */
9579 0, 0, 0, /* y */
9580 0, 0, -1 /* y + 1 */
9581};
9582
9583/* Value is the intensity of the color whose red/green/blue values
9584 are R, G, and B. */
9585
9586#define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
9587
9588
9589/* On frame F, return an array of XColor structures describing image
9590 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
9591 non-zero means also fill the red/green/blue members of the XColor
9592 structures. Value is a pointer to the array of XColors structures,
9593 allocated with xmalloc; it must be freed by the caller. */
9594
9595static XColor *
9596x_to_xcolors (f, img, rgb_p)
9597 struct frame *f;
9598 struct image *img;
9599 int rgb_p;
9600{
9601 int x, y;
9602 XColor *colors, *p;
9603 HDC hdc, bmpdc;
9604 HGDIOBJ prev;
9605
9606 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
9607
9608 /* Load the image into a memory device context. */
9609 hdc = get_frame_dc (f);
9610 bmpdc = CreateCompatibleDC (hdc);
9611 release_frame_dc (f, hdc);
9612 prev = SelectObject (bmpdc, img->pixmap);
9613
9614 /* Fill the `pixel' members of the XColor array. I wished there
9615 were an easy and portable way to circumvent XGetPixel. */
9616 p = colors;
9617 for (y = 0; y < img->height; ++y)
9618 {
9619 XColor *row = p;
9620
9621 for (x = 0; x < img->width; ++x, ++p)
9622 {
9623 /* TODO: palette support needed here? */
9624 p->pixel = GetPixel (bmpdc, x, y);
9625
9626 if (rgb_p)
9627 {
9628 p->red = 256 * GetRValue (p->pixel);
9629 p->green = 256 * GetGValue (p->pixel);
9630 p->blue = 256 * GetBValue (p->pixel);
9631 }
9632 }
9633 }
9634
9635 SelectObject (bmpdc, prev);
9636 DeleteDC (bmpdc);
9637
9638 return colors;
9639}
9640
9641/* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
9642 created with CreateDIBSection, with the pointer to the bit values
9643 stored in ximg->data. */
9644
9645static void XPutPixel (ximg, x, y, color)
9646 XImage * ximg;
9647 int x, y;
9648 COLORREF color;
9649{
9650 int width = ximg->info.bmiHeader.biWidth;
9651 int height = ximg->info.bmiHeader.biHeight;
9652 unsigned char * pixel;
9653
9654 /* True color images. */
9655 if (ximg->info.bmiHeader.biBitCount == 24)
9656 {
9657 int rowbytes = width * 3;
9658 /* Ensure scanlines are aligned on 4 byte boundaries. */
9659 if (rowbytes % 4)
9660 rowbytes += 4 - (rowbytes % 4);
9661
9662 pixel = ximg->data + y * rowbytes + x * 3;
9663 /* Windows bitmaps are in BGR order. */
9664 *pixel = GetBValue (color);
9665 *(pixel + 1) = GetGValue (color);
9666 *(pixel + 2) = GetRValue (color);
9667 }
9668 /* Monochrome images. */
9669 else if (ximg->info.bmiHeader.biBitCount == 1)
9670 {
9671 int rowbytes = width / 8;
9672 /* Ensure scanlines are aligned on 4 byte boundaries. */
9673 if (rowbytes % 4)
9674 rowbytes += 4 - (rowbytes % 4);
9675 pixel = ximg->data + y * rowbytes + x / 8;
9676 /* Filter out palette info. */
9677 if (color & 0x00ffffff)
9678 *pixel = *pixel | (1 << x % 8);
9679 else
9680 *pixel = *pixel & ~(1 << x % 8);
9681 }
9682 else
9683 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
9684}
9685
9686/* Create IMG->pixmap from an array COLORS of XColor structures, whose
9687 RGB members are set. F is the frame on which this all happens.
9688 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
9689
9690static void
9691x_from_xcolors (f, img, colors)
9692 struct frame *f;
9693 struct image *img;
9694 XColor *colors;
9695{
9696 int x, y;
9697 XImage *oimg;
9698 Pixmap pixmap;
9699 XColor *p;
9700#if 0 /* TODO: color tables. */
9701 init_color_table ();
9702#endif
9703 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
9704 &oimg, &pixmap);
9705 p = colors;
9706 for (y = 0; y < img->height; ++y)
9707 for (x = 0; x < img->width; ++x, ++p)
9708 {
9709 unsigned long pixel;
9710#if 0 /* TODO: color tables. */
9711 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
9712#else
9713 pixel = PALETTERGB (p->red / 256, p->green / 256, p->blue / 256);
9714#endif
9715 XPutPixel (oimg, x, y, pixel);
9716 }
9717
9718 xfree (colors);
9719 x_clear_image_1 (f, img, 1, 0, 1);
9720
9721 x_put_x_image (f, oimg, pixmap, img->width, img->height);
9722 x_destroy_x_image (oimg);
9723 img->pixmap = pixmap;
9724#if 0 /* TODO: color tables. */
9725 img->colors = colors_in_color_table (&img->ncolors);
9726 free_color_table ();
9727#endif
9728}
9729
9730
9731/* On frame F, perform edge-detection on image IMG.
9732
9733 MATRIX is a nine-element array specifying the transformation
9734 matrix. See emboss_matrix for an example.
9735
9736 COLOR_ADJUST is a color adjustment added to each pixel of the
9737 outgoing image. */
9738
9739static void
9740x_detect_edges (f, img, matrix, color_adjust)
9741 struct frame *f;
9742 struct image *img;
9743 int matrix[9], color_adjust;
9744{
9745 XColor *colors = x_to_xcolors (f, img, 1);
9746 XColor *new, *p;
9747 int x, y, i, sum;
9748
9749 for (i = sum = 0; i < 9; ++i)
9750 sum += abs (matrix[i]);
9751
9752#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
9753
9754 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
9755
9756 for (y = 0; y < img->height; ++y)
9757 {
9758 p = COLOR (new, 0, y);
9759 p->red = p->green = p->blue = 0xffff/2;
9760 p = COLOR (new, img->width - 1, y);
9761 p->red = p->green = p->blue = 0xffff/2;
9762 }
9763
9764 for (x = 1; x < img->width - 1; ++x)
9765 {
9766 p = COLOR (new, x, 0);
9767 p->red = p->green = p->blue = 0xffff/2;
9768 p = COLOR (new, x, img->height - 1);
9769 p->red = p->green = p->blue = 0xffff/2;
9770 }
9771
9772 for (y = 1; y < img->height - 1; ++y)
9773 {
9774 p = COLOR (new, 1, y);
9775
9776 for (x = 1; x < img->width - 1; ++x, ++p)
9777 {
9778 int r, g, b, y1, x1;
9779
9780 r = g = b = i = 0;
9781 for (y1 = y - 1; y1 < y + 2; ++y1)
9782 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
9783 if (matrix[i])
9784 {
9785 XColor *t = COLOR (colors, x1, y1);
9786 r += matrix[i] * t->red;
9787 g += matrix[i] * t->green;
9788 b += matrix[i] * t->blue;
9789 }
9790
9791 r = (r / sum + color_adjust) & 0xffff;
9792 g = (g / sum + color_adjust) & 0xffff;
9793 b = (b / sum + color_adjust) & 0xffff;
9794 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
9795 }
9796 }
9797
9798 xfree (colors);
9799 x_from_xcolors (f, img, new);
9800
9801#undef COLOR
9802}
9803
9804
9805/* Perform the pre-defined `emboss' edge-detection on image IMG
9806 on frame F. */
9807
9808static void
9809x_emboss (f, img)
9810 struct frame *f;
9811 struct image *img;
9812{
9813 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
9814}
9815
9816
9817/* Transform image IMG which is used on frame F with a Laplace
9818 edge-detection algorithm. The result is an image that can be used
9819 to draw disabled buttons, for example. */
9820
9821static void
9822x_laplace (f, img)
9823 struct frame *f;
9824 struct image *img;
9825{
9826 x_detect_edges (f, img, laplace_matrix, 45000);
9827}
9828
9829
9830/* Perform edge-detection on image IMG on frame F, with specified
9831 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
9832
9833 MATRIX must be either
9834
9835 - a list of at least 9 numbers in row-major form
9836 - a vector of at least 9 numbers
9837
9838 COLOR_ADJUST nil means use a default; otherwise it must be a
9839 number. */
9840
9841static void
9842x_edge_detection (f, img, matrix, color_adjust)
9843 struct frame *f;
9844 struct image *img;
9845 Lisp_Object matrix, color_adjust;
9846{
9847 int i = 0;
9848 int trans[9];
9849
9850 if (CONSP (matrix))
9851 {
9852 for (i = 0;
9853 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
9854 ++i, matrix = XCDR (matrix))
9855 trans[i] = XFLOATINT (XCAR (matrix));
9856 }
9857 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
9858 {
9859 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
9860 trans[i] = XFLOATINT (AREF (matrix, i));
9861 }
9862
9863 if (NILP (color_adjust))
9864 color_adjust = make_number (0xffff / 2);
9865
9866 if (i == 9 && NUMBERP (color_adjust))
9867 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
9868}
9869
9870
9871/* Transform image IMG on frame F so that it looks disabled. */
9872
9873static void
9874x_disable_image (f, img)
9875 struct frame *f;
9876 struct image *img;
9877{
9878 struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9879
9880 if (dpyinfo->n_planes * dpyinfo->n_cbits >= 2)
9881 {
9882 /* Color (or grayscale). Convert to gray, and equalize. Just
9883 drawing such images with a stipple can look very odd, so
9884 we're using this method instead. */
9885 XColor *colors = x_to_xcolors (f, img, 1);
9886 XColor *p, *end;
9887 const int h = 15000;
9888 const int l = 30000;
9889
9890 for (p = colors, end = colors + img->width * img->height;
9891 p < end;
9892 ++p)
9893 {
9894 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
9895 int i2 = (0xffff - h - l) * i / 0xffff + l;
9896 p->red = p->green = p->blue = i2;
9897 }
9898
9899 x_from_xcolors (f, img, colors);
9900 }
9901
9902 /* Draw a cross over the disabled image, if we must or if we
9903 should. */
9904 if (dpyinfo->n_planes * dpyinfo->n_cbits < 2 || cross_disabled_images)
9905 {
9906 HDC hdc, bmpdc;
9907 HGDIOBJ prev;
9908
9909 hdc = get_frame_dc (f);
9910 bmpdc = CreateCompatibleDC (hdc);
9911 release_frame_dc (f, hdc);
9912
9913 prev = SelectObject (bmpdc, img->pixmap);
9914
9915 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
9916 MoveToEx (bmpdc, 0, 0, NULL);
9917 LineTo (bmpdc, img->width - 1, img->height - 1);
9918 MoveToEx (bmpdc, 0, img->height - 1, NULL);
9919 LineTo (bmpdc, img->width - 1, 0);
9920
9921 if (img->mask)
9922 {
9923 SelectObject (bmpdc, img->mask);
9924 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
9925 MoveToEx (bmpdc, 0, 0, NULL);
9926 LineTo (bmpdc, img->width - 1, img->height - 1);
9927 MoveToEx (bmpdc, 0, img->height - 1, NULL);
9928 LineTo (bmpdc, img->width - 1, 0);
9929 }
9930 SelectObject (bmpdc, prev);
9931 DeleteDC (bmpdc);
9932 }
9933}
9934
9935
9936/* Build a mask for image IMG which is used on frame F. FILE is the
9937 name of an image file, for error messages. HOW determines how to
9938 determine the background color of IMG. If it is a list '(R G B)',
9939 with R, G, and B being integers >= 0, take that as the color of the
9940 background. Otherwise, determine the background color of IMG
9941 heuristically. Value is non-zero if successful. */
9942
9943static int
9944x_build_heuristic_mask (f, img, how)
9945 struct frame *f;
9946 struct image *img;
9947 Lisp_Object how;
9948{
9949 HDC img_dc, frame_dc;
9950 HGDIOBJ prev;
9951 char *mask_img;
9952 int x, y, rc, use_img_background;
9953 unsigned long bg = 0;
9954 int row_width;
9955
9956 if (img->mask)
9957 {
9958 DeleteObject (img->mask);
9959 img->mask = NULL;
9960 img->background_transparent_valid = 0;
9961 }
9962
9963 /* Create the bit array serving as mask. */
9964 row_width = (img->width + 7) / 8;
9965 mask_img = xmalloc (row_width * img->height);
9966 bzero (mask_img, row_width * img->height);
9967
9968 /* Create a memory device context for IMG->pixmap. */
9969 frame_dc = get_frame_dc (f);
9970 img_dc = CreateCompatibleDC (frame_dc);
9971 release_frame_dc (f, frame_dc);
9972 prev = SelectObject (img_dc, img->pixmap);
9973
9974 /* Determine the background color of img_dc. If HOW is `(R G B)'
9975 take that as color. Otherwise, use the image's background color. */
9976 use_img_background = 1;
9977
9978 if (CONSP (how))
9979 {
9980 int rgb[3], i;
9981
9982 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
9983 {
9984 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
9985 how = XCDR (how);
9986 }
9987
9988 if (i == 3 && NILP (how))
9989 {
9990 char color_name[30];
9991 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
9992 bg = x_alloc_image_color (f, img, build_string (color_name), 0)
9993 & 0x00ffffff; /* Filter out palette info. */
9994 use_img_background = 0;
9995 }
9996 }
9997
9998 if (use_img_background)
9999 bg = four_corners_best (img_dc, img->width, img->height);
10000
10001 /* Set all bits in mask_img to 1 whose color in ximg is different
10002 from the background color bg. */
10003 for (y = 0; y < img->height; ++y)
10004 for (x = 0; x < img->width; ++x)
10005 {
10006 COLORREF p = GetPixel (img_dc, x, y);
10007 if (p != bg)
10008 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
10009 }
10010
10011 /* Create the mask image. */
10012 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
10013 mask_img);
10014
10015 /* Fill in the background_transparent field while we have the mask handy. */
10016 SelectObject (img_dc, img->mask);
10017
10018 image_background_transparent (img, f, img_dc);
10019
10020 /* Put mask_img into img->mask. */
10021 x_destroy_x_image ((XImage *)mask_img);
10022 SelectObject (img_dc, prev);
10023 DeleteDC (img_dc);
10024
10025 return 1;
10026}
10027
10028
10029/***********************************************************************
10030 PBM (mono, gray, color)
10031 ***********************************************************************/
10032
10033static int pbm_image_p P_ ((Lisp_Object object));
10034static int pbm_load P_ ((struct frame *f, struct image *img));
10035static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
10036
10037/* The symbol `pbm' identifying images of this type. */
10038
10039Lisp_Object Qpbm;
10040
10041/* Indices of image specification fields in gs_format, below. */
10042
10043enum pbm_keyword_index
10044{
10045 PBM_TYPE,
10046 PBM_FILE,
10047 PBM_DATA,
10048 PBM_ASCENT,
10049 PBM_MARGIN,
10050 PBM_RELIEF,
10051 PBM_ALGORITHM,
10052 PBM_HEURISTIC_MASK,
10053 PBM_MASK,
10054 PBM_FOREGROUND,
10055 PBM_BACKGROUND,
10056 PBM_LAST
10057};
10058
10059/* Vector of image_keyword structures describing the format
10060 of valid user-defined image specifications. */
10061
10062static struct image_keyword pbm_format[PBM_LAST] =
10063{
10064 {":type", IMAGE_SYMBOL_VALUE, 1},
10065 {":file", IMAGE_STRING_VALUE, 0},
10066 {":data", IMAGE_STRING_VALUE, 0},
10067 {":ascent", IMAGE_ASCENT_VALUE, 0},
10068 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10069 {":relief", IMAGE_INTEGER_VALUE, 0},
10070 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10071 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10072 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10073 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
10074 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10075};
10076
10077/* Structure describing the image type `pbm'. */
10078
10079static struct image_type pbm_type =
10080{
10081 &Qpbm,
10082 pbm_image_p,
10083 pbm_load,
10084 x_clear_image,
10085 NULL
10086};
10087
10088
10089/* Return non-zero if OBJECT is a valid PBM image specification. */
10090
10091static int
10092pbm_image_p (object)
10093 Lisp_Object object;
10094{
10095 struct image_keyword fmt[PBM_LAST];
10096
10097 bcopy (pbm_format, fmt, sizeof fmt);
10098
10099 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
10100 return 0;
10101
10102 /* Must specify either :data or :file. */
10103 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
10104}
10105
10106
10107/* Scan a decimal number from *S and return it. Advance *S while
10108 reading the number. END is the end of the string. Value is -1 at
10109 end of input. */
10110
10111static int
10112pbm_scan_number (s, end)
10113 unsigned char **s, *end;
10114{
10115 int c, val = -1;
10116
10117 while (*s < end)
10118 {
10119 /* Skip white-space. */
10120 while (*s < end && (c = *(*s)++, isspace (c)))
10121 ;
10122
10123 if (c == '#')
10124 {
10125 /* Skip comment to end of line. */
10126 while (*s < end && (c = *(*s)++, c != '\n'))
10127 ;
10128 }
10129 else if (isdigit (c))
10130 {
10131 /* Read decimal number. */
10132 val = c - '0';
10133 while (*s < end && (c = *(*s)++, isdigit (c)))
10134 val = 10 * val + c - '0';
10135 break;
10136 }
10137 else
10138 break;
10139 }
10140
10141 return val;
10142}
10143
10144
10145/* Read FILE into memory. Value is a pointer to a buffer allocated
10146 with xmalloc holding FILE's contents. Value is null if an error
10147 occurred. *SIZE is set to the size of the file. */
10148
10149static char *
10150pbm_read_file (file, size)
10151 Lisp_Object file;
10152 int *size;
10153{
10154 FILE *fp = NULL;
10155 char *buf = NULL;
10156 struct stat st;
10157
10158 if (stat (SDATA (file), &st) == 0
10159 && (fp = fopen (SDATA (file), "rb")) != NULL
10160 && (buf = (char *) xmalloc (st.st_size),
10161 fread (buf, 1, st.st_size, fp) == st.st_size))
10162 {
10163 *size = st.st_size;
10164 fclose (fp);
10165 }
10166 else
10167 {
10168 if (fp)
10169 fclose (fp);
10170 if (buf)
10171 {
10172 xfree (buf);
10173 buf = NULL;
10174 }
10175 }
10176
10177 return buf;
10178}
10179
10180
10181/* Load PBM image IMG for use on frame F. */
10182
10183static int
10184pbm_load (f, img)
10185 struct frame *f;
10186 struct image *img;
10187{
10188 int raw_p, x, y;
10189 int width, height, max_color_idx = 0;
10190 XImage *ximg;
10191 Lisp_Object file, specified_file;
10192 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
10193 struct gcpro gcpro1;
10194 unsigned char *contents = NULL;
10195 unsigned char *end, *p;
10196 int size;
10197
10198 specified_file = image_spec_value (img->spec, QCfile, NULL);
10199 file = Qnil;
10200 GCPRO1 (file);
10201
10202 if (STRINGP (specified_file))
10203 {
10204 file = x_find_image_file (specified_file);
10205 if (!STRINGP (file))
10206 {
10207 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10208 UNGCPRO;
10209 return 0;
10210 }
10211
10212 contents = slurp_file (SDATA (file), &size);
10213 if (contents == NULL)
10214 {
10215 image_error ("Error reading `%s'", file, Qnil);
10216 UNGCPRO;
10217 return 0;
10218 }
10219
10220 p = contents;
10221 end = contents + size;
10222 }
10223 else
10224 {
10225 Lisp_Object data;
10226 data = image_spec_value (img->spec, QCdata, NULL);
10227 p = SDATA (data);
10228 end = p + SBYTES (data);
10229 }
10230
10231 /* Check magic number. */
10232 if (end - p < 2 || *p++ != 'P')
10233 {
10234 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
10235 error:
10236 xfree (contents);
10237 UNGCPRO;
10238 return 0;
10239 }
10240
10241 switch (*p++)
10242 {
10243 case '1':
10244 raw_p = 0, type = PBM_MONO;
10245 break;
10246
10247 case '2':
10248 raw_p = 0, type = PBM_GRAY;
10249 break;
10250
10251 case '3':
10252 raw_p = 0, type = PBM_COLOR;
10253 break;
10254
10255 case '4':
10256 raw_p = 1, type = PBM_MONO;
10257 break;
10258
10259 case '5':
10260 raw_p = 1, type = PBM_GRAY;
10261 break;
10262
10263 case '6':
10264 raw_p = 1, type = PBM_COLOR;
10265 break;
10266
10267 default:
10268 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
10269 goto error;
10270 }
10271
10272 /* Read width, height, maximum color-component. Characters
10273 starting with `#' up to the end of a line are ignored. */
10274 width = pbm_scan_number (&p, end);
10275 height = pbm_scan_number (&p, end);
10276
10277 if (type != PBM_MONO)
10278 {
10279 max_color_idx = pbm_scan_number (&p, end);
10280 if (raw_p && max_color_idx > 255)
10281 max_color_idx = 255;
10282 }
10283
10284 if (width < 0
10285 || height < 0
10286 || (type != PBM_MONO && max_color_idx < 0))
10287 goto error;
10288
10289 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
10290 goto error;
10291
10292#if 0 /* TODO: color tables. */
10293 /* Initialize the color hash table. */
10294 init_color_table ();
10295#endif
10296
10297 if (type == PBM_MONO)
10298 {
10299 int c = 0, g;
10300 struct image_keyword fmt[PBM_LAST];
10301 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
10302 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
10303
10304 /* Parse the image specification. */
10305 bcopy (pbm_format, fmt, sizeof fmt);
10306 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
10307
10308 /* Get foreground and background colors, maybe allocate colors. */
10309 if (fmt[PBM_FOREGROUND].count
10310 && STRINGP (fmt[PBM_FOREGROUND].value))
10311 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
10312 if (fmt[PBM_BACKGROUND].count
10313 && STRINGP (fmt[PBM_BACKGROUND].value))
10314 {
10315 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
10316 img->background = bg;
10317 img->background_valid = 1;
10318 }
10319
10320 for (y = 0; y < height; ++y)
10321 for (x = 0; x < width; ++x)
10322 {
10323 if (raw_p)
10324 {
10325 if ((x & 7) == 0)
10326 c = *p++;
10327 g = c & 0x80;
10328 c <<= 1;
10329 }
10330 else
10331 g = pbm_scan_number (&p, end);
10332
10333 XPutPixel (ximg, x, y, g ? fg : bg);
10334 }
10335 }
10336 else
10337 {
10338 for (y = 0; y < height; ++y)
10339 for (x = 0; x < width; ++x)
10340 {
10341 int r, g, b;
10342
10343 if (type == PBM_GRAY)
10344 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
10345 else if (raw_p)
10346 {
10347 r = *p++;
10348 g = *p++;
10349 b = *p++;
10350 }
10351 else
10352 {
10353 r = pbm_scan_number (&p, end);
10354 g = pbm_scan_number (&p, end);
10355 b = pbm_scan_number (&p, end);
10356 }
10357
10358 if (r < 0 || g < 0 || b < 0)
10359 {
10360 x_destroy_x_image (ximg);
10361 image_error ("Invalid pixel value in image `%s'",
10362 img->spec, Qnil);
10363 goto error;
10364 }
10365
10366 /* RGB values are now in the range 0..max_color_idx.
10367 Scale this to the range 0..0xff supported by W32. */
10368 r = (int) ((double) r * 255 / max_color_idx);
10369 g = (int) ((double) g * 255 / max_color_idx);
10370 b = (int) ((double) b * 255 / max_color_idx);
10371 XPutPixel (ximg, x, y,
10372#if 0 /* TODO: color tables. */
10373 lookup_rgb_color (f, r, g, b));
10374#else
10375 PALETTERGB (r, g, b));
10376#endif
10377 }
10378 }
10379
10380#if 0 /* TODO: color tables. */
10381 /* Store in IMG->colors the colors allocated for the image, and
10382 free the color table. */
10383 img->colors = colors_in_color_table (&img->ncolors);
10384 free_color_table ();
10385#endif
10386 /* Maybe fill in the background field while we have ximg handy. */
10387 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10388 IMAGE_BACKGROUND (img, f, ximg);
10389
10390 /* Put the image into a pixmap. */
10391 x_put_x_image (f, ximg, img->pixmap, width, height);
10392 x_destroy_x_image (ximg);
10393
10394 img->width = width;
10395 img->height = height;
10396
10397 UNGCPRO;
10398 xfree (contents);
10399 return 1;
10400}
10401
10402
10403/***********************************************************************
10404 PNG
10405 ***********************************************************************/
10406
10407#if HAVE_PNG
10408
10409#include <png.h>
10410
10411/* Function prototypes. */
10412
10413static int png_image_p P_ ((Lisp_Object object));
10414static int png_load P_ ((struct frame *f, struct image *img));
10415
10416/* The symbol `png' identifying images of this type. */
10417
10418Lisp_Object Qpng;
10419
10420/* Indices of image specification fields in png_format, below. */
10421
10422enum png_keyword_index
10423{
10424 PNG_TYPE,
10425 PNG_DATA,
10426 PNG_FILE,
10427 PNG_ASCENT,
10428 PNG_MARGIN,
10429 PNG_RELIEF,
10430 PNG_ALGORITHM,
10431 PNG_HEURISTIC_MASK,
10432 PNG_MASK,
10433 PNG_BACKGROUND,
10434 PNG_LAST
10435};
10436
10437/* Vector of image_keyword structures describing the format
10438 of valid user-defined image specifications. */
10439
10440static struct image_keyword png_format[PNG_LAST] =
10441{
10442 {":type", IMAGE_SYMBOL_VALUE, 1},
10443 {":data", IMAGE_STRING_VALUE, 0},
10444 {":file", IMAGE_STRING_VALUE, 0},
10445 {":ascent", IMAGE_ASCENT_VALUE, 0},
10446 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
10447 {":relief", IMAGE_INTEGER_VALUE, 0},
10448 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10449 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10450 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
10451 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
10452};
10453
10454/* Structure describing the image type `png'. */
10455
10456static struct image_type png_type =
10457{
10458 &Qpng,
10459 png_image_p,
10460 png_load,
10461 x_clear_image,
10462 NULL
10463};
10464
10465/* PNG library details. */
10466
10467DEF_IMGLIB_FN (png_get_io_ptr);
10468DEF_IMGLIB_FN (png_check_sig);
10469DEF_IMGLIB_FN (png_create_read_struct);
10470DEF_IMGLIB_FN (png_create_info_struct);
10471DEF_IMGLIB_FN (png_destroy_read_struct);
10472DEF_IMGLIB_FN (png_set_read_fn);
10473DEF_IMGLIB_FN (png_init_io);
10474DEF_IMGLIB_FN (png_set_sig_bytes);
10475DEF_IMGLIB_FN (png_read_info);
10476DEF_IMGLIB_FN (png_get_IHDR);
10477DEF_IMGLIB_FN (png_get_valid);
10478DEF_IMGLIB_FN (png_set_strip_16);
10479DEF_IMGLIB_FN (png_set_expand);
10480DEF_IMGLIB_FN (png_set_gray_to_rgb);
10481DEF_IMGLIB_FN (png_set_background);
10482DEF_IMGLIB_FN (png_get_bKGD);
10483DEF_IMGLIB_FN (png_read_update_info);
10484DEF_IMGLIB_FN (png_get_channels);
10485DEF_IMGLIB_FN (png_get_rowbytes);
10486DEF_IMGLIB_FN (png_read_image);
10487DEF_IMGLIB_FN (png_read_end);
10488DEF_IMGLIB_FN (png_error);
10489
10490static int
10491init_png_functions (library)
10492 HMODULE library;
10493{
10494 LOAD_IMGLIB_FN (library, png_get_io_ptr);
10495 LOAD_IMGLIB_FN (library, png_check_sig);
10496 LOAD_IMGLIB_FN (library, png_create_read_struct);
10497 LOAD_IMGLIB_FN (library, png_create_info_struct);
10498 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
10499 LOAD_IMGLIB_FN (library, png_set_read_fn);
10500 LOAD_IMGLIB_FN (library, png_init_io);
10501 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
10502 LOAD_IMGLIB_FN (library, png_read_info);
10503 LOAD_IMGLIB_FN (library, png_get_IHDR);
10504 LOAD_IMGLIB_FN (library, png_get_valid);
10505 LOAD_IMGLIB_FN (library, png_set_strip_16);
10506 LOAD_IMGLIB_FN (library, png_set_expand);
10507 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
10508 LOAD_IMGLIB_FN (library, png_set_background);
10509 LOAD_IMGLIB_FN (library, png_get_bKGD);
10510 LOAD_IMGLIB_FN (library, png_read_update_info);
10511 LOAD_IMGLIB_FN (library, png_get_channels);
10512 LOAD_IMGLIB_FN (library, png_get_rowbytes);
10513 LOAD_IMGLIB_FN (library, png_read_image);
10514 LOAD_IMGLIB_FN (library, png_read_end);
10515 LOAD_IMGLIB_FN (library, png_error);
10516 return 1;
10517}
10518
10519/* Return non-zero if OBJECT is a valid PNG image specification. */
10520
10521static int
10522png_image_p (object)
10523 Lisp_Object object;
10524{
10525 struct image_keyword fmt[PNG_LAST];
10526 bcopy (png_format, fmt, sizeof fmt);
10527
10528 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
10529 return 0;
10530
10531 /* Must specify either the :data or :file keyword. */
10532 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
10533}
10534
10535
10536/* Error and warning handlers installed when the PNG library
10537 is initialized. */
10538
10539static void
10540my_png_error (png_ptr, msg)
10541 png_struct *png_ptr;
10542 char *msg;
10543{
10544 xassert (png_ptr != NULL);
10545 image_error ("PNG error: %s", build_string (msg), Qnil);
10546 longjmp (png_ptr->jmpbuf, 1);
10547}
10548
10549
10550static void
10551my_png_warning (png_ptr, msg)
10552 png_struct *png_ptr;
10553 char *msg;
10554{
10555 xassert (png_ptr != NULL);
10556 image_error ("PNG warning: %s", build_string (msg), Qnil);
10557}
10558
10559/* Memory source for PNG decoding. */
10560
10561struct png_memory_storage
10562{
10563 unsigned char *bytes; /* The data */
10564 size_t len; /* How big is it? */
10565 int index; /* Where are we? */
10566};
10567
10568
10569/* Function set as reader function when reading PNG image from memory.
10570 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
10571 bytes from the input to DATA. */
10572
10573static void
10574png_read_from_memory (png_ptr, data, length)
10575 png_structp png_ptr;
10576 png_bytep data;
10577 png_size_t length;
10578{
10579 struct png_memory_storage *tbr
10580 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
10581
10582 if (length > tbr->len - tbr->index)
10583 fn_png_error (png_ptr, "Read error");
10584
10585 bcopy (tbr->bytes + tbr->index, data, length);
10586 tbr->index = tbr->index + length;
10587}
10588
10589/* Load PNG image IMG for use on frame F. Value is non-zero if
10590 successful. */
10591
10592static int
10593png_load (f, img)
10594 struct frame *f;
10595 struct image *img;
10596{
10597 Lisp_Object file, specified_file;
10598 Lisp_Object specified_data;
10599 int x, y, i;
10600 XImage *ximg, *mask_img = NULL;
10601 struct gcpro gcpro1;
10602 png_struct *png_ptr = NULL;
10603 png_info *info_ptr = NULL, *end_info = NULL;
10604 FILE *volatile fp = NULL;
10605 png_byte sig[8];
10606 png_byte * volatile pixels = NULL;
10607 png_byte ** volatile rows = NULL;
10608 png_uint_32 width, height;
10609 int bit_depth, color_type, interlace_type;
10610 png_byte channels;
10611 png_uint_32 row_bytes;
10612 int transparent_p;
10613 double screen_gamma, image_gamma;
10614 int intent;
10615 struct png_memory_storage tbr; /* Data to be read */
10616
10617 /* Find out what file to load. */
10618 specified_file = image_spec_value (img->spec, QCfile, NULL);
10619 specified_data = image_spec_value (img->spec, QCdata, NULL);
10620 file = Qnil;
10621 GCPRO1 (file);
10622
10623 if (NILP (specified_data))
10624 {
10625 file = x_find_image_file (specified_file);
10626 if (!STRINGP (file))
10627 {
10628 image_error ("Cannot find image file `%s'", specified_file, Qnil);
10629 UNGCPRO;
10630 return 0;
10631 }
10632
10633 /* Open the image file. */
10634 fp = fopen (SDATA (file), "rb");
10635 if (!fp)
10636 {
10637 image_error ("Cannot open image file `%s'", file, Qnil);
10638 UNGCPRO;
10639 fclose (fp);
10640 return 0;
10641 }
10642
10643 /* Check PNG signature. */
10644 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
10645 || !fn_png_check_sig (sig, sizeof sig))
10646 {
10647 image_error ("Not a PNG file: `%s'", file, Qnil);
10648 UNGCPRO;
10649 fclose (fp);
10650 return 0;
10651 }
10652 }
10653 else
10654 {
10655 /* Read from memory. */
10656 tbr.bytes = SDATA (specified_data);
10657 tbr.len = SBYTES (specified_data);
10658 tbr.index = 0;
10659
10660 /* Check PNG signature. */
10661 if (tbr.len < sizeof sig
10662 || !fn_png_check_sig (tbr.bytes, sizeof sig))
10663 {
10664 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
10665 UNGCPRO;
10666 return 0;
10667 }
10668
10669 /* Need to skip past the signature. */
10670 tbr.bytes += sizeof (sig);
10671 }
10672
10673 /* Initialize read and info structs for PNG lib. */
10674 png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
10675 my_png_error, my_png_warning);
10676 if (!png_ptr)
10677 {
10678 if (fp) fclose (fp);
10679 UNGCPRO;
10680 return 0;
10681 }
10682
10683 info_ptr = fn_png_create_info_struct (png_ptr);
10684 if (!info_ptr)
10685 {
10686 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
10687 if (fp) fclose (fp);
10688 UNGCPRO;
10689 return 0;
10690 }
10691
10692 end_info = fn_png_create_info_struct (png_ptr);
10693 if (!end_info)
10694 {
10695 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
10696 if (fp) fclose (fp);
10697 UNGCPRO;
10698 return 0;
10699 }
10700
10701 /* Set error jump-back. We come back here when the PNG library
10702 detects an error. */
10703 if (setjmp (png_ptr->jmpbuf))
10704 {
10705 error:
10706 if (png_ptr)
10707 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
10708 xfree (pixels);
10709 xfree (rows);
10710 if (fp) fclose (fp);
10711 UNGCPRO;
10712 return 0;
10713 }
10714
10715 /* Read image info. */
10716 if (!NILP (specified_data))
10717 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
10718 else
10719 fn_png_init_io (png_ptr, fp);
10720
10721 fn_png_set_sig_bytes (png_ptr, sizeof sig);
10722 fn_png_read_info (png_ptr, info_ptr);
10723 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
10724 &interlace_type, NULL, NULL);
10725
10726 /* If image contains simply transparency data, we prefer to
10727 construct a clipping mask. */
10728 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
10729 transparent_p = 1;
10730 else
10731 transparent_p = 0;
10732
10733 /* This function is easier to write if we only have to handle
10734 one data format: RGB or RGBA with 8 bits per channel. Let's
10735 transform other formats into that format. */
10736
10737 /* Strip more than 8 bits per channel. */
10738 if (bit_depth == 16)
10739 fn_png_set_strip_16 (png_ptr);
10740
10741 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
10742 if available. */
10743 fn_png_set_expand (png_ptr);
10744
10745 /* Convert grayscale images to RGB. */
10746 if (color_type == PNG_COLOR_TYPE_GRAY
10747 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
10748 fn_png_set_gray_to_rgb (png_ptr);
10749
10750 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
10751
10752#if 0 /* Avoid double gamma correction for PNG images. */
10753 /* Tell the PNG lib to handle gamma correction for us. */
10754#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
10755 if (png_get_sRGB (png_ptr, info_ptr, &intent))
10756 /* The libpng documentation says this is right in this case. */
10757 png_set_gamma (png_ptr, screen_gamma, 0.45455);
10758 else
10759#endif
10760 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
10761 /* Image contains gamma information. */
10762 png_set_gamma (png_ptr, screen_gamma, image_gamma);
10763 else
10764 /* Use the standard default for the image gamma. */
10765 png_set_gamma (png_ptr, screen_gamma, 0.45455);
10766#endif /* if 0 */
10767
10768 /* Handle alpha channel by combining the image with a background
10769 color. Do this only if a real alpha channel is supplied. For
10770 simple transparency, we prefer a clipping mask. */
10771 if (!transparent_p)
10772 {
10773 png_color_16 *image_bg;
10774 Lisp_Object specified_bg
10775 = image_spec_value (img->spec, QCbackground, NULL);
10776
10777 if (STRINGP (specified_bg))
10778 /* The user specified `:background', use that. */
10779 {
10780 COLORREF color;
10781 if (w32_defined_color (f, SDATA (specified_bg), &color, 0))
10782 {
10783 png_color_16 user_bg;
10784
10785 bzero (&user_bg, sizeof user_bg);
10786 user_bg.red = 256 * GetRValue (color);
10787 user_bg.green = 256 * GetGValue (color);
10788 user_bg.blue = 256 * GetBValue (color);
10789
10790 fn_png_set_background (png_ptr, &user_bg,
10791 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
10792 }
10793 }
10794 else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
10795 /* Image contains a background color with which to
10796 combine the image. */
10797 fn_png_set_background (png_ptr, image_bg,
10798 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
10799 else
10800 {
10801 /* Image does not contain a background color with which
10802 to combine the image data via an alpha channel. Use
10803 the frame's background instead. */
10804 COLORREF color;
10805 png_color_16 frame_background;
10806 color = FRAME_BACKGROUND_PIXEL (f);
10807#if 0 /* TODO : Colormap support. */
10808 Colormap cmap;
10809
10810 cmap = FRAME_X_COLORMAP (f);
10811 x_query_color (f, &color);
10812#endif
10813
10814 bzero (&frame_background, sizeof frame_background);
10815 frame_background.red = 256 * GetRValue (color);
10816 frame_background.green = 256 * GetGValue (color);
10817 frame_background.blue = 256 * GetBValue (color);
10818
10819 fn_png_set_background (png_ptr, &frame_background,
10820 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
10821 }
10822 }
10823
10824 /* Update info structure. */
10825 fn_png_read_update_info (png_ptr, info_ptr);
10826
10827 /* Get number of channels. Valid values are 1 for grayscale images
10828 and images with a palette, 2 for grayscale images with transparency
10829 information (alpha channel), 3 for RGB images, and 4 for RGB
10830 images with alpha channel, i.e. RGBA. If conversions above were
10831 sufficient we should only have 3 or 4 channels here. */
10832 channels = fn_png_get_channels (png_ptr, info_ptr);
10833 xassert (channels == 3 || channels == 4);
10834
10835 /* Number of bytes needed for one row of the image. */
10836 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
10837
10838 /* Allocate memory for the image. */
10839 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
10840 rows = (png_byte **) xmalloc (height * sizeof *rows);
10841 for (i = 0; i < height; ++i)
10842 rows[i] = pixels + i * row_bytes;
10843
10844 /* Read the entire image. */
10845 fn_png_read_image (png_ptr, rows);
10846 fn_png_read_end (png_ptr, info_ptr);
10847 if (fp)
10848 {
10849 fclose (fp);
10850 fp = NULL;
10851 }
10852
10853 /* Create the X image and pixmap. */
10854 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
10855 &img->pixmap))
10856 goto error;
10857
10858 /* Create an image and pixmap serving as mask if the PNG image
10859 contains an alpha channel. */
10860 if (channels == 4
10861 && !transparent_p
10862 && !x_create_x_image_and_pixmap (f, width, height, 1,
10863 &mask_img, &img->mask))
10864 {
10865 x_destroy_x_image (ximg);
10866 DeleteObject (img->pixmap);
10867 img->pixmap = 0;
10868 goto error;
10869 }
10870 /* Fill the X image and mask from PNG data. */
10871#if 0 /* TODO: Color tables. */
10872 init_color_table ();
10873#endif
10874
10875 for (y = 0; y < height; ++y)
10876 {
10877 png_byte *p = rows[y];
10878
10879 for (x = 0; x < width; ++x)
10880 {
10881 unsigned r, g, b;
10882
10883 r = *p++;
10884 g = *p++;
10885 b = *p++;
10886#if 0 /* TODO: Color tables. */
10887 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
10888#else
10889 XPutPixel (ximg, x, y, PALETTERGB (r, g, b));
10890#endif
10891 /* An alpha channel, aka mask channel, associates variable
10892 transparency with an image. Where other image formats
10893 support binary transparency---fully transparent or fully
10894 opaque---PNG allows up to 254 levels of partial transparency.
10895 The PNG library implements partial transparency by combining
10896 the image with a specified background color.
10897
10898 I'm not sure how to handle this here nicely: because the
10899 background on which the image is displayed may change, for
10900 real alpha channel support, it would be necessary to create
10901 a new image for each possible background.
10902
10903 What I'm doing now is that a mask is created if we have
10904 boolean transparency information. Otherwise I'm using
10905 the frame's background color to combine the image with. */
10906
10907 if (channels == 4)
10908 {
10909 if (mask_img)
10910 XPutPixel (mask_img, x, y, *p > 0);
10911 ++p;
10912 }
10913 }
10914 }
10915
10916 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
10917 /* Set IMG's background color from the PNG image, unless the user
10918 overrode it. */
10919 {
10920 png_color_16 *bg;
10921 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
10922 {
10923#if 0 /* TODO: Color tables. */
10924 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
10925#else
10926 img->background = PALETTERGB (bg->red / 256, bg->green / 256,
10927 bg->blue / 256);
10928#endif
10929 img->background_valid = 1;
10930 }
10931 }
10932
10933#if 0 /* TODO: Color tables. */
10934 /* Remember colors allocated for this image. */
10935 img->colors = colors_in_color_table (&img->ncolors);
10936 free_color_table ();
10937#endif
10938
10939 /* Clean up. */
10940 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
10941 xfree (rows);
10942 xfree (pixels);
10943
10944 img->width = width;
10945 img->height = height;
10946
10947 /* Maybe fill in the background field while we have ximg handy. */
10948 IMAGE_BACKGROUND (img, f, ximg);
10949
10950 /* Put the image into the pixmap, then free the X image and its buffer. */
10951 x_put_x_image (f, ximg, img->pixmap, width, height);
10952 x_destroy_x_image (ximg);
10953
10954 /* Same for the mask. */
10955 if (mask_img)
10956 {
10957 /* Fill in the background_transparent field while we have the mask
10958 handy. */
10959 image_background_transparent (img, f, mask_img);
10960
10961 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
10962 x_destroy_x_image (mask_img);
10963 }
10964
10965 UNGCPRO;
10966 return 1;
10967}
10968
10969#endif /* HAVE_PNG != 0 */
10970
10971
10972
10973/***********************************************************************
10974 JPEG
10975 ***********************************************************************/
10976
10977#if HAVE_JPEG
10978
10979/* Work around a warning about HAVE_STDLIB_H being redefined in
10980 jconfig.h. */
10981#ifdef HAVE_STDLIB_H
10982#define HAVE_STDLIB_H_1
10983#undef HAVE_STDLIB_H
10984#endif /* HAVE_STLIB_H */
10985
10986#include <jpeglib.h>
10987#include <jerror.h>
10988#include <setjmp.h>
10989
10990#ifdef HAVE_STLIB_H_1
10991#define HAVE_STDLIB_H 1
10992#endif
10993
10994static int jpeg_image_p P_ ((Lisp_Object object));
10995static int jpeg_load P_ ((struct frame *f, struct image *img));
10996
10997/* The symbol `jpeg' identifying images of this type. */
10998
10999Lisp_Object Qjpeg;
11000
11001/* Indices of image specification fields in gs_format, below. */
11002
11003enum jpeg_keyword_index
11004{
11005 JPEG_TYPE,
11006 JPEG_DATA,
11007 JPEG_FILE,
11008 JPEG_ASCENT,
11009 JPEG_MARGIN,
11010 JPEG_RELIEF,
11011 JPEG_ALGORITHM,
11012 JPEG_HEURISTIC_MASK,
11013 JPEG_MASK,
11014 JPEG_BACKGROUND,
11015 JPEG_LAST
11016};
11017
11018/* Vector of image_keyword structures describing the format
11019 of valid user-defined image specifications. */
11020
11021static struct image_keyword jpeg_format[JPEG_LAST] =
11022{
11023 {":type", IMAGE_SYMBOL_VALUE, 1},
11024 {":data", IMAGE_STRING_VALUE, 0},
11025 {":file", IMAGE_STRING_VALUE, 0},
11026 {":ascent", IMAGE_ASCENT_VALUE, 0},
11027 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11028 {":relief", IMAGE_INTEGER_VALUE, 0},
11029 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11030 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11031 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11032 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11033};
11034
11035/* Structure describing the image type `jpeg'. */
11036
11037static struct image_type jpeg_type =
11038{
11039 &Qjpeg,
11040 jpeg_image_p,
11041 jpeg_load,
11042 x_clear_image,
11043 NULL
11044};
11045
11046
11047/* JPEG library details. */
11048DEF_IMGLIB_FN (jpeg_CreateDecompress);
11049DEF_IMGLIB_FN (jpeg_start_decompress);
11050DEF_IMGLIB_FN (jpeg_finish_decompress);
11051DEF_IMGLIB_FN (jpeg_destroy_decompress);
11052DEF_IMGLIB_FN (jpeg_read_header);
11053DEF_IMGLIB_FN (jpeg_read_scanlines);
11054DEF_IMGLIB_FN (jpeg_stdio_src);
11055DEF_IMGLIB_FN (jpeg_std_error);
11056DEF_IMGLIB_FN (jpeg_resync_to_restart);
11057
11058static int
11059init_jpeg_functions (library)
11060 HMODULE library;
11061{
11062 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
11063 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
11064 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
11065 LOAD_IMGLIB_FN (library, jpeg_read_header);
11066 LOAD_IMGLIB_FN (library, jpeg_stdio_src);
11067 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
11068 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
11069 LOAD_IMGLIB_FN (library, jpeg_std_error);
11070 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
11071 return 1;
11072}
11073
11074/* Wrapper since we can't directly assign the function pointer
11075 to another function pointer that was declared more completely easily. */
11076static boolean
11077jpeg_resync_to_restart_wrapper(cinfo, desired)
11078 j_decompress_ptr cinfo;
11079 int desired;
11080{
11081 return fn_jpeg_resync_to_restart (cinfo, desired);
11082}
11083
11084
11085/* Return non-zero if OBJECT is a valid JPEG image specification. */
11086
11087static int
11088jpeg_image_p (object)
11089 Lisp_Object object;
11090{
11091 struct image_keyword fmt[JPEG_LAST];
11092
11093 bcopy (jpeg_format, fmt, sizeof fmt);
11094
11095 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
11096 return 0;
11097
11098 /* Must specify either the :data or :file keyword. */
11099 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
11100}
11101
11102
11103struct my_jpeg_error_mgr
11104{
11105 struct jpeg_error_mgr pub;
11106 jmp_buf setjmp_buffer;
11107};
11108
11109
11110static void
11111my_error_exit (cinfo)
11112 j_common_ptr cinfo;
11113{
11114 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
11115 longjmp (mgr->setjmp_buffer, 1);
11116}
11117
11118
11119/* Init source method for JPEG data source manager. Called by
11120 jpeg_read_header() before any data is actually read. See
11121 libjpeg.doc from the JPEG lib distribution. */
11122
11123static void
11124our_init_source (cinfo)
11125 j_decompress_ptr cinfo;
11126{
11127}
11128
11129
11130/* Fill input buffer method for JPEG data source manager. Called
11131 whenever more data is needed. We read the whole image in one step,
11132 so this only adds a fake end of input marker at the end. */
11133
11134static boolean
11135our_fill_input_buffer (cinfo)
11136 j_decompress_ptr cinfo;
11137{
11138 /* Insert a fake EOI marker. */
11139 struct jpeg_source_mgr *src = cinfo->src;
11140 static JOCTET buffer[2];
11141
11142 buffer[0] = (JOCTET) 0xFF;
11143 buffer[1] = (JOCTET) JPEG_EOI;
11144
11145 src->next_input_byte = buffer;
11146 src->bytes_in_buffer = 2;
11147 return TRUE;
11148}
11149
11150
11151/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
11152 is the JPEG data source manager. */
11153
11154static void
11155our_skip_input_data (cinfo, num_bytes)
11156 j_decompress_ptr cinfo;
11157 long num_bytes;
11158{
11159 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
11160
11161 if (src)
11162 {
11163 if (num_bytes > src->bytes_in_buffer)
11164 ERREXIT (cinfo, JERR_INPUT_EOF);
11165
11166 src->bytes_in_buffer -= num_bytes;
11167 src->next_input_byte += num_bytes;
11168 }
11169}
11170
11171
11172/* Method to terminate data source. Called by
11173 jpeg_finish_decompress() after all data has been processed. */
11174
11175static void
11176our_term_source (cinfo)
11177 j_decompress_ptr cinfo;
11178{
11179}
11180
11181
11182/* Set up the JPEG lib for reading an image from DATA which contains
11183 LEN bytes. CINFO is the decompression info structure created for
11184 reading the image. */
11185
11186static void
11187jpeg_memory_src (cinfo, data, len)
11188 j_decompress_ptr cinfo;
11189 JOCTET *data;
11190 unsigned int len;
11191{
11192 struct jpeg_source_mgr *src;
11193
11194 if (cinfo->src == NULL)
11195 {
11196 /* First time for this JPEG object? */
11197 cinfo->src = (struct jpeg_source_mgr *)
11198 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
11199 sizeof (struct jpeg_source_mgr));
11200 src = (struct jpeg_source_mgr *) cinfo->src;
11201 src->next_input_byte = data;
11202 }
11203
11204 src = (struct jpeg_source_mgr *) cinfo->src;
11205 src->init_source = our_init_source;
11206 src->fill_input_buffer = our_fill_input_buffer;
11207 src->skip_input_data = our_skip_input_data;
11208 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
11209 src->term_source = our_term_source;
11210 src->bytes_in_buffer = len;
11211 src->next_input_byte = data;
11212}
11213
11214
11215/* Load image IMG for use on frame F. Patterned after example.c
11216 from the JPEG lib. */
11217
11218static int
11219jpeg_load (f, img)
11220 struct frame *f;
11221 struct image *img;
11222{
11223 struct jpeg_decompress_struct cinfo;
11224 struct my_jpeg_error_mgr mgr;
11225 Lisp_Object file, specified_file;
11226 Lisp_Object specified_data;
11227 FILE * volatile fp = NULL;
11228 JSAMPARRAY buffer;
11229 int row_stride, x, y;
11230 XImage *ximg = NULL;
11231 int rc;
11232 unsigned long *colors;
11233 int width, height;
11234 struct gcpro gcpro1;
11235
11236 /* Open the JPEG file. */
11237 specified_file = image_spec_value (img->spec, QCfile, NULL);
11238 specified_data = image_spec_value (img->spec, QCdata, NULL);
11239 file = Qnil;
11240 GCPRO1 (file);
11241
11242 if (NILP (specified_data))
11243 {
11244 file = x_find_image_file (specified_file);
11245 if (!STRINGP (file))
11246 {
11247 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11248 UNGCPRO;
11249 return 0;
11250 }
11251
11252 fp = fopen (SDATA (file), "rb");
11253 if (fp == NULL)
11254 {
11255 image_error ("Cannot open `%s'", file, Qnil);
11256 UNGCPRO;
11257 return 0;
11258 }
11259 }
11260
11261 /* Customize libjpeg's error handling to call my_error_exit when an
11262 error is detected. This function will perform a longjmp. */
11263 cinfo.err = fn_jpeg_std_error (&mgr.pub);
11264 mgr.pub.error_exit = my_error_exit;
11265
11266 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
11267 {
11268 if (rc == 1)
11269 {
11270 /* Called from my_error_exit. Display a JPEG error. */
11271 char buffer[JMSG_LENGTH_MAX];
11272 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
11273 image_error ("Error reading JPEG image `%s': %s", img->spec,
11274 build_string (buffer));
11275 }
11276
11277 /* Close the input file and destroy the JPEG object. */
11278 if (fp)
11279 fclose ((FILE *) fp);
11280 fn_jpeg_destroy_decompress (&cinfo);
11281
11282 /* If we already have an XImage, free that. */
11283 x_destroy_x_image (ximg);
11284
11285 /* Free pixmap and colors. */
11286 x_clear_image (f, img);
11287
11288 UNGCPRO;
11289 return 0;
11290 }
11291
11292 /* Create the JPEG decompression object. Let it read from fp.
11293 Read the JPEG image header. */
11294 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
11295
11296 if (NILP (specified_data))
11297 fn_jpeg_stdio_src (&cinfo, (FILE *) fp);
11298 else
11299 jpeg_memory_src (&cinfo, SDATA (specified_data),
11300 SBYTES (specified_data));
11301
11302 fn_jpeg_read_header (&cinfo, TRUE);
11303
11304 /* Customize decompression so that color quantization will be used.
11305 Start decompression. */
11306 cinfo.quantize_colors = TRUE;
11307 fn_jpeg_start_decompress (&cinfo);
11308 width = img->width = cinfo.output_width;
11309 height = img->height = cinfo.output_height;
11310
11311 /* Create X image and pixmap. */
11312 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
11313 longjmp (mgr.setjmp_buffer, 2);
11314
11315 /* Allocate colors. When color quantization is used,
11316 cinfo.actual_number_of_colors has been set with the number of
11317 colors generated, and cinfo.colormap is a two-dimensional array
11318 of color indices in the range 0..cinfo.actual_number_of_colors.
11319 No more than 255 colors will be generated. */
11320 {
11321 int i, ir, ig, ib;
11322
11323 if (cinfo.out_color_components > 2)
11324 ir = 0, ig = 1, ib = 2;
11325 else if (cinfo.out_color_components > 1)
11326 ir = 0, ig = 1, ib = 0;
11327 else
11328 ir = 0, ig = 0, ib = 0;
11329
11330#if 0 /* TODO: Color tables. */
11331 /* Use the color table mechanism because it handles colors that
11332 cannot be allocated nicely. Such colors will be replaced with
11333 a default color, and we don't have to care about which colors
11334 can be freed safely, and which can't. */
11335 init_color_table ();
11336#endif
11337 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
11338 * sizeof *colors);
11339
11340 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
11341 {
11342 int r = cinfo.colormap[ir][i];
11343 int g = cinfo.colormap[ig][i];
11344 int b = cinfo.colormap[ib][i];
11345#if 0 /* TODO: Color tables. */
11346 colors[i] = lookup_rgb_color (f, r, g, b);
11347#else
11348 colors[i] = PALETTERGB (r, g, b);
11349#endif
11350 }
11351
11352#if 0 /* TODO: Color tables. */
11353 /* Remember those colors actually allocated. */
11354 img->colors = colors_in_color_table (&img->ncolors);
11355 free_color_table ();
11356#endif
11357 }
11358
11359 /* Read pixels. */
11360 row_stride = width * cinfo.output_components;
11361 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
11362 row_stride, 1);
11363 for (y = 0; y < height; ++y)
11364 {
11365 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
11366 for (x = 0; x < cinfo.output_width; ++x)
11367 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
11368 }
11369
11370 /* Clean up. */
11371 fn_jpeg_finish_decompress (&cinfo);
11372 fn_jpeg_destroy_decompress (&cinfo);
11373 if (fp)
11374 fclose ((FILE *) fp);
11375
11376 /* Maybe fill in the background field while we have ximg handy. */
11377 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11378 IMAGE_BACKGROUND (img, f, ximg);
11379
11380 /* Put the image into the pixmap. */
11381 x_put_x_image (f, ximg, img->pixmap, width, height);
11382 x_destroy_x_image (ximg);
11383 UNGCPRO;
11384 return 1;
11385}
11386
11387#endif /* HAVE_JPEG */
11388
11389
11390
11391/***********************************************************************
11392 TIFF
11393 ***********************************************************************/
11394
11395#if HAVE_TIFF
11396
11397#include <tiffio.h>
11398
11399static int tiff_image_p P_ ((Lisp_Object object));
11400static int tiff_load P_ ((struct frame *f, struct image *img));
11401
11402/* The symbol `tiff' identifying images of this type. */
11403
11404Lisp_Object Qtiff;
11405
11406/* Indices of image specification fields in tiff_format, below. */
11407
11408enum tiff_keyword_index
11409{
11410 TIFF_TYPE,
11411 TIFF_DATA,
11412 TIFF_FILE,
11413 TIFF_ASCENT,
11414 TIFF_MARGIN,
11415 TIFF_RELIEF,
11416 TIFF_ALGORITHM,
11417 TIFF_HEURISTIC_MASK,
11418 TIFF_MASK,
11419 TIFF_BACKGROUND,
11420 TIFF_LAST
11421};
11422
11423/* Vector of image_keyword structures describing the format
11424 of valid user-defined image specifications. */
11425
11426static struct image_keyword tiff_format[TIFF_LAST] =
11427{
11428 {":type", IMAGE_SYMBOL_VALUE, 1},
11429 {":data", IMAGE_STRING_VALUE, 0},
11430 {":file", IMAGE_STRING_VALUE, 0},
11431 {":ascent", IMAGE_ASCENT_VALUE, 0},
11432 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11433 {":relief", IMAGE_INTEGER_VALUE, 0},
11434 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11435 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11436 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11437 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11438};
11439
11440/* Structure describing the image type `tiff'. */
11441
11442static struct image_type tiff_type =
11443{
11444 &Qtiff,
11445 tiff_image_p,
11446 tiff_load,
11447 x_clear_image,
11448 NULL
11449};
11450
11451/* TIFF library details. */
11452DEF_IMGLIB_FN (TIFFSetErrorHandler);
11453DEF_IMGLIB_FN (TIFFSetWarningHandler);
11454DEF_IMGLIB_FN (TIFFOpen);
11455DEF_IMGLIB_FN (TIFFClientOpen);
11456DEF_IMGLIB_FN (TIFFGetField);
11457DEF_IMGLIB_FN (TIFFReadRGBAImage);
11458DEF_IMGLIB_FN (TIFFClose);
11459
11460static int
11461init_tiff_functions (library)
11462 HMODULE library;
11463{
11464 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
11465 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
11466 LOAD_IMGLIB_FN (library, TIFFOpen);
11467 LOAD_IMGLIB_FN (library, TIFFClientOpen);
11468 LOAD_IMGLIB_FN (library, TIFFGetField);
11469 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
11470 LOAD_IMGLIB_FN (library, TIFFClose);
11471 return 1;
11472}
11473
11474/* Return non-zero if OBJECT is a valid TIFF image specification. */
11475
11476static int
11477tiff_image_p (object)
11478 Lisp_Object object;
11479{
11480 struct image_keyword fmt[TIFF_LAST];
11481 bcopy (tiff_format, fmt, sizeof fmt);
11482
11483 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
11484 return 0;
11485
11486 /* Must specify either the :data or :file keyword. */
11487 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
11488}
11489
11490
11491/* Reading from a memory buffer for TIFF images Based on the PNG
11492 memory source, but we have to provide a lot of extra functions.
11493 Blah.
11494
11495 We really only need to implement read and seek, but I am not
11496 convinced that the TIFF library is smart enough not to destroy
11497 itself if we only hand it the function pointers we need to
11498 override. */
11499
11500typedef struct
11501{
11502 unsigned char *bytes;
11503 size_t len;
11504 int index;
11505}
11506tiff_memory_source;
11507
11508static size_t
11509tiff_read_from_memory (data, buf, size)
11510 thandle_t data;
11511 tdata_t buf;
11512 tsize_t size;
11513{
11514 tiff_memory_source *src = (tiff_memory_source *) data;
11515
11516 if (size > src->len - src->index)
11517 return (size_t) -1;
11518 bcopy (src->bytes + src->index, buf, size);
11519 src->index += size;
11520 return size;
11521}
11522
11523static size_t
11524tiff_write_from_memory (data, buf, size)
11525 thandle_t data;
11526 tdata_t buf;
11527 tsize_t size;
11528{
11529 return (size_t) -1;
11530}
11531
11532static toff_t
11533tiff_seek_in_memory (data, off, whence)
11534 thandle_t data;
11535 toff_t off;
11536 int whence;
11537{
11538 tiff_memory_source *src = (tiff_memory_source *) data;
11539 int idx;
11540
11541 switch (whence)
11542 {
11543 case SEEK_SET: /* Go from beginning of source. */
11544 idx = off;
11545 break;
11546
11547 case SEEK_END: /* Go from end of source. */
11548 idx = src->len + off;
11549 break;
11550
11551 case SEEK_CUR: /* Go from current position. */
11552 idx = src->index + off;
11553 break;
11554
11555 default: /* Invalid `whence'. */
11556 return -1;
11557 }
11558
11559 if (idx > src->len || idx < 0)
11560 return -1;
11561
11562 src->index = idx;
11563 return src->index;
11564}
11565
11566static int
11567tiff_close_memory (data)
11568 thandle_t data;
11569{
11570 /* NOOP */
11571 return 0;
11572}
11573
11574static int
11575tiff_mmap_memory (data, pbase, psize)
11576 thandle_t data;
11577 tdata_t *pbase;
11578 toff_t *psize;
11579{
11580 /* It is already _IN_ memory. */
11581 return 0;
11582}
11583
11584static void
11585tiff_unmap_memory (data, base, size)
11586 thandle_t data;
11587 tdata_t base;
11588 toff_t size;
11589{
11590 /* We don't need to do this. */
11591}
11592
11593static toff_t
11594tiff_size_of_memory (data)
11595 thandle_t data;
11596{
11597 return ((tiff_memory_source *) data)->len;
11598}
11599
11600
11601static void
11602tiff_error_handler (title, format, ap)
11603 const char *title, *format;
11604 va_list ap;
11605{
11606 char buf[512];
11607 int len;
11608
11609 len = sprintf (buf, "TIFF error: %s ", title);
11610 vsprintf (buf + len, format, ap);
11611 add_to_log (buf, Qnil, Qnil);
11612}
11613
11614
11615static void
11616tiff_warning_handler (title, format, ap)
11617 const char *title, *format;
11618 va_list ap;
11619{
11620 char buf[512];
11621 int len;
11622
11623 len = sprintf (buf, "TIFF warning: %s ", title);
11624 vsprintf (buf + len, format, ap);
11625 add_to_log (buf, Qnil, Qnil);
11626}
11627
11628
11629/* Load TIFF image IMG for use on frame F. Value is non-zero if
11630 successful. */
11631
11632static int
11633tiff_load (f, img)
11634 struct frame *f;
11635 struct image *img;
11636{
11637 Lisp_Object file, specified_file;
11638 Lisp_Object specified_data;
11639 TIFF *tiff;
11640 int width, height, x, y;
11641 uint32 *buf;
11642 int rc;
11643 XImage *ximg;
11644 struct gcpro gcpro1;
11645 tiff_memory_source memsrc;
11646
11647 specified_file = image_spec_value (img->spec, QCfile, NULL);
11648 specified_data = image_spec_value (img->spec, QCdata, NULL);
11649 file = Qnil;
11650 GCPRO1 (file);
11651
11652 fn_TIFFSetErrorHandler (tiff_error_handler);
11653 fn_TIFFSetWarningHandler (tiff_warning_handler);
11654
11655 if (NILP (specified_data))
11656 {
11657 /* Read from a file */
11658 file = x_find_image_file (specified_file);
11659 if (!STRINGP (file))
11660 {
11661 image_error ("Cannot find image file `%s'", file, Qnil);
11662 UNGCPRO;
11663 return 0;
11664 }
11665
11666 /* Try to open the image file. */
11667 tiff = fn_TIFFOpen (SDATA (file), "r");
11668 if (tiff == NULL)
11669 {
11670 image_error ("Cannot open `%s'", file, Qnil);
11671 UNGCPRO;
11672 return 0;
11673 }
11674 }
11675 else
11676 {
11677 /* Memory source! */
11678 memsrc.bytes = SDATA (specified_data);
11679 memsrc.len = SBYTES (specified_data);
11680 memsrc.index = 0;
11681
11682 tiff = fn_TIFFClientOpen ("memory_source", "r", &memsrc,
11683 (TIFFReadWriteProc) tiff_read_from_memory,
11684 (TIFFReadWriteProc) tiff_write_from_memory,
11685 tiff_seek_in_memory,
11686 tiff_close_memory,
11687 tiff_size_of_memory,
11688 tiff_mmap_memory,
11689 tiff_unmap_memory);
11690
11691 if (!tiff)
11692 {
11693 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
11694 UNGCPRO;
11695 return 0;
11696 }
11697 }
11698
11699 /* Get width and height of the image, and allocate a raster buffer
11700 of width x height 32-bit values. */
11701 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
11702 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
11703 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
11704
11705 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
11706 fn_TIFFClose (tiff);
11707 if (!rc)
11708 {
11709 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
11710 xfree (buf);
11711 UNGCPRO;
11712 return 0;
11713 }
11714
11715 /* Create the X image and pixmap. */
11716 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
11717 {
11718 xfree (buf);
11719 UNGCPRO;
11720 return 0;
11721 }
11722
11723#if 0 /* TODO: Color tables. */
11724 /* Initialize the color table. */
11725 init_color_table ();
11726#endif
11727
11728 /* Process the pixel raster. Origin is in the lower-left corner. */
11729 for (y = 0; y < height; ++y)
11730 {
11731 uint32 *row = buf + y * width;
11732
11733 for (x = 0; x < width; ++x)
11734 {
11735 uint32 abgr = row[x];
11736 int r = TIFFGetR (abgr);
11737 int g = TIFFGetG (abgr);
11738 int b = TIFFGetB (abgr);
11739#if 0 /* TODO: Color tables. */
11740 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
11741#else
11742 XPutPixel (ximg, x, height - 1 - y, PALETTERGB (r, g, b));
11743#endif
11744 }
11745 }
11746
11747#if 0 /* TODO: Color tables. */
11748 /* Remember the colors allocated for the image. Free the color table. */
11749 img->colors = colors_in_color_table (&img->ncolors);
11750 free_color_table ();
11751#endif
11752
11753 img->width = width;
11754 img->height = height;
11755
11756 /* Maybe fill in the background field while we have ximg handy. */
11757 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
11758 IMAGE_BACKGROUND (img, f, ximg);
11759
11760 /* Put the image into the pixmap, then free the X image and its buffer. */
11761 x_put_x_image (f, ximg, img->pixmap, width, height);
11762 x_destroy_x_image (ximg);
11763 xfree (buf);
11764
11765 UNGCPRO;
11766 return 1;
11767}
11768
11769#endif /* HAVE_TIFF != 0 */
11770
11771
11772
11773/***********************************************************************
11774 GIF
11775 ***********************************************************************/
11776
11777#if HAVE_GIF
11778
11779#define DrawText gif_DrawText
11780#include <gif_lib.h>
11781#undef DrawText
11782
11783static int gif_image_p P_ ((Lisp_Object object));
11784static int gif_load P_ ((struct frame *f, struct image *img));
11785
11786/* The symbol `gif' identifying images of this type. */
11787
11788Lisp_Object Qgif;
11789
11790/* Indices of image specification fields in gif_format, below. */
11791
11792enum gif_keyword_index
11793{
11794 GIF_TYPE,
11795 GIF_DATA,
11796 GIF_FILE,
11797 GIF_ASCENT,
11798 GIF_MARGIN,
11799 GIF_RELIEF,
11800 GIF_ALGORITHM,
11801 GIF_HEURISTIC_MASK,
11802 GIF_MASK,
11803 GIF_IMAGE,
11804 GIF_BACKGROUND,
11805 GIF_LAST
11806};
11807
11808/* Vector of image_keyword structures describing the format
11809 of valid user-defined image specifications. */
11810
11811static struct image_keyword gif_format[GIF_LAST] =
11812{
11813 {":type", IMAGE_SYMBOL_VALUE, 1},
11814 {":data", IMAGE_STRING_VALUE, 0},
11815 {":file", IMAGE_STRING_VALUE, 0},
11816 {":ascent", IMAGE_ASCENT_VALUE, 0},
11817 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
11818 {":relief", IMAGE_INTEGER_VALUE, 0},
11819 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11820 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11821 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
11822 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
11823 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
11824};
11825
11826/* Structure describing the image type `gif'. */
11827
11828static struct image_type gif_type =
11829{
11830 &Qgif,
11831 gif_image_p,
11832 gif_load,
11833 x_clear_image,
11834 NULL
11835};
11836
11837
11838/* GIF library details. */
11839DEF_IMGLIB_FN (DGifCloseFile);
11840DEF_IMGLIB_FN (DGifSlurp);
11841DEF_IMGLIB_FN (DGifOpen);
11842DEF_IMGLIB_FN (DGifOpenFileName);
11843
11844static int
11845init_gif_functions (library)
11846 HMODULE library;
11847{
11848 LOAD_IMGLIB_FN (library, DGifCloseFile);
11849 LOAD_IMGLIB_FN (library, DGifSlurp);
11850 LOAD_IMGLIB_FN (library, DGifOpen);
11851 LOAD_IMGLIB_FN (library, DGifOpenFileName);
11852 return 1;
11853}
11854
11855
11856/* Return non-zero if OBJECT is a valid GIF image specification. */
11857
11858static int
11859gif_image_p (object)
11860 Lisp_Object object;
11861{
11862 struct image_keyword fmt[GIF_LAST];
11863 bcopy (gif_format, fmt, sizeof fmt);
11864
11865 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
11866 return 0;
11867
11868 /* Must specify either the :data or :file keyword. */
11869 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
11870}
11871
11872/* Reading a GIF image from memory
11873 Based on the PNG memory stuff to a certain extent. */
11874
11875typedef struct
11876{
11877 unsigned char *bytes;
11878 size_t len;
11879 int index;
11880}
11881gif_memory_source;
11882
11883/* Make the current memory source available to gif_read_from_memory.
11884 It's done this way because not all versions of libungif support
11885 a UserData field in the GifFileType structure. */
11886static gif_memory_source *current_gif_memory_src;
11887
11888static int
11889gif_read_from_memory (file, buf, len)
11890 GifFileType *file;
11891 GifByteType *buf;
11892 int len;
11893{
11894 gif_memory_source *src = current_gif_memory_src;
11895
11896 if (len > src->len - src->index)
11897 return -1;
11898
11899 bcopy (src->bytes + src->index, buf, len);
11900 src->index += len;
11901 return len;
11902}
11903
11904
11905/* Load GIF image IMG for use on frame F. Value is non-zero if
11906 successful. */
11907
11908static int
11909gif_load (f, img)
11910 struct frame *f;
11911 struct image *img;
11912{
11913 Lisp_Object file, specified_file;
11914 Lisp_Object specified_data;
11915 int rc, width, height, x, y, i;
11916 XImage *ximg;
11917 ColorMapObject *gif_color_map;
11918 unsigned long pixel_colors[256];
11919 GifFileType *gif;
11920 struct gcpro gcpro1;
11921 Lisp_Object image;
11922 int ino, image_left, image_top, image_width, image_height;
11923 gif_memory_source memsrc;
11924 unsigned char *raster;
11925
11926 specified_file = image_spec_value (img->spec, QCfile, NULL);
11927 specified_data = image_spec_value (img->spec, QCdata, NULL);
11928 file = Qnil;
11929 GCPRO1 (file);
11930
11931 if (NILP (specified_data))
11932 {
11933 file = x_find_image_file (specified_file);
11934 if (!STRINGP (file))
11935 {
11936 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11937 UNGCPRO;
11938 return 0;
11939 }
11940
11941 /* Open the GIF file. */
11942 gif = fn_DGifOpenFileName (SDATA (file));
11943 if (gif == NULL)
11944 {
11945 image_error ("Cannot open `%s'", file, Qnil);
11946 UNGCPRO;
11947 return 0;
11948 }
11949 }
11950 else
11951 {
11952 /* Read from memory! */
11953 current_gif_memory_src = &memsrc;
11954 memsrc.bytes = SDATA (specified_data);
11955 memsrc.len = SBYTES (specified_data);
11956 memsrc.index = 0;
11957
11958 gif = fn_DGifOpen(&memsrc, gif_read_from_memory);
11959 if (!gif)
11960 {
11961 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
11962 UNGCPRO;
11963 return 0;
11964 }
11965 }
11966
11967 /* Read entire contents. */
11968 rc = fn_DGifSlurp (gif);
11969 if (rc == GIF_ERROR)
11970 {
11971 image_error ("Error reading `%s'", img->spec, Qnil);
11972 fn_DGifCloseFile (gif);
11973 UNGCPRO;
11974 return 0;
11975 }
11976
11977 image = image_spec_value (img->spec, QCindex, NULL);
11978 ino = INTEGERP (image) ? XFASTINT (image) : 0;
11979 if (ino >= gif->ImageCount)
11980 {
11981 image_error ("Invalid image number `%s' in image `%s'",
11982 image, img->spec);
11983 fn_DGifCloseFile (gif);
11984 UNGCPRO;
11985 return 0;
11986 }
11987
11988 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
11989 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
11990
11991 /* Create the X image and pixmap. */
11992 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
11993 {
11994 fn_DGifCloseFile (gif);
11995 UNGCPRO;
11996 return 0;
11997 }
11998
11999 /* Allocate colors. */
12000 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
12001 if (!gif_color_map)
12002 gif_color_map = gif->SColorMap;
12003#if 0 /* TODO: Color tables */
12004 init_color_table ();
12005#endif
12006 bzero (pixel_colors, sizeof pixel_colors);
12007
12008 for (i = 0; i < gif_color_map->ColorCount; ++i)
12009 {
12010 int r = gif_color_map->Colors[i].Red;
12011 int g = gif_color_map->Colors[i].Green;
12012 int b = gif_color_map->Colors[i].Blue;
12013#if 0 /* TODO: Color tables */
12014 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
12015#else
12016 pixel_colors[i] = PALETTERGB (r, g, b);
12017#endif
12018 }
12019
12020#if 0 /* TODO: Color tables */
12021 img->colors = colors_in_color_table (&img->ncolors);
12022 free_color_table ();
12023#endif
12024
12025 /* Clear the part of the screen image that are not covered by
12026 the image from the GIF file. Full animated GIF support
12027 requires more than can be done here (see the gif89 spec,
12028 disposal methods). Let's simply assume that the part
12029 not covered by a sub-image is in the frame's background color. */
12030 image_top = gif->SavedImages[ino].ImageDesc.Top;
12031 image_left = gif->SavedImages[ino].ImageDesc.Left;
12032 image_width = gif->SavedImages[ino].ImageDesc.Width;
12033 image_height = gif->SavedImages[ino].ImageDesc.Height;
12034
12035 for (y = 0; y < image_top; ++y)
12036 for (x = 0; x < width; ++x)
12037 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12038
12039 for (y = image_top + image_height; y < height; ++y)
12040 for (x = 0; x < width; ++x)
12041 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12042
12043 for (y = image_top; y < image_top + image_height; ++y)
12044 {
12045 for (x = 0; x < image_left; ++x)
12046 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12047 for (x = image_left + image_width; x < width; ++x)
12048 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
12049 }
12050
12051 /* Read the GIF image into the X image. We use a local variable
12052 `raster' here because RasterBits below is a char *, and invites
12053 problems with bytes >= 0x80. */
12054 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
12055
12056 if (gif->SavedImages[ino].ImageDesc.Interlace)
12057 {
12058 static int interlace_start[] = {0, 4, 2, 1};
12059 static int interlace_increment[] = {8, 8, 4, 2};
12060 int pass;
12061 int row = interlace_start[0];
12062
12063 pass = 0;
12064
12065 for (y = 0; y < image_height; y++)
12066 {
12067 if (row >= image_height)
12068 {
12069 row = interlace_start[++pass];
12070 while (row >= image_height)
12071 row = interlace_start[++pass];
12072 }
12073
12074 for (x = 0; x < image_width; x++)
12075 {
12076 int i = raster[(y * image_width) + x];
12077 XPutPixel (ximg, x + image_left, row + image_top,
12078 pixel_colors[i]);
12079 }
12080
12081 row += interlace_increment[pass];
12082 }
12083 }
12084 else
12085 {
12086 for (y = 0; y < image_height; ++y)
12087 for (x = 0; x < image_width; ++x)
12088 {
12089 int i = raster[y* image_width + x];
12090 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
12091 }
12092 }
12093
12094 fn_DGifCloseFile (gif);
12095
12096 /* Maybe fill in the background field while we have ximg handy. */
12097 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
12098 IMAGE_BACKGROUND (img, f, ximg);
12099
12100 /* Put the image into the pixmap, then free the X image and its buffer. */
12101 x_put_x_image (f, ximg, img->pixmap, width, height);
12102 x_destroy_x_image (ximg);
12103
12104 UNGCPRO;
12105 return 1;
12106}
12107
12108#endif /* HAVE_GIF != 0 */
12109
12110
12111
12112/***********************************************************************
12113 Ghostscript
12114 ***********************************************************************/
12115
12116Lisp_Object Qpostscript;
12117
12118/* Keyword symbols. */
12119
12120Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
12121
12122#ifdef HAVE_GHOSTSCRIPT
12123static int gs_image_p P_ ((Lisp_Object object));
12124static int gs_load P_ ((struct frame *f, struct image *img));
12125static void gs_clear_image P_ ((struct frame *f, struct image *img));
12126
12127/* The symbol `postscript' identifying images of this type. */
12128
12129/* Keyword symbols. */
12130
12131Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
12132
12133/* Indices of image specification fields in gs_format, below. */
12134
12135enum gs_keyword_index
12136{
12137 GS_TYPE,
12138 GS_PT_WIDTH,
12139 GS_PT_HEIGHT,
12140 GS_FILE,
12141 GS_LOADER,
12142 GS_BOUNDING_BOX,
12143 GS_ASCENT,
12144 GS_MARGIN,
12145 GS_RELIEF,
12146 GS_ALGORITHM,
12147 GS_HEURISTIC_MASK,
12148 GS_MASK,
12149 GS_BACKGROUND,
12150 GS_LAST
12151};
12152
12153/* Vector of image_keyword structures describing the format
12154 of valid user-defined image specifications. */
12155
12156static struct image_keyword gs_format[GS_LAST] =
12157{
12158 {":type", IMAGE_SYMBOL_VALUE, 1},
12159 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12160 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
12161 {":file", IMAGE_STRING_VALUE, 1},
12162 {":loader", IMAGE_FUNCTION_VALUE, 0},
12163 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
12164 {":ascent", IMAGE_ASCENT_VALUE, 0},
12165 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
12166 {":relief", IMAGE_INTEGER_VALUE, 0},
12167 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12168 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12169 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
12170 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
12171};
12172
12173/* Structure describing the image type `ghostscript'. */
12174
12175static struct image_type gs_type =
12176{
12177 &Qpostscript,
12178 gs_image_p,
12179 gs_load,
12180 gs_clear_image,
12181 NULL
12182};
12183
12184
12185/* Free X resources of Ghostscript image IMG which is used on frame F. */
12186
12187static void
12188gs_clear_image (f, img)
12189 struct frame *f;
12190 struct image *img;
12191{
12192 /* IMG->data.ptr_val may contain a recorded colormap. */
12193 xfree (img->data.ptr_val);
12194 x_clear_image (f, img);
12195}
12196
12197
12198/* Return non-zero if OBJECT is a valid Ghostscript image
12199 specification. */
12200
12201static int
12202gs_image_p (object)
12203 Lisp_Object object;
12204{
12205 struct image_keyword fmt[GS_LAST];
12206 Lisp_Object tem;
12207 int i;
12208
12209 bcopy (gs_format, fmt, sizeof fmt);
12210
12211 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
12212 return 0;
12213
12214 /* Bounding box must be a list or vector containing 4 integers. */
12215 tem = fmt[GS_BOUNDING_BOX].value;
12216 if (CONSP (tem))
12217 {
12218 for (i = 0; i < 4; ++i, tem = XCDR (tem))
12219 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
12220 return 0;
12221 if (!NILP (tem))
12222 return 0;
12223 }
12224 else if (VECTORP (tem))
12225 {
12226 if (XVECTOR (tem)->size != 4)
12227 return 0;
12228 for (i = 0; i < 4; ++i)
12229 if (!INTEGERP (XVECTOR (tem)->contents[i]))
12230 return 0;
12231 }
12232 else
12233 return 0;
12234
12235 return 1;
12236}
12237
12238
12239/* Load Ghostscript image IMG for use on frame F. Value is non-zero
12240 if successful. */
12241
12242static int
12243gs_load (f, img)
12244 struct frame *f;
12245 struct image *img;
12246{
12247 char buffer[100];
12248 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
12249 struct gcpro gcpro1, gcpro2;
12250 Lisp_Object frame;
12251 double in_width, in_height;
12252 Lisp_Object pixel_colors = Qnil;
12253
12254 /* Compute pixel size of pixmap needed from the given size in the
12255 image specification. Sizes in the specification are in pt. 1 pt
12256 = 1/72 in, xdpi and ydpi are stored in the frame's X display
12257 info. */
12258 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
12259 in_width = XFASTINT (pt_width) / 72.0;
12260 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
12261 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
12262 in_height = XFASTINT (pt_height) / 72.0;
12263 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
12264
12265 /* Create the pixmap. */
12266 BLOCK_INPUT;
12267 xassert (img->pixmap == 0);
12268 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
12269 img->width, img->height,
12270 one_w32_display_info.n_cbits);
12271 UNBLOCK_INPUT;
12272
12273 if (!img->pixmap)
12274 {
12275 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
12276 return 0;
12277 }
12278
12279 /* Call the loader to fill the pixmap. It returns a process object
12280 if successful. We do not record_unwind_protect here because
12281 other places in redisplay like calling window scroll functions
12282 don't either. Let the Lisp loader use `unwind-protect' instead. */
12283 GCPRO2 (window_and_pixmap_id, pixel_colors);
12284
12285 sprintf (buffer, "%lu %lu",
12286 (unsigned long) FRAME_W32_WINDOW (f),
12287 (unsigned long) img->pixmap);
12288 window_and_pixmap_id = build_string (buffer);
12289
12290 sprintf (buffer, "%lu %lu",
12291 FRAME_FOREGROUND_PIXEL (f),
12292 FRAME_BACKGROUND_PIXEL (f));
12293 pixel_colors = build_string (buffer);
12294
12295 XSETFRAME (frame, f);
12296 loader = image_spec_value (img->spec, QCloader, NULL);
12297 if (NILP (loader))
12298 loader = intern ("gs-load-image");
12299
12300 img->data.lisp_val = call6 (loader, frame, img->spec,
12301 make_number (img->width),
12302 make_number (img->height),
12303 window_and_pixmap_id,
12304 pixel_colors);
12305 UNGCPRO;
12306 return PROCESSP (img->data.lisp_val);
12307}
12308
12309
12310/* Kill the Ghostscript process that was started to fill PIXMAP on
12311 frame F. Called from XTread_socket when receiving an event
12312 telling Emacs that Ghostscript has finished drawing. */
12313
12314void
12315x_kill_gs_process (pixmap, f)
12316 Pixmap pixmap;
12317 struct frame *f;
12318{
12319 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
12320 int class, i;
12321 struct image *img;
12322
12323 /* Find the image containing PIXMAP. */
12324 for (i = 0; i < c->used; ++i)
12325 if (c->images[i]->pixmap == pixmap)
12326 break;
12327
12328 /* Should someone in between have cleared the image cache, for
12329 instance, give up. */
12330 if (i == c->used)
12331 return;
12332
12333 /* Kill the GS process. We should have found PIXMAP in the image
12334 cache and its image should contain a process object. */
12335 img = c->images[i];
12336 xassert (PROCESSP (img->data.lisp_val));
12337 Fkill_process (img->data.lisp_val, Qnil);
12338 img->data.lisp_val = Qnil;
12339
12340 /* On displays with a mutable colormap, figure out the colors
12341 allocated for the image by looking at the pixels of an XImage for
12342 img->pixmap. */
12343 class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
12344 if (class != StaticColor && class != StaticGray && class != TrueColor)
12345 {
12346 XImage *ximg;
12347
12348 BLOCK_INPUT;
12349
12350 /* Try to get an XImage for img->pixmep. */
12351 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
12352 0, 0, img->width, img->height, ~0, ZPixmap);
12353 if (ximg)
12354 {
12355 int x, y;
12356
12357 /* Initialize the color table. */
12358 init_color_table ();
12359
12360 /* For each pixel of the image, look its color up in the
12361 color table. After having done so, the color table will
12362 contain an entry for each color used by the image. */
12363 for (y = 0; y < img->height; ++y)
12364 for (x = 0; x < img->width; ++x)
12365 {
12366 unsigned long pixel = XGetPixel (ximg, x, y);
12367 lookup_pixel_color (f, pixel);
12368 }
12369
12370 /* Record colors in the image. Free color table and XImage. */
12371 img->colors = colors_in_color_table (&img->ncolors);
12372 free_color_table ();
12373 XDestroyImage (ximg);
12374
12375#if 0 /* This doesn't seem to be the case. If we free the colors
12376 here, we get a BadAccess later in x_clear_image when
12377 freeing the colors. */
12378 /* We have allocated colors once, but Ghostscript has also
12379 allocated colors on behalf of us. So, to get the
12380 reference counts right, free them once. */
12381 if (img->ncolors)
12382 x_free_colors (FRAME_W32_DISPLAY (f), cmap,
12383 img->colors, img->ncolors, 0);
12384#endif
12385 }
12386 else
12387 image_error ("Cannot get X image of `%s'; colors will not be freed",
12388 img->spec, Qnil);
12389
12390 UNBLOCK_INPUT;
12391 }
12392
12393 /* Now that we have the pixmap, compute mask and transform the
12394 image if requested. */
12395 BLOCK_INPUT;
12396 postprocess_image (f, img);
12397 UNBLOCK_INPUT;
12398}
12399
12400#endif /* HAVE_GHOSTSCRIPT */
12401 6707
12402 6708
12403/*********************************************************************** 6709/***********************************************************************
@@ -14066,8 +8372,6 @@ syms_of_w32fns ()
14066 staticpro (&Qsuppress_icon); 8372 staticpro (&Qsuppress_icon);
14067 Qundefined_color = intern ("undefined-color"); 8373 Qundefined_color = intern ("undefined-color");
14068 staticpro (&Qundefined_color); 8374 staticpro (&Qundefined_color);
14069 Qcenter = intern ("center");
14070 staticpro (&Qcenter);
14071 Qcancel_timer = intern ("cancel-timer"); 8375 Qcancel_timer = intern ("cancel-timer");
14072 staticpro (&Qcancel_timer); 8376 staticpro (&Qcancel_timer);
14073 8377
@@ -14092,21 +8396,6 @@ syms_of_w32fns ()
14092 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky); 8396 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
14093 8397
14094 8398
14095 Qlaplace = intern ("laplace");
14096 staticpro (&Qlaplace);
14097 Qemboss = intern ("emboss");
14098 staticpro (&Qemboss);
14099 Qedge_detection = intern ("edge-detection");
14100 staticpro (&Qedge_detection);
14101 Qheuristic = intern ("heuristic");
14102 staticpro (&Qheuristic);
14103 QCmatrix = intern (":matrix");
14104 staticpro (&QCmatrix);
14105 QCcolor_adjustment = intern (":color-adjustment");
14106 staticpro (&QCcolor_adjustment);
14107 QCmask = intern (":mask");
14108 staticpro (&QCmask);
14109
14110 Fput (Qundefined_color, Qerror_conditions, 8399 Fput (Qundefined_color, Qerror_conditions,
14111 Fcons (Qundefined_color, Fcons (Qerror, Qnil))); 8400 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
14112 Fput (Qundefined_color, Qerror_message, 8401 Fput (Qundefined_color, Qerror_message,
@@ -14237,10 +8526,6 @@ If this variable is non-nil, Emacs will pass them on, allowing the
14237system to handle them. */); 8526system to handle them. */);
14238 w32_pass_extra_mouse_buttons_to_system = 0; 8527 w32_pass_extra_mouse_buttons_to_system = 0;
14239 8528
14240 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
14241 doc: /* List of directories to search for window system bitmap files. */);
14242 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
14243
14244 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape, 8529 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
14245 doc: /* The shape of the pointer when over text. 8530 doc: /* The shape of the pointer when over text.
14246Changing the value does not affect existing frames 8531Changing the value does not affect existing frames
@@ -14307,13 +8592,6 @@ such a font. This is especially effective for such large fonts as
14307Chinese, Japanese, and Korean. */); 8592Chinese, Japanese, and Korean. */);
14308 Vx_pixel_size_width_font_regexp = Qnil; 8593 Vx_pixel_size_width_font_regexp = Qnil;
14309 8594
14310 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
14311 doc: /* Time after which cached images are removed from the cache.
14312When an image has not been displayed this many seconds, remove it
14313from the image cache. Value must be an integer or nil with nil
14314meaning don't clear the cache. */);
14315 Vimage_cache_eviction_delay = make_number (30 * 60);
14316
14317 DEFVAR_LISP ("w32-bdf-filename-alist", 8595 DEFVAR_LISP ("w32-bdf-filename-alist",
14318 &Vw32_bdf_filename_alist, 8596 &Vw32_bdf_filename_alist,
14319 doc: /* List of bdf fonts and their corresponding filenames. */); 8597 doc: /* List of bdf fonts and their corresponding filenames. */);
@@ -14478,64 +8756,6 @@ versions of Windows) characters. */);
14478 set_frame_fontset_func = x_set_font; 8756 set_frame_fontset_func = x_set_font;
14479 check_window_system_func = check_w32; 8757 check_window_system_func = check_w32;
14480 8758
14481 /* Images. */
14482 Qxbm = intern ("xbm");
14483 staticpro (&Qxbm);
14484 QCconversion = intern (":conversion");
14485 staticpro (&QCconversion);
14486 QCheuristic_mask = intern (":heuristic-mask");
14487 staticpro (&QCheuristic_mask);
14488 QCcolor_symbols = intern (":color-symbols");
14489 staticpro (&QCcolor_symbols);
14490 QCascent = intern (":ascent");
14491 staticpro (&QCascent);
14492 QCmargin = intern (":margin");
14493 staticpro (&QCmargin);
14494 QCrelief = intern (":relief");
14495 staticpro (&QCrelief);
14496 Qpostscript = intern ("postscript");
14497 staticpro (&Qpostscript);
14498 QCloader = intern (":loader");
14499 staticpro (&QCloader);
14500 QCbounding_box = intern (":bounding-box");
14501 staticpro (&QCbounding_box);
14502 QCpt_width = intern (":pt-width");
14503 staticpro (&QCpt_width);
14504 QCpt_height = intern (":pt-height");
14505 staticpro (&QCpt_height);
14506 QCindex = intern (":index");
14507 staticpro (&QCindex);
14508 Qpbm = intern ("pbm");
14509 staticpro (&Qpbm);
14510
14511#if HAVE_XPM
14512 Qxpm = intern ("xpm");
14513 staticpro (&Qxpm);
14514#endif
14515
14516#if HAVE_JPEG
14517 Qjpeg = intern ("jpeg");
14518 staticpro (&Qjpeg);
14519#endif
14520
14521#if HAVE_TIFF
14522 Qtiff = intern ("tiff");
14523 staticpro (&Qtiff);
14524#endif
14525
14526#if HAVE_GIF
14527 Qgif = intern ("gif");
14528 staticpro (&Qgif);
14529#endif
14530
14531#if HAVE_PNG
14532 Qpng = intern ("png");
14533 staticpro (&Qpng);
14534#endif
14535
14536 defsubr (&Sclear_image_cache);
14537 defsubr (&Simage_size);
14538 defsubr (&Simage_mask_p);
14539 8759
14540 hourglass_atimer = NULL; 8760 hourglass_atimer = NULL;
14541 hourglass_shown_p = 0; 8761 hourglass_shown_p = 0;
@@ -14575,84 +8795,6 @@ void globals_of_w32fns ()
14575 GetProcAddress (user32_lib, "GetClipboardSequenceNumber"); 8795 GetProcAddress (user32_lib, "GetClipboardSequenceNumber");
14576} 8796}
14577 8797
14578/* Initialize image types. Based on which libraries are available. */
14579static void
14580init_external_image_libraries ()
14581{
14582 HINSTANCE library;
14583
14584#if HAVE_XPM
14585 if ((library = LoadLibrary ("libXpm.dll")))
14586 {
14587 if (init_xpm_functions (library))
14588 define_image_type (&xpm_type);
14589 }
14590
14591#endif
14592
14593#if HAVE_JPEG
14594 /* Try loading jpeg library under probable names. */
14595 if ((library = LoadLibrary ("libjpeg.dll"))
14596 || (library = LoadLibrary ("jpeg-62.dll"))
14597 || (library = LoadLibrary ("jpeg.dll")))
14598 {
14599 if (init_jpeg_functions (library))
14600 define_image_type (&jpeg_type);
14601 }
14602#endif
14603
14604#if HAVE_TIFF
14605 if (library = LoadLibrary ("libtiff.dll"))
14606 {
14607 if (init_tiff_functions (library))
14608 define_image_type (&tiff_type);
14609 }
14610#endif
14611
14612#if HAVE_GIF
14613 if (library = LoadLibrary ("libungif.dll"))
14614 {
14615 if (init_gif_functions (library))
14616 define_image_type (&gif_type);
14617 }
14618#endif
14619
14620#if HAVE_PNG
14621 /* Ensure zlib is loaded. Try debug version first. */
14622 if (!LoadLibrary ("zlibd.dll"))
14623 LoadLibrary ("zlib.dll");
14624
14625 /* Try loading libpng under probable names. */
14626 if ((library = LoadLibrary ("libpng13d.dll"))
14627 || (library = LoadLibrary ("libpng13.dll"))
14628 || (library = LoadLibrary ("libpng12d.dll"))
14629 || (library = LoadLibrary ("libpng12.dll"))
14630 || (library = LoadLibrary ("libpng.dll")))
14631 {
14632 if (init_png_functions (library))
14633 define_image_type (&png_type);
14634 }
14635#endif
14636}
14637
14638void
14639init_xfns ()
14640{
14641 image_types = NULL;
14642 Vimage_types = Qnil;
14643
14644 define_image_type (&pbm_type);
14645 define_image_type (&xbm_type);
14646
14647#if 0 /* TODO : Ghostscript support for W32 */
14648 define_image_type (&gs_type);
14649#endif
14650
14651 /* Image types that rely on external libraries are loaded dynamically
14652 if the library is available. */
14653 init_external_image_libraries ();
14654}
14655
14656#undef abort 8798#undef abort
14657 8799
14658void 8800void