comparison src/glyphs-x.c @ 207:e45d5e7c476e r20-4b2

Import from CVS: tag r20-4b2
author cvs
date Mon, 13 Aug 2007 10:03:52 +0200
parents 169c0442b401
children 41ff10fd062f
comparison
equal deleted inserted replaced
206:d3e9274cbc4e 207:e45d5e7c476e
35 Improved GIF/JPEG support added by Bill Perry for 19.14 35 Improved GIF/JPEG support added by Bill Perry for 19.14
36 Cleanup/simplification of error handling by Ben Wing for 19.14 36 Cleanup/simplification of error handling by Ben Wing for 19.14
37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14 37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
38 38
39 TODO: 39 TODO:
40 TIFF Support 40 ImageMagick support
41 Loadable module support for images
42 Convert images.el to C and stick it in here? 41 Convert images.el to C and stick it in here?
43 */ 42 */
44 43
45 #include <config.h> 44 #include <config.h>
46 #include "lisp.h" 45 #include "lisp.h"
55 #include "insdel.h" 54 #include "insdel.h"
56 #include "opaque.h" 55 #include "opaque.h"
57 56
58 #include "sysfile.h" 57 #include "sysfile.h"
59 58
60 #ifdef HAVE_PNG 59 #ifdef HAVE_IMAGEMAGICK
61 #ifdef __cplusplus 60 #define HAVE_X11_MAGICK_IMAGE_H
62 extern "C" { 61 #endif /* HAVE_IMAGEMAGICK */
63 #endif 62
64 #include <png.h> 63 #ifdef HAVE_X11_MAGICK_IMAGE_H
65 #ifdef __cplusplus 64 #include <magick.h>
66 } 65 /* #include <image.h> */
67 #endif 66 #include <assert.h>
68 #else
69 #include <setjmp.h>
70 #endif 67 #endif
71 68
72 #define LISP_DEVICE_TO_X_SCREEN(dev) \ 69 #define LISP_DEVICE_TO_X_SCREEN(dev) \
73 XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev))) 70 XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
74 71
87 #ifdef HAVE_XFACE 84 #ifdef HAVE_XFACE
88 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface); 85 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface);
89 Lisp_Object Qxface; 86 Lisp_Object Qxface;
90 #endif 87 #endif
91 88
92 #ifdef HAVE_JPEG 89 #ifdef HAVE_IMAGEMAGICK
93 DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg); 90 DEFINE_IMAGE_INSTANTIATOR_FORMAT (imagick);
94 Lisp_Object Qjpeg; 91 Lisp_Object Qimagick;
95 #endif
96
97 #ifdef HAVE_PNG
98 DEFINE_IMAGE_INSTANTIATOR_FORMAT (png);
99 Lisp_Object Qpng;
100 #endif
101
102 #ifdef HAVE_TIFF
103 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff);
104 Lisp_Object Qtiff;
105 #endif
106
107 #ifdef HAVE_GIF
108 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif);
109 Lisp_Object Qgif;
110 #endif 92 #endif
111 93
112 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); 94 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
113 Lisp_Object Qcursor_font; 95 Lisp_Object Qcursor_font;
114 96
958 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d; 940 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
959 } 941 }
960 break; 942 break;
961 943
962 case IMAGE_POINTER: 944 case IMAGE_POINTER:
963 { 945 {
964 XColor fg_color, bg_color; 946 XColor fg_color, bg_color;
965 Pixmap source; 947 Pixmap source;
966 948
967 check_pointer_sizes (scr, width, height, instantiator); 949 check_pointer_sizes (scr, width, height, instantiator);
968 950
997 979
998 default: 980 default:
999 abort (); 981 abort ();
1000 } 982 }
1001 } 983 }
1002 984
1003 static int 985 static int
1004 xbm_possible_dest_types (void) 986 xbm_possible_dest_types (void)
1005 { 987 {
1006 return 988 return
1007 IMAGE_MONO_PIXMAP_MASK | 989 IMAGE_MONO_PIXMAP_MASK |
1021 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1003 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1022 Pixmap mask = 0; 1004 Pixmap mask = 0;
1023 CONST char *gcc_may_you_rot_in_hell; 1005 CONST char *gcc_may_you_rot_in_hell;
1024 1006
1025 if (!NILP (mask_data)) 1007 if (!NILP (mask_data))
1026 { 1008 {
1027 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))), 1009 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
1028 gcc_may_you_rot_in_hell); 1010 gcc_may_you_rot_in_hell);
1029 mask = 1011 mask =
1030 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii), 1012 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1031 XINT (XCAR (mask_data)), 1013 XINT (XCAR (mask_data)),
1032 XINT (XCAR (XCDR (mask_data))), 1014 XINT (XCAR (XCDR (mask_data))),
1033 (CONST unsigned char *) 1015 (CONST unsigned char *)
1034 gcc_may_you_rot_in_hell); 1016 gcc_may_you_rot_in_hell);
1035 } 1017 }
1036 1018
1037 init_image_instance_from_xbm_inline (ii, width, height, bits, 1019 init_image_instance_from_xbm_inline (ii, width, height, bits,
1038 instantiator, pointer_fg, pointer_bg, 1020 instantiator, pointer_fg, pointer_bg,
1039 dest_mask, mask, mask_file); 1021 dest_mask, mask, mask_file);
1040 } 1022 }
1041 1023
1042 /* Instantiate method for XBM's. */ 1024 /* Instantiate method for XBM's. */
1043 1025
1044 static void 1026 static void
1045 xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 1027 xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1046 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 1028 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1047 int dest_mask, Lisp_Object domain) 1029 int dest_mask, Lisp_Object domain)
1048 { 1030 {
1049 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); 1031 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1050 CONST char *gcc_go_home; 1032 CONST char *gcc_go_home;
1051 1033
1052 assert (!NILP (data)); 1034 assert (!NILP (data));
1056 1038
1057 xbm_instantiate_1 (image_instance, instantiator, pointer_fg, 1039 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1058 pointer_bg, dest_mask, XINT (XCAR (data)), 1040 pointer_bg, dest_mask, XINT (XCAR (data)),
1059 XINT (XCAR (XCDR (data))), gcc_go_home); 1041 XINT (XCAR (XCDR (data))), gcc_go_home);
1060 } 1042 }
1061
1062
1063 #define USE_TEMP_FILES_FOR_PNG_IMAGES 1
1064
1065 #ifdef HAVE_JPEG
1066
1067 /**********************************************************************
1068 * JPEG *
1069 **********************************************************************/
1070
1071 #ifdef __cplusplus
1072 extern "C" {
1073 #endif
1074 #include <jpeglib.h>
1075 #include <jerror.h>
1076 #ifdef __cplusplus
1077 }
1078 #endif
1079
1080 /* The in-core jpeg code doesn't work, so I'm avoiding it for now. -sb */
1081 /* Late-breaking update, we're going to give it a try, I think it's */
1082 /* fixed now -sb */
1083 /*#define USE_TEMP_FILES_FOR_JPEG_IMAGES 1*/
1084 static void
1085 jpeg_validate (Lisp_Object instantiator)
1086 {
1087 file_or_data_must_be_present (instantiator);
1088 }
1089
1090 static Lisp_Object
1091 jpeg_normalize (Lisp_Object inst, Lisp_Object console_type)
1092 {
1093 return simple_image_type_normalize (inst, console_type, Qjpeg);
1094 }
1095
1096 static int
1097 jpeg_possible_dest_types (void)
1098 {
1099 return IMAGE_COLOR_PIXMAP_MASK;
1100 }
1101
1102 /* To survive the otherwise baffling complexity of making sure
1103 everything gets cleaned up in the presence of an error, we
1104 use an unwind_protect(). */
1105
1106 struct jpeg_unwind_data
1107 {
1108 Display *dpy;
1109 /* Stream that we need to close */
1110 FILE *instream;
1111 /* Object that holds state info for JPEG decoding */
1112 struct jpeg_decompress_struct *cinfo_ptr;
1113 /* Pixels to keep around while the image is active */
1114 unsigned long *pixels;
1115 int npixels;
1116 /* Client-side image structure */
1117 XImage *ximage;
1118 /* Tempfile to remove */
1119 char tempfile[50];
1120 int tempfile_needs_to_be_removed;
1121 };
1122
1123 static Lisp_Object
1124 jpeg_instantiate_unwind (Lisp_Object unwind_obj)
1125 {
1126 struct jpeg_unwind_data *data =
1127 (struct jpeg_unwind_data *) get_opaque_ptr (unwind_obj);
1128
1129 free_opaque_ptr (unwind_obj);
1130 if (data->cinfo_ptr)
1131 jpeg_destroy_decompress (data->cinfo_ptr);
1132
1133 if (data->instream)
1134 fclose (data->instream);
1135
1136 if (data->tempfile_needs_to_be_removed)
1137 unlink (data->tempfile);
1138
1139 if (data->npixels > 0)
1140 {
1141 Screen *scr = DefaultScreenOfDisplay (data->dpy);
1142 Colormap cmap = DefaultColormapOfScreen (scr);
1143 XFreeColors (data->dpy, cmap, data->pixels, data->npixels, 0L);
1144 xfree (data->pixels);
1145 }
1146
1147 if (data->ximage)
1148 {
1149 if (data->ximage->data)
1150 {
1151 xfree (data->ximage->data);
1152 data->ximage->data = 0;
1153 }
1154 XDestroyImage (data->ximage);
1155 }
1156
1157 return Qnil;
1158 }
1159
1160 /*
1161 * ERROR HANDLING:
1162 *
1163 * The JPEG library's standard error handler (jerror.c) is divided into
1164 * several "methods" which you can override individually. This lets you
1165 * adjust the behavior without duplicating a lot of code, which you might
1166 * have to update with each future release.
1167 *
1168 * Our example here shows how to override the "error_exit" method so that
1169 * control is returned to the library's caller when a fatal error occurs,
1170 * rather than calling exit() as the standard error_exit method does.
1171 *
1172 * We use C's setjmp/longjmp facility to return control. This means that the
1173 * routine which calls the JPEG library must first execute a setjmp() call to
1174 * establish the return point. We want the replacement error_exit to do a
1175 * longjmp(). But we need to make the setjmp buffer accessible to the
1176 * error_exit routine. To do this, we make a private extension of the
1177 * standard JPEG error handler object. (If we were using C++, we'd say we
1178 * were making a subclass of the regular error handler.)
1179 *
1180 * Here's the extended error handler struct:
1181 */
1182
1183 struct my_jpeg_error_mgr
1184 {
1185 struct jpeg_error_mgr pub; /* "public" fields */
1186 jmp_buf setjmp_buffer; /* for return to caller */
1187 };
1188
1189 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1190 METHODDEF(void)
1191 #else
1192 METHODDEF void
1193 #endif
1194 our_init_source (j_decompress_ptr cinfo) {
1195 }
1196
1197 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1198 METHODDEF(boolean)
1199 #else
1200 METHODDEF boolean
1201 #endif
1202 our_fill_input_buffer (j_decompress_ptr cinfo) {
1203 /* Insert a fake EOI marker */
1204 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
1205 static JOCTET buffer[2];
1206
1207 buffer[0] = (JOCTET) 0xFF;
1208 buffer[1] = (JOCTET) JPEG_EOI;
1209
1210 src->next_input_byte = buffer;
1211 src->bytes_in_buffer = 2;
1212 return TRUE;
1213 }
1214
1215 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1216 METHODDEF(void)
1217 #else
1218 METHODDEF void
1219 #endif
1220 our_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
1221 struct jpeg_source_mgr *src = NULL;
1222
1223 src = (struct jpeg_source_mgr *) cinfo->src;
1224
1225 if (!src) {
1226 return;
1227 } else if (num_bytes > src->bytes_in_buffer) {
1228 ERREXIT(cinfo, JERR_INPUT_EOF);
1229 /*NOTREACHED*/
1230 }
1231
1232 src->bytes_in_buffer -= num_bytes;
1233 src->next_input_byte += num_bytes;
1234 }
1235
1236 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1237 METHODDEF(void)
1238 #else
1239 METHODDEF void
1240 #endif
1241 our_term_source (j_decompress_ptr cinfo) {
1242 }
1243
1244 typedef struct {
1245 struct jpeg_source_mgr pub;
1246 } our_jpeg_source_mgr;
1247
1248 static void
1249 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
1250 {
1251 struct jpeg_source_mgr *src = NULL;
1252
1253 if (cinfo->src == NULL) { /* first time for this JPEG object? */
1254 cinfo->src = (struct jpeg_source_mgr *)
1255 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
1256 sizeof(our_jpeg_source_mgr));
1257 src = (struct jpeg_source_mgr *) cinfo->src;
1258 src->next_input_byte = data;
1259 }
1260 src = (struct jpeg_source_mgr *) cinfo->src;
1261 src->init_source = our_init_source;
1262 src->fill_input_buffer = our_fill_input_buffer;
1263 src->skip_input_data = our_skip_input_data;
1264 src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
1265 src->term_source = our_term_source;
1266 src->bytes_in_buffer = len;
1267 src->next_input_byte = data;
1268 }
1269
1270 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1271 METHODDEF(void)
1272 #else
1273 METHODDEF void
1274 #endif
1275 my_jpeg_error_exit (j_common_ptr cinfo)
1276 {
1277 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
1278 struct my_jpeg_error_mgr *myerr = (struct my_jpeg_error_mgr *) cinfo->err;
1279
1280 /* Return control to the setjmp point */
1281 longjmp (myerr->setjmp_buffer, 1);
1282 }
1283
1284 /* The code in this routine is based on example.c from the JPEG library
1285 source code and from gif_instantiate() */
1286 static void
1287 jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1288 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1289 int dest_mask, Lisp_Object domain)
1290 {
1291 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1292 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1293 Display *dpy;
1294 Screen *scr;
1295 /* It is OK for the unwind data to be local to this function,
1296 because the unwind-protect is always executed when this
1297 stack frame is still valid. */
1298 struct jpeg_unwind_data unwind;
1299 int speccount = specpdl_depth ();
1300
1301 /* This struct contains the JPEG decompression parameters and pointers to
1302 * working space (which is allocated as needed by the JPEG library).
1303 */
1304 struct jpeg_decompress_struct cinfo;
1305 /* We use our private extension JPEG error handler.
1306 * Note that this struct must live as long as the main JPEG parameter
1307 * struct, to avoid dangling-pointer problems.
1308 */
1309 struct my_jpeg_error_mgr jerr;
1310
1311 if (!DEVICE_X_P (XDEVICE (device)))
1312 signal_simple_error ("Not an X device", device);
1313
1314 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1315 scr = DefaultScreenOfDisplay (dpy);
1316
1317 /* Step -1: First record our unwind-protect, which will clean up after
1318 any exit, normal or not */
1319
1320 memset (&unwind, 0, sizeof (unwind));
1321 unwind.dpy = dpy;
1322 record_unwind_protect (jpeg_instantiate_unwind, make_opaque_ptr (&unwind));
1323
1324 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
1325 /* Step 0: Write out to a temp file.
1326
1327 The JPEG routines require you to read from a file unless
1328 you provide your own special input handlers, which I don't
1329 feel like doing. */
1330 {
1331 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1332
1333 assert (!NILP (data));
1334
1335 write_lisp_string_to_temp_file (data, unwind.tempfile);
1336 unwind.tempfile_needs_to_be_removed = 1;
1337
1338 /* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
1339 * requires it in order to read binary files.
1340 */
1341
1342 if ((unwind.instream = fopen (unwind.tempfile, "r")) == NULL)
1343 report_file_error ("Opening JPEG temp file",
1344 list1 (build_string (unwind.tempfile)));
1345 }
1346 #endif
1347
1348 /* Step 1: allocate and initialize JPEG decompression object */
1349
1350 /* We set up the normal JPEG error routines, then override error_exit. */
1351 cinfo.err = jpeg_std_error (&jerr.pub);
1352 jerr.pub.error_exit = my_jpeg_error_exit;
1353
1354 /* Establish the setjmp return context for my_error_exit to use. */
1355 if (setjmp (jerr.setjmp_buffer))
1356 {
1357 /* If we get here, the JPEG code has signaled an error.
1358 * We need to clean up the JPEG object, close the input file, and return.
1359 */
1360
1361 {
1362 Lisp_Object errstring;
1363 char buffer[JMSG_LENGTH_MAX];
1364
1365 /* Create the message */
1366 (*cinfo.err->format_message) ((j_common_ptr) &cinfo, buffer);
1367 errstring = build_string (buffer);
1368
1369 signal_simple_error_2 ("JPEG decoding error",
1370 errstring, instantiator);
1371 }
1372 }
1373
1374 /* Now we can initialize the JPEG decompression object. */
1375 jpeg_create_decompress (&cinfo);
1376 unwind.cinfo_ptr = &cinfo;
1377
1378 /* Step 2: specify data source (eg, a file) */
1379
1380 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
1381 jpeg_stdio_src (&cinfo, unwind.instream);
1382 #else
1383 {
1384 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1385 Extbyte *bytes;
1386 Extcount len;
1387
1388 /* #### This is a definite problem under Mule due to the amount of
1389 stack data it might allocate. Need to be able to convert and
1390 write out to a file. */
1391 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
1392 jpeg_memory_src (&cinfo, bytes, len);
1393 }
1394 #endif
1395
1396 /* Step 3: read file parameters with jpeg_read_header() */
1397
1398 jpeg_read_header (&cinfo, TRUE);
1399 /* We can ignore the return value from jpeg_read_header since
1400 * (a) suspension is not possible with the stdio data source, and
1401 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
1402 * See libjpeg.doc for more info.
1403 */
1404
1405 /* Step 4: set parameters for decompression. */
1406
1407 /* We request that the JPEG file be automatically quantized into
1408 8-bit color in case it's not already (many JPEGs are stored in
1409 24-bit color). "Two-pass quantize" means that the colormap
1410 is determined on-the-fly for this particular image rather than
1411 quantizing to a supplied colormap. We can get away with this
1412 because we then use allocate_nearest_color().
1413
1414 #### Note of course that this is not the most color-effective
1415 way of doing things -- we could quantize an image that has
1416 lots of very similar colors, and eat up the colormap with these
1417 (useless to other images) colors. Unfortunately I don't think
1418 there's any "general" way of maximizing the overall image
1419 quality of lots of images, given that we don't know the
1420 colors of the images until we come across each one. Best we
1421 could do would be various sorts of heuristics, which I don't
1422 feel like dealing with now. A better scheme would be the
1423 way things are done under MS Windows, where the colormap is
1424 dynamically adjusted for various applications; but that kind
1425 of thing would have to be provided by X, which it isn't. */
1426
1427 cinfo.quantize_colors = TRUE;
1428 cinfo.two_pass_quantize = TRUE;
1429 cinfo.colormap = NULL;
1430
1431 /* Step 5: Start decompressor */
1432
1433 jpeg_start_decompress (&cinfo);
1434 /* We can ignore the return value since suspension is not possible
1435 * with the stdio data source.
1436 */
1437
1438 /* At this point we know the size of the image and the colormap. */
1439
1440 /* Step 5.33: Allocate the colors */
1441 {
1442 int i;
1443
1444 /* Just in case the image contains out-of-range pixels, we go
1445 ahead and allocate space for all of them. */
1446 unwind.pixels = xnew_array (unsigned long, 256);
1447 unwind.npixels = cinfo.actual_number_of_colors;
1448
1449 for (i = 0; i < 256; i++)
1450 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */
1451
1452 /* Allocate pixels for the various colors. */
1453 for (i = 0; i < unwind.npixels; i++)
1454 {
1455 XColor color;
1456 int ri, gi, bi;
1457
1458 ri = 0;
1459 gi = cinfo.out_color_components > 1 ? 1 : 0;
1460 bi = cinfo.out_color_components > 2 ? 2 : 0;
1461
1462 /* Ok... apparently, an entry of cinfo.colormap can be NULL if
1463 there are no bits of that color in the image. How incredibly
1464 gross. Wouldn't it be nice to have exceptions!? */
1465 color.red = cinfo.colormap[ri] ? cinfo.colormap[ri][i] << 8 : 0;
1466 color.green = cinfo.colormap[gi] ? cinfo.colormap[gi][i] << 8 : 0;
1467 color.blue = cinfo.colormap[bi] ? cinfo.colormap[bi][i] << 8 : 0;
1468 color.flags = DoRed | DoGreen | DoBlue;
1469
1470 allocate_nearest_color (dpy, DefaultColormapOfScreen (scr), &color);
1471 unwind.pixels[i] = color.pixel;
1472 }
1473 }
1474
1475 /* Step 5.66: Create the image */
1476 {
1477 int height = cinfo.output_height;
1478 int width = cinfo.output_width;
1479 int depth;
1480 int bitmap_pad;
1481
1482 depth = DefaultDepthOfScreen (scr);
1483
1484 /* first get bitmap_pad (from XPM) */
1485 bitmap_pad = ((depth > 16) ? 32 :
1486 (depth > 8) ? 16 :
1487 8);
1488
1489 unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr),
1490 depth, ZPixmap, 0, 0, width, height,
1491 bitmap_pad, 0);
1492
1493 if (!unwind.ximage)
1494 signal_simple_error ("Unable to create X image struct", instantiator);
1495
1496 /* now that bytes_per_line must have been set properly alloc data */
1497 unwind.ximage->data =
1498 (char *) xmalloc (unwind.ximage->bytes_per_line * height);
1499 }
1500
1501 /* Step 6: Read in the data and put into image */
1502 {
1503 JSAMPARRAY row_buffer; /* Output row buffer */
1504 int row_stride; /* physical row width in output buffer */
1505
1506 /* We may need to do some setup of our own at this point before reading
1507 * the data. After jpeg_start_decompress() we have the correct scaled
1508 * output image dimensions available, as well as the output colormap
1509 * if we asked for color quantization.
1510 * In this example, we need to make an output work buffer of the right size.
1511 */
1512 /* JSAMPLEs per row in output buffer.
1513 Since we asked for quantized output, cinfo.output_components
1514 will always be 1. */
1515 row_stride = cinfo.output_width * cinfo.output_components;
1516 /* Make a one-row-high sample array that will go away when done
1517 with image */
1518 row_buffer = ((*cinfo.mem->alloc_sarray)
1519 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1));
1520
1521 /* Here we use the library's state variable cinfo.output_scanline as the
1522 * loop counter, so that we don't have to keep track ourselves.
1523 */
1524 while (cinfo.output_scanline < cinfo.output_height)
1525 {
1526 int i;
1527 int scanline = cinfo.output_scanline;
1528
1529 /* jpeg_read_scanlines expects an array of pointers to scanlines.
1530 * Here the array is only one element long, but you could ask for
1531 * more than one scanline at a time if that's more convenient.
1532 */
1533 (void) jpeg_read_scanlines (&cinfo, row_buffer, 1);
1534
1535 for (i = 0; i < cinfo.output_width; i++)
1536 XPutPixel (unwind.ximage, i, scanline,
1537 /* Let's make sure we avoid getting bit like
1538 what happened for GIF's. It's probably the
1539 case that JSAMPLE's are unsigned chars as
1540 opposed to chars, but you never know.
1541
1542 (They could even be shorts if the library
1543 was compiled with 12-bit samples -- ####
1544 We should deal with this possibility) */
1545 unwind.pixels[(unsigned char) row_buffer[0][i]]);
1546 }
1547 }
1548
1549 /* Step 6.5: Create the pixmap and set up the image instance */
1550 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
1551 unwind.pixels, unwind.npixels,
1552 instantiator);
1553
1554 /* Step 7: Finish decompression */
1555
1556 jpeg_finish_decompress (&cinfo);
1557 /* We can ignore the return value since suspension is not possible
1558 * with the stdio data source.
1559 */
1560
1561 /* And we're done!
1562
1563 Now that we've succeeded, we don't want the pixels
1564 freed right now. They're kept around in the image instance
1565 structure until it's destroyed. */
1566 unwind.npixels = 0;
1567
1568 /* This will clean up everything else. */
1569 unbind_to (speccount, Qnil);
1570 }
1571
1572 #endif /* HAVE_JPEG */
1573
1574
1575 #ifdef HAVE_GIF
1576
1577 /**********************************************************************
1578 * GIF *
1579 **********************************************************************/
1580
1581 #include "gif_lib.h" /* This is in our own source tree */
1582
1583 static void
1584 gif_validate (Lisp_Object instantiator)
1585 {
1586 file_or_data_must_be_present (instantiator);
1587 }
1588
1589 static Lisp_Object
1590 gif_normalize (Lisp_Object inst, Lisp_Object console_type)
1591 {
1592 return simple_image_type_normalize (inst, console_type, Qgif);
1593 }
1594
1595 static int
1596 gif_possible_dest_types (void)
1597 {
1598 return IMAGE_COLOR_PIXMAP_MASK;
1599 }
1600
1601 /* To survive the otherwise baffling complexity of making sure
1602 everything gets cleaned up in the presence of an error, we
1603 use an unwind_protect(). */
1604
1605 struct gif_unwind_data
1606 {
1607 Display *dpy;
1608 /* Object that holds the decoded data from a GIF file */
1609 GifFileType *giffile;
1610 /* Pixels to keep around while the image is active */
1611 unsigned long *pixels;
1612 int npixels;
1613 /* Client-side image structure */
1614 XImage *ximage;
1615 /* Tempfile to remove */
1616 char tempfile[50];
1617 int tempfile_needs_to_be_removed;
1618 };
1619
1620 static Lisp_Object
1621 gif_instantiate_unwind (Lisp_Object unwind_obj)
1622 {
1623 struct gif_unwind_data *data =
1624 (struct gif_unwind_data *) get_opaque_ptr (unwind_obj);
1625
1626 free_opaque_ptr (unwind_obj);
1627 if (data->giffile)
1628 DGifCloseFile (data->giffile);
1629 if (data->tempfile_needs_to_be_removed)
1630 unlink (data->tempfile);
1631 if (data->npixels > 0)
1632 {
1633 Screen *scr = DefaultScreenOfDisplay (data->dpy);
1634 Colormap cmap = DefaultColormapOfScreen (scr);
1635 XFreeColors (data->dpy, cmap, data->pixels, data->npixels, 0L);
1636 xfree (data->pixels);
1637 }
1638 if (data->ximage)
1639 {
1640 if (data->ximage->data)
1641 {
1642 xfree (data->ximage->data);
1643 data->ximage->data = 0;
1644 }
1645 XDestroyImage (data->ximage);
1646 }
1647
1648 return Qnil;
1649 }
1650
1651 #if 0
1652 /* We provide our own version of DGifSlurp() because the standardly
1653 provided one doesn't handle interlaced GIFs. This is based on
1654 code in gif2x11.c. */
1655
1656 /* Return value is GIF_ERROR, GIF_OK, or -1.
1657 #### We are using "forbidden" knowledge that neither of these
1658 constants is -1. */
1659
1660 static int
1661 our_own_dgif_slurp_from_gif2x11_c (GifFileType *GifFile)
1662 {
1663 int i, j, Row, Col, Width, Height;
1664 int ExtCode, Count;
1665 GifRecordType RecordType;
1666 GifByteType *Extension;
1667 SavedImage *sp = NULL;
1668 static int InterlacedOffset[] = { 0, 4, 2, 1 };
1669 static int InterlacedJumps[] = { 8, 8, 4, 2 };
1670
1671 GifPixelType *ScreenBuffer =
1672 (GifPixelType *) xmalloc (GifFile->SHeight * GifFile->SWidth *
1673 sizeof (GifPixelType));
1674 GifFile->SavedImages = xnew (SavedImage);
1675
1676 for (i = 0; i < GifFile->SHeight * GifFile->SWidth; i++)
1677 ScreenBuffer[i] = GifFile->SBackGroundColor;
1678
1679 /* Scan the content of the GIF file and load the image(s) in: */
1680 do
1681 {
1682 if (DGifGetRecordType (GifFile, &RecordType) == GIF_ERROR)
1683 return GIF_ERROR;
1684
1685 switch (RecordType)
1686 {
1687 case IMAGE_DESC_RECORD_TYPE:
1688 if (DGifGetImageDesc (GifFile) == GIF_ERROR)
1689 return GIF_ERROR;
1690
1691 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
1692 Row = GifFile->Image.Top; /* Image Position relative to Screen. */
1693 Col = GifFile->Image.Left;
1694 Width = GifFile->Image.Width;
1695 Height = GifFile->Image.Height;
1696 if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth ||
1697 GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight)
1698 return -1;
1699
1700 sp->RasterBits = (GifPixelType*) xmalloc(Width * Height *
1701 sizeof (GifPixelType));
1702
1703 if (GifFile->Image.Interlace)
1704 {
1705 /* Need to perform 4 passes on the images: */
1706 for (Count = i = 0; i < 4; i++)
1707 for (j = Row + InterlacedOffset[i]; j < Row + Height;
1708 j += InterlacedJumps[i])
1709 {
1710 if (DGifGetLine (GifFile, &sp->RasterBits[j * Width + Col],
1711 Width) == GIF_ERROR)
1712 return GIF_ERROR;
1713 }
1714 }
1715 else
1716 {
1717 for (i = 0; i < Height; i++)
1718 {
1719 if (DGifGetLine (GifFile,
1720 &sp->RasterBits[(Row++) * Width + Col],
1721 Width) == GIF_ERROR)
1722 return GIF_ERROR;
1723 }
1724 }
1725
1726 /* Only get 1 image from animated gifs. */
1727 /* #### if the rest of the file was bad, we still return
1728 GIF_OK, since we don't even bother looking at it. Should
1729 probably check for ImageCount == 1 above too, hmm. */
1730 goto done;
1731 break;
1732
1733 case EXTENSION_RECORD_TYPE:
1734 /* Skip any extension blocks in file: */
1735 if (DGifGetExtension (GifFile, &ExtCode, &Extension) == GIF_ERROR)
1736 return GIF_ERROR;
1737
1738 while (Extension != NULL)
1739 {
1740 if (DGifGetExtensionNext (GifFile, &Extension) == GIF_ERROR)
1741 return GIF_ERROR;
1742 }
1743 break;
1744
1745 case TERMINATE_RECORD_TYPE:
1746 break;
1747
1748 default: /* Should be traps by DGifGetRecordType. */
1749 break;
1750 }
1751 }
1752 while (RecordType != TERMINATE_RECORD_TYPE);
1753
1754 done:
1755
1756 return GIF_OK;
1757 }
1758 #endif
1759
1760 static void
1761 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1762 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1763 int dest_mask, Lisp_Object domain)
1764 {
1765 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1766 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1767 Display *dpy;
1768 Screen *scr;
1769 /* It is OK for the unwind data to be local to this function,
1770 because the unwind-protect is always executed when this
1771 stack frame is still valid. */
1772 struct gif_unwind_data unwind;
1773 int speccount = specpdl_depth ();
1774
1775 if (!DEVICE_X_P (XDEVICE (device)))
1776 signal_simple_error ("Not an X device", device);
1777
1778 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1779 scr = DefaultScreenOfDisplay (dpy);
1780
1781 memset (&unwind, 0, sizeof (unwind));
1782 unwind.dpy = dpy;
1783 record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind));
1784
1785 /* 1. Now decode the data. */
1786
1787 /* #### The GIF routines currently require that you read from a file,
1788 so write out to a temp file. We should change this. */
1789 {
1790 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1791
1792 assert (!NILP (data));
1793
1794 write_lisp_string_to_temp_file (data, unwind.tempfile);
1795 unwind.tempfile_needs_to_be_removed = 1;
1796
1797 /* Then slurp the image into memory, decoding along the way.
1798 The result is the image in a simple one-byte-per-pixel
1799 format (#### the GIF routines only support 8-bit GIFs,
1800 it appears). */
1801 unwind.giffile = DGifOpenFileName (unwind.tempfile);
1802 if (unwind.giffile == NULL)
1803 {
1804 gif_decode_error:
1805 signal_simple_error ("Unable to decode GIF",
1806 build_string (EmacsPrintGifError ()));
1807 }
1808 #if 0
1809 if (our_own_dgif_slurp_from_gif2x11_c(unwind.giffile) != GIF_OK)
1810 #else
1811 /* DGifSlurp() doesn't handle interlaced files. */
1812 /* Actually, it does, sort of. It just sets the Interlace flag
1813 and stores RasterBits in interlaced order. We handle that below. */
1814 if (DGifSlurp (unwind.giffile) != GIF_OK)
1815 #endif
1816 goto gif_decode_error;
1817 }
1818
1819 /* 2. Now allocate the colors for the image. */
1820 {
1821 int i;
1822 ColorMapObject *cmap = unwind.giffile->SColorMap;
1823 /* Just in case the image contains out-of-range pixels, we go
1824 ahead and allocate space for all of them. */
1825 unwind.pixels = xnew_array (unsigned long, 256);
1826 unwind.npixels = cmap->ColorCount;
1827
1828 for (i = 0; i < 256; i++)
1829 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */
1830
1831 /* Allocate pixels for the various colors. */
1832 for (i = 0; i < cmap->ColorCount; i++)
1833 {
1834 XColor color;
1835
1836 color.red = cmap->Colors[i].Red << 8;
1837 color.green = cmap->Colors[i].Green << 8;
1838 color.blue = cmap->Colors[i].Blue << 8;
1839 color.flags = DoRed | DoGreen | DoBlue;
1840
1841 allocate_nearest_color (dpy, DefaultColormapOfScreen (scr), &color);
1842 unwind.pixels[i] = color.pixel;
1843 }
1844 }
1845
1846 /* 3. Now create the image */
1847 {
1848 int height = unwind.giffile->SHeight;
1849 int width = unwind.giffile->SWidth;
1850 int depth;
1851 int bitmap_pad;
1852 int i, j, row, pass, interlace;
1853 /* interlaced gifs have rows in this order:
1854 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */
1855 static int InterlacedOffset[] = { 0, 4, 2, 1 };
1856 static int InterlacedJumps[] = { 8, 8, 4, 2 };
1857
1858
1859 depth = DefaultDepthOfScreen (scr);
1860
1861 /* first get bitmap_pad (from XPM) */
1862 bitmap_pad = ((depth > 16) ? 32 :
1863 (depth > 8) ? 16 :
1864 8);
1865
1866 unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr),
1867 depth, ZPixmap, 0, 0, width, height,
1868 bitmap_pad, 0);
1869
1870 if (!unwind.ximage)
1871 signal_simple_error ("Unable to create X image struct", instantiator);
1872
1873 /* now that bytes_per_line must have been set properly alloc data */
1874 unwind.ximage->data =
1875 (char *) xmalloc (unwind.ximage->bytes_per_line * height);
1876
1877 /* write the data --
1878 #### XPutPixel() is a client-side-only function but could
1879 still be slow. Another possibility is to just convert to
1880 XPM format and use the Xpm routines, which optimize this
1881 stuff; but it's doubtful that this will be faster in the
1882 long run, what with all the XPM overhead. If this proves
1883 to be a bottleneck here, maybe we should just copy the
1884 optimization routines from XPM (they're in turn mostly
1885 copied from the Xlib source code). */
1886
1887 /* Note: We just use the first image in the file and ignore the rest.
1888 We check here that that image covers the full "screen" size.
1889 I don't know whether that's always the case.
1890 -dkindred@cs.cmu.edu */
1891 if (unwind.giffile->SavedImages[0].ImageDesc.Height != height
1892 || unwind.giffile->SavedImages[0].ImageDesc.Width != width
1893 || unwind.giffile->SavedImages[0].ImageDesc.Left != 0
1894 || unwind.giffile->SavedImages[0].ImageDesc.Top != 0)
1895 signal_simple_error ("First image in GIF file is not full size",
1896 instantiator);
1897
1898 interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace;
1899 pass = 0;
1900 row = interlace ? InterlacedOffset[pass] : 0;
1901 for (i = 0; i < height; i++)
1902 {
1903 if (interlace && row >= height)
1904 row = InterlacedOffset[++pass];
1905
1906 for (j = 0; j < width; j++)
1907 XPutPixel (unwind.ximage, j, row,
1908 unwind.pixels[(unsigned char)
1909 /* incorrect signed declaration
1910 of RasterBits[] */
1911 (unwind.giffile->SavedImages[0].
1912 RasterBits[i * width + j])]);
1913
1914 row += interlace ? InterlacedJumps[pass] : 1;
1915 }
1916 }
1917
1918 /* 4. Now create the pixmap and set up the image instance */
1919 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
1920 unwind.pixels, unwind.npixels,
1921 instantiator);
1922 /* Now that we've succeeded, we don't want the pixels
1923 freed right now. They're kept around in the image instance
1924 structure until it's destroyed. */
1925 unwind.npixels = 0;
1926 unbind_to (speccount, Qnil);
1927 }
1928
1929 #endif /* HAVE_GIF */
1930
1931
1932 #ifdef HAVE_PNG
1933
1934 /**********************************************************************
1935 * PNG *
1936 **********************************************************************/
1937 static void
1938 png_validate (Lisp_Object instantiator)
1939 {
1940 file_or_data_must_be_present (instantiator);
1941 }
1942
1943 static Lisp_Object
1944 png_normalize (Lisp_Object inst, Lisp_Object console_type)
1945 {
1946 return simple_image_type_normalize (inst, console_type, Qpng);
1947 }
1948
1949 static int
1950 png_possible_dest_types (void)
1951 {
1952 return IMAGE_COLOR_PIXMAP_MASK;
1953 }
1954
1955 #if !defined (USE_TEMP_FILES_FOR_PNG_IMAGES) && (PNG_LIBPNG_VER >= 87)
1956 struct png_memory_storage
1957 {
1958 Extbyte *bytes; /* The data */
1959 Extcount len; /* How big is it? */
1960 int index; /* Where are we? */
1961 };
1962
1963 static void png_read_from_memory(png_structp png_ptr, png_bytep data,
1964 png_uint_32 length)
1965 {
1966 struct png_memory_storage *tbr =
1967 (struct png_memory_storage *) png_get_io_ptr (png_ptr);
1968
1969 if (length > (tbr->len - tbr->index))
1970 png_error (png_ptr, (png_const_charp) "Read Error");
1971 memcpy(data,tbr->bytes + tbr->index,length);
1972 tbr->index = tbr->index + length;
1973 }
1974 #endif /* !USE_TEMP_FILES_FOR_PNG_IMAGESS || PNG_LIBPNG_VER >= 87 */
1975
1976 struct png_unwind_data
1977 {
1978 Display *dpy;
1979 FILE *instream;
1980 png_struct *png_ptr;
1981 png_info *info_ptr;
1982 unsigned long *pixels;
1983 int npixels;
1984 XImage *ximage;
1985 char tempfile[50];
1986 int tempfile_needs_to_be_removed;
1987 };
1988
1989 static Lisp_Object
1990 png_instantiate_unwind (Lisp_Object unwind_obj)
1991 {
1992 struct png_unwind_data *data =
1993 (struct png_unwind_data *) get_opaque_ptr (unwind_obj);
1994
1995 free_opaque_ptr (unwind_obj);
1996 if (data->png_ptr)
1997 png_read_destroy (data->png_ptr, data->info_ptr, (png_info *) NULL);
1998 if (data->instream)
1999 fclose (data->instream);
2000 if (data->tempfile_needs_to_be_removed)
2001 unlink (data->tempfile);
2002 if (data->npixels > 0)
2003 {
2004 Screen *scr = DefaultScreenOfDisplay (data->dpy);
2005 Colormap cmap = DefaultColormapOfScreen (scr);
2006 XFreeColors (data->dpy, cmap, data->pixels, data->npixels, 0L);
2007 xfree (data->pixels);
2008 }
2009
2010 if (data->ximage)
2011 {
2012 if (data->ximage->data)
2013 {
2014 xfree (data->ximage->data);
2015 data->ximage->data = 0;
2016 }
2017 XDestroyImage (data->ximage);
2018 }
2019
2020 return Qnil;
2021 }
2022
2023 /* This doesn't appear to be used. */
2024 #if 0
2025 #define get_png_val(p) _get_png_val (&(p), info_ptr.bit_depth)
2026 png_uint_16
2027 _get_png_val (png_byte **pp, int bit_depth)
2028 {
2029 png_uint_16 c = 0;
2030
2031 if (bit_depth == 16) {
2032 c = (*((*pp)++)) << 8;
2033 }
2034 c |= (*((*pp)++));
2035
2036 return c;
2037 }
2038 #endif
2039
2040 static void
2041 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2042 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2043 int dest_mask, Lisp_Object domain)
2044 {
2045 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2046 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2047 Display *dpy;
2048 Screen *scr;
2049 struct png_unwind_data unwind;
2050 int speccount = specpdl_depth ();
2051
2052 /* PNG variables */
2053 png_struct *png_ptr;
2054 png_info *info_ptr;
2055
2056 if (!DEVICE_X_P (XDEVICE (device)))
2057 signal_simple_error ("Not an X device", device);
2058
2059 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2060 scr = DefaultScreenOfDisplay (dpy);
2061
2062 png_ptr = xnew (png_struct);
2063 info_ptr = xnew (png_info);
2064
2065 memset (&unwind, 0, sizeof (unwind));
2066 unwind.png_ptr = png_ptr;
2067 unwind.info_ptr = info_ptr;
2068 unwind.dpy = dpy;
2069
2070 record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind));
2071
2072 /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from
2073 this file, example.c from the libpng 0.81 distribution, and the
2074 pngtopnm sources. -WMP-
2075 */
2076 #if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87)
2077 /* Write out to a temp file - we really should take the time to
2078 write appropriate memory bound IO stuff, but I am just trying
2079 to get the stupid thing working right now.
2080 */
2081 {
2082 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2083
2084 assert (!NILP (data));
2085
2086 write_lisp_string_to_temp_file (data, unwind.tempfile);
2087 unwind.tempfile_needs_to_be_removed = 1;
2088
2089 if ((unwind.instream = fopen (unwind.tempfile, "rb")) == NULL)
2090 report_file_error ("Opening PNG temp file",
2091 list1 (build_string (unwind.tempfile)));
2092 }
2093 #else
2094 /* Nothing */
2095 #endif
2096
2097 /* Set the jmp_buf reurn context for png_error ... if this returns !0, then
2098 we ran into a problem somewhere, and need to clean up after ourselves. */
2099 if (setjmp (png_ptr->jmpbuf))
2100 {
2101 /* Am I doing enough here? I think so, since most things happen
2102 in png_unwind */
2103 png_read_destroy (png_ptr, info_ptr, (png_info *) NULL);
2104 signal_simple_error ("Error decoding PNG", instantiator);
2105 }
2106
2107 /* Initialize all PNG structures */
2108 png_info_init (info_ptr);
2109 png_read_init (png_ptr);
2110
2111 /* Initialize the IO layer and read in header information */
2112 #if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87)
2113 png_init_io (png_ptr, unwind.instream);
2114 #else
2115 {
2116 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2117 Extbyte *bytes;
2118 Extcount len;
2119 struct png_memory_storage tbr; /* Data to be read */
2120
2121 assert (!NILP (data));
2122
2123 /* #### This is a definite problem under Mule due to the amount of
2124 stack data it might allocate. Need to be able to convert and
2125 write out to a file. */
2126 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
2127 tbr.bytes = bytes;
2128 tbr.len = len;
2129 tbr.index = 0;
2130 png_set_read_fn(png_ptr,(void *) &tbr, png_read_from_memory);
2131 }
2132 #endif
2133
2134 png_read_info (png_ptr, info_ptr);
2135
2136 /* set up the transformations you want. Note that these are
2137 all optional. Only call them if you want them */
2138 /* tell libpng to strip 16 bit depth files down to 8 bits */
2139 if (info_ptr->bit_depth == 16)
2140 png_set_strip_16 (png_ptr);
2141 if (info_ptr->bit_depth < 8)
2142 png_set_packing (png_ptr);
2143 /* ##### Perhaps some way to specify the screen gamma should be in here? */
2144
2145 {
2146 int height = info_ptr->height;
2147 int width = info_ptr->width;
2148 int depth = info_ptr->bit_depth;
2149 int linesize = max (info_ptr->bit_depth >> 3, 1) * width;
2150 int bitmap_pad;
2151 int y;
2152 XColor color;
2153 png_byte *png_pixels;
2154 png_byte **row_pointers;
2155 png_color static_color_cube[216];
2156
2157 /* Wow, allocate all the memory. Truly, exciting. */
2158 unwind.pixels = xnew_array (unsigned long, 256);
2159 png_pixels = xnew_array (png_byte, linesize * height);
2160 row_pointers = xnew_array (png_byte *, height);
2161
2162 for (y = 0; y < 256; y++)
2163 unwind.pixels[y] = 0;
2164 for (y = 0; y < height; y++)
2165 row_pointers[y] = png_pixels + (linesize * y);
2166
2167 /* #### This is where we should handle transparency, but I am unsure of
2168 how exactly to get that information right now, in a safe manner. */
2169 #if 0
2170 {
2171 png_color_16 current_background;
2172
2173 /* Some appropriate magic should go here to get the current
2174 buffers (device?) background color and convert it to a
2175 png_color_16 struct */
2176 if (info_ptr->valid & PNG_INFO_bKGD)
2177 png_set_background (png_ptr, &(info_ptr->background), PNG_GAMMA_FILE,
2178 1, 1.0);
2179 else
2180 png_set_background (png_ptr, &current_background, PNG_GAMMA_SCREEN,
2181 0, 1.0);
2182 }
2183 #endif
2184
2185 if ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2186 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA))
2187 {
2188 if (!(info_ptr->valid & PNG_INFO_PLTE))
2189 {
2190 for (y = 0; y < 216; y++)
2191 {
2192 static_color_cube[y].red = (y % 6) * 255.0 / 5;
2193 static_color_cube[y].green = ((y / 6) % 6) * 255.0 / 5;
2194 static_color_cube[y].blue = (y / 36) * 255.0 / 5;
2195 }
2196 png_set_dither (png_ptr, static_color_cube, 216, 216, NULL, 1);
2197 }
2198 else
2199 {
2200 png_set_dither (png_ptr, info_ptr->palette, info_ptr->num_palette,
2201 info_ptr->num_palette, info_ptr->hist, 1);
2202 }
2203 }
2204
2205 png_read_image (png_ptr, row_pointers);
2206 png_read_end (png_ptr, info_ptr);
2207
2208 /* Ok, now we go and allocate all the colors */
2209 if (info_ptr->valid & PNG_INFO_PLTE)
2210 {
2211 unwind.npixels = info_ptr->num_palette;
2212 for (y = 0; y < unwind.npixels; y++)
2213 {
2214 color.red = info_ptr->palette[y].red << 8;
2215 color.green = info_ptr->palette[y].green << 8;
2216 color.blue = info_ptr->palette[y].blue << 8;
2217 color.flags = DoRed | DoGreen | DoBlue;
2218 allocate_nearest_color (dpy, DefaultColormapOfScreen (scr),
2219 &color);
2220 unwind.pixels[y] = color.pixel;
2221 }
2222 }
2223 else
2224 {
2225 unwind.npixels = 216;
2226 for (y = 0; y < 216; y++)
2227 {
2228 color.red = static_color_cube[y].red << 8;
2229 color.green = static_color_cube[y].green << 8;
2230 color.blue = static_color_cube[y].blue << 8;
2231 color.flags = DoRed|DoGreen|DoBlue;
2232 allocate_nearest_color (dpy, DefaultColormapOfScreen (scr),
2233 &color);
2234 unwind.pixels[y] = color.pixel;
2235 }
2236 }
2237
2238 #ifdef PNG_SHOW_COMMENTS
2239 /* ####
2240 * I turn this off by default now, because the !%^@#!% comments
2241 * show up every time the image is instantiated, which can get
2242 * really really annoying. There should be some way to pass this
2243 * type of data down into the glyph code, where you can get to it
2244 * from lisp anyway. - WMP
2245 */
2246 {
2247 int i;
2248
2249 for (i = 0 ; i < info_ptr->num_text ; i++)
2250 {
2251 /* How paranoid do I have to be about no trailing NULLs, and
2252 using (int)info_ptr->text[i].text_length, and strncpy and a temp
2253 string somewhere? */
2254
2255 warn_when_safe (Qpng, Qinfo, "%s - %s",
2256 info_ptr->text[i].key,
2257 info_ptr->text[i].text);
2258 }
2259 }
2260 #endif
2261
2262 /* Now create the image */
2263
2264 depth = DefaultDepthOfScreen (scr);
2265
2266 /* first get bitmap_pad (from XPM) */
2267 bitmap_pad = ((depth > 16) ? 32 :
2268 (depth > 8) ? 16 :
2269 8);
2270
2271 unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr),
2272 depth, ZPixmap, 0, 0, width, height,
2273 bitmap_pad, 0);
2274
2275 if (!unwind.ximage)
2276 signal_simple_error ("Unable to create X image struct",
2277 instantiator);
2278
2279 /* now that bytes_per_line must have been set properly alloc data */
2280 unwind.ximage->data = (char *) xmalloc (unwind.ximage->bytes_per_line *
2281 height);
2282
2283 {
2284 int i, j;
2285 for (i = 0; i < height; i++)
2286 for (j = 0; j < width; j++)
2287 XPutPixel (unwind.ximage, j, i,
2288 unwind.pixels[png_pixels[i * width + j]]);
2289 }
2290
2291 xfree (row_pointers);
2292 xfree (png_pixels);
2293 }
2294
2295 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2296 unwind.pixels, unwind.npixels,
2297 instantiator);
2298
2299 /* This will clean up everything else. */
2300 unwind.npixels = 0;
2301 unbind_to (speccount, Qnil);
2302 }
2303
2304 #endif /* HAVE_PNG */
2305
2306
2307 #ifdef HAVE_TIFF
2308
2309 /**********************************************************************
2310 * TIFF *
2311 **********************************************************************/
2312 static void
2313 tiff_validate (Lisp_Object instantiator)
2314 {
2315 file_or_data_must_be_present (instantiator);
2316 }
2317
2318 static Lisp_Object
2319 tiff_normalize (Lisp_Object inst, Lisp_Object console_type)
2320 {
2321 signal_simple_error ("No TIFF support yet", inst);
2322 return Qnil;
2323 }
2324
2325 static int
2326 tiff_possible_dest_types (void)
2327 {
2328 return IMAGE_COLOR_PIXMAP_MASK;
2329 }
2330
2331 static void
2332 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2333 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2334 int dest_mask, Lisp_Object domain)
2335 {
2336 abort ();
2337 }
2338
2339 #endif /* HAVE_TIFF */
2340 1043
2341 1044
2342 #ifdef HAVE_XPM 1045 #ifdef HAVE_XPM
2343 1046
2344 /********************************************************************** 1047 /**********************************************************************
2966 } 1669 }
2967 1670
2968 #endif /* HAVE_XPM */ 1671 #endif /* HAVE_XPM */
2969 1672
2970 1673
1674 #ifdef HAVE_IMAGEMAGICK
1675 /**********************************************************************
1676 * ImageMagick *
1677 **********************************************************************/
1678 static void
1679 imagick_validate (Lisp_Object instantiator)
1680 {
1681 file_or_data_must_be_present (instantiator);
1682 }
1683
1684 static Lisp_Object
1685 imagick_normalize (Lisp_Object inst, Lisp_Object console_type)
1686 {
1687 return simple_image_type_normalize (inst, console_type, Qimagick);
1688 }
1689
1690 static int
1691 imagick_possible_dest_types (void)
1692 {
1693 return IMAGE_COLOR_PIXMAP_MASK;
1694 }
1695
1696 struct imagick_unwind_data
1697 {
1698 /* FIXME - what goes here...*/
1699 Display *dpy;
1700 FILE *instream;
1701 Image *image;
1702 XImage *ximage;
1703 unsigned long *pixels;
1704 unsigned long npixels;
1705 char tempfile[50];
1706 int tempfile_needs_to_be_removed;
1707 };
1708
1709 static Lisp_Object
1710 imagick_instantiate_unwind (Lisp_Object unwind_obj)
1711 {
1712 struct imagick_unwind_data *data =
1713 (struct imagick_unwind_data *) get_opaque_ptr (unwind_obj);
1714
1715 free_opaque_ptr (unwind_obj);
1716 if (data->instream)
1717 fclose (data->instream);
1718 if (data->tempfile_needs_to_be_removed)
1719 unlink (data->tempfile);
1720
1721 if (data->image) {
1722 DestroyImage(data->image);
1723 }
1724
1725 if (data->ximage)
1726 {
1727 if (data->ximage->data)
1728 {
1729 xfree (data->ximage->data);
1730 data->ximage->data = NULL;
1731 }
1732 XDestroyImage (data->ximage);
1733 }
1734
1735 return Qnil;
1736 }
1737
1738 static void XDitherImage(Image *image,XImage *ximage);
1739
1740 static void
1741 imagick_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1742 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1743 int dest_mask, Lisp_Object domain)
1744 {
1745 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1746 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1747 Display *dpy;
1748 Screen *scr;
1749 Dimension depth;
1750 struct imagick_unwind_data unwind;
1751 int speccount = specpdl_depth ();
1752 ImageInfo image_info;
1753
1754 /* ImageMagick variables */
1755
1756 /* Basic error checking */
1757 if (!DEVICE_X_P (XDEVICE (device)))
1758 signal_simple_error ("Not an X device", device);
1759
1760 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1761 scr = DefaultScreenOfDisplay (dpy);
1762 depth = DefaultDepthOfScreen (scr);
1763 /* Set up the unwind */
1764 memset (&unwind, 0, sizeof (unwind));
1765 unwind.dpy = dpy;
1766 record_unwind_protect(imagick_instantiate_unwind,make_opaque_ptr(&unwind));
1767
1768 /* Write out to a temp file - not sure if ImageMagick supports the
1769 ** notion of an abstrat 'data source' right now.
1770 */
1771 {
1772 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1773
1774 assert (!NILP (data));
1775
1776 write_lisp_string_to_temp_file (data, unwind.tempfile);
1777 unwind.tempfile_needs_to_be_removed = 1;
1778
1779 if ((unwind.instream = fopen (unwind.tempfile, "rb")) == NULL)
1780 report_file_error ("Opening ImageMagick temp file",
1781 list1 (build_string (unwind.tempfile)));
1782 }
1783
1784 /* Initialize structures and read in the image */
1785 GetImageInfo(&image_info);
1786 strcpy(image_info.filename,unwind.tempfile);
1787 unwind.image = ReadImage(&image_info);
1788 if (unwind.image == (Image *) NULL) {
1789 signal_simple_error ("Unable to read image.",instantiator);
1790 }
1791
1792 unwind.ximage = XCreateImage(dpy, DefaultVisualOfScreen (scr),
1793 depth,
1794 (depth == 1) ? XYPixmap : ZPixmap,
1795 0, 0,
1796 unwind.image->columns,
1797 unwind.image->rows,
1798 XBitmapPad(dpy), 0);
1799
1800 if (!unwind.ximage) {
1801 signal_simple_error("Unable to allocate XImage structure",
1802 instantiator);
1803 }
1804
1805 unwind.ximage->data = (char *) xmalloc(unwind.ximage->bytes_per_line *
1806 unwind.ximage->height *
1807 unwind.ximage->depth);
1808
1809 if (unwind.ximage->data == (char *)NULL) {
1810 signal_simple_error("Unable to allocate pixel information",
1811 instantiator);
1812 }
1813
1814 /* Need to pull the data from the 'Image' structure in
1815 ** unwind.image and convert it to an 'XImage' in unwind.ximage
1816 **
1817 ** FIXME IM FUCKED
1818 **
1819 ** WMP 10/30/97
1820 */
1821
1822 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
1823 unwind.pixels, unwind.npixels,
1824 instantiator);
1825 }
1826
1827 #endif /* HAVE_IMAGEMAGICK */
1828
1829
2971 #ifdef HAVE_XFACE 1830 #ifdef HAVE_XFACE
2972 1831
2973 /********************************************************************** 1832 /**********************************************************************
2974 * X-Face * 1833 * X-Face *
2975 **********************************************************************/ 1834 **********************************************************************/
3870 2729
3871 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); 2730 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
3872 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); 2731 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
3873 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); 2732 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
3874 2733
3875 #ifdef HAVE_JPEG 2734 #ifdef HAVE_IMAGEMAGICK
3876 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg"); 2735 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (imagick, "imagick");
3877 2736
3878 IIFORMAT_HAS_METHOD (jpeg, validate); 2737 IIFORMAT_HAS_METHOD (imagick, validate);
3879 IIFORMAT_HAS_METHOD (jpeg, normalize); 2738 IIFORMAT_HAS_METHOD (imagick, normalize);
3880 IIFORMAT_HAS_METHOD (jpeg, possible_dest_types); 2739 IIFORMAT_HAS_METHOD (imagick, possible_dest_types);
3881 IIFORMAT_HAS_METHOD (jpeg, instantiate); 2740 IIFORMAT_HAS_METHOD (imagick, instantiate);
3882 2741
3883 IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string); 2742 IIFORMAT_VALID_KEYWORD (imagick, Q_data, check_valid_string);
3884 IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string); 2743 IIFORMAT_VALID_KEYWORD (imagick, Q_file, check_valid_string);
3885 #endif
3886
3887 #ifdef HAVE_GIF
3888 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif");
3889
3890 IIFORMAT_HAS_METHOD (gif, validate);
3891 IIFORMAT_HAS_METHOD (gif, normalize);
3892 IIFORMAT_HAS_METHOD (gif, possible_dest_types);
3893 IIFORMAT_HAS_METHOD (gif, instantiate);
3894
3895 IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string);
3896 IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string);
3897 #endif
3898
3899 #ifdef HAVE_PNG
3900 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png");
3901
3902 IIFORMAT_HAS_METHOD (png, validate);
3903 IIFORMAT_HAS_METHOD (png, normalize);
3904 IIFORMAT_HAS_METHOD (png, possible_dest_types);
3905 IIFORMAT_HAS_METHOD (png, instantiate);
3906
3907 IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string);
3908 IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string);
3909 #endif
3910
3911 #ifdef HAVE_TIFF
3912 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff");
3913
3914 IIFORMAT_HAS_METHOD (tiff, validate);
3915 IIFORMAT_HAS_METHOD (tiff, normalize);
3916 IIFORMAT_HAS_METHOD (tiff, possible_dest_types);
3917 IIFORMAT_HAS_METHOD (tiff, instantiate);
3918
3919 IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string);
3920 IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string);
3921 #endif 2744 #endif
3922 2745
3923 #ifdef HAVE_XPM 2746 #ifdef HAVE_XPM
3924 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xpm, "xpm"); 2747 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xpm, "xpm");
3925 2748
3961 } 2784 }
3962 2785
3963 void 2786 void
3964 vars_of_glyphs_x (void) 2787 vars_of_glyphs_x (void)
3965 { 2788 {
3966 #ifdef HAVE_JPEG
3967 Fprovide (Qjpeg);
3968 #endif
3969
3970 #ifdef HAVE_GIF
3971 Fprovide (Qgif);
3972 #endif
3973
3974 #ifdef HAVE_PNG
3975 Fprovide (Qpng);
3976 #endif
3977
3978 #ifdef HAVE_TIFF
3979 Fprovide (Qtiff);
3980 #endif
3981
3982 #ifdef HAVE_XPM 2789 #ifdef HAVE_XPM
3983 Fprovide (Qxpm); 2790 Fprovide (Qxpm);
3984 2791
3985 DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols /* 2792 DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols /*
3986 Definitions of logical color-names used when reading XPM files. 2793 Definitions of logical color-names used when reading XPM files.
3992 2799
3993 The default value of this variable defines the logical color names 2800 The default value of this variable defines the logical color names
3994 \"foreground\" and \"background\" to be the colors of the `default' face. 2801 \"foreground\" and \"background\" to be the colors of the `default' face.
3995 */ ); 2802 */ );
3996 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */ 2803 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
2804 #endif
2805
2806 #ifdef HAVE_IMAGEMAGICK
2807 Fprovide (Qimagick);
3997 #endif 2808 #endif
3998 2809
3999 #ifdef HAVE_XFACE 2810 #ifdef HAVE_XFACE
4000 Fprovide (Qxface); 2811 Fprovide (Qxface);
4001 #endif 2812 #endif