Mercurial > hg > xemacs-beta
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, ¤t_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 |