comparison src/glyphs-gtk.c @ 2082:16489ca72b3d

[xemacs-hg @ 2004-05-15 07:43:05 by malcolmp] Improvements to the rendering of GTK glyph backgrounds.
author malcolmp
date Sat, 15 May 2004 07:43:09 +0000
parents 91d4c8c65a0f
children 95fee4a1420e
comparison
equal deleted inserted replaced
2081:e8db6a10ad42 2082:16489ca72b3d
69 #include "ui-gtk.h" 69 #include "ui-gtk.h"
70 70
71 #include "sysfile.h" 71 #include "sysfile.h"
72 72
73 #include <setjmp.h> 73 #include <setjmp.h>
74
75 #if defined (HAVE_XPM)
76 #include <X11/xpm.h>
77 #endif
74 78
75 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); 79 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
76 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); 80 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
77 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); 81 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
78 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); 82 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
1058 1062
1059 #ifdef HAVE_XPM 1063 #ifdef HAVE_XPM
1060 /********************************************************************** 1064 /**********************************************************************
1061 * XPM * 1065 * XPM *
1062 **********************************************************************/ 1066 **********************************************************************/
1063 static Lisp_Object
1064 write_lisp_string_to_temp_file (Lisp_Object string)
1065 {
1066 Lisp_Object instream, outstream;
1067 Lstream *istr, *ostr;
1068 Char_Binary tempbuf[1024]; /* some random amount */
1069 int fubar = 0;
1070 FILE *tmpfil;
1071 static Extbyte_dynarr *conversion_out_dynarr;
1072 Bytecount bstart, bend;
1073 Lisp_Object tempfile;
1074 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1075 Lisp_Object conv_out_stream;
1076 Lstream *costr;
1077
1078 /* This function can GC */
1079 if (!conversion_out_dynarr)
1080 conversion_out_dynarr = Dynarr_new (Extbyte);
1081 else
1082 Dynarr_reset (conversion_out_dynarr);
1083
1084 /* Create the temporary file ... */
1085 tempfile = Fmake_temp_name (build_string ("/tmp/emacs"));
1086 tmpfil = qxe_fopen (XSTRING_DATA (tempfile), "w");
1087 if (!tmpfil)
1088 {
1089 if (tmpfil)
1090 {
1091 int old_errno = errno;
1092 retry_fclose (tmpfil);
1093 qxe_unlink (XSTRING_DATA (tempfile));
1094 errno = old_errno;
1095 }
1096 report_file_error ("Creating temp file", tempfile);
1097 }
1098
1099 CHECK_STRING (string);
1100 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
1101 GB_HISTORICAL_STRING_BEHAVIOR);
1102 instream = make_lisp_string_input_stream (string, bstart, bend);
1103 istr = XLSTREAM (instream);
1104 /* setup the out stream */
1105 outstream =
1106 make_dynarr_output_stream ((unsigned_char_dynarr *) conversion_out_dynarr);
1107 ostr = XLSTREAM (outstream);
1108 /* setup the conversion stream */
1109 conv_out_stream =
1110 make_coding_output_stream (ostr, Qbinary, CODING_ENCODE, 0);
1111 costr = XLSTREAM (conv_out_stream);
1112 GCPRO4 (tempfile, instream, outstream, conv_out_stream);
1113
1114 /* Get the data while doing the conversion */
1115 while (1)
1116 {
1117 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
1118 if (!size_in_bytes)
1119 break;
1120 /* It does seem the flushes are necessary... */
1121 Lstream_write (costr, tempbuf, size_in_bytes);
1122 Lstream_flush (costr);
1123 Lstream_flush (ostr);
1124 if (retry_fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
1125 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
1126 {
1127 fubar = 1;
1128 break;
1129 }
1130 /* reset the dynarr */
1131 Lstream_rewind(ostr);
1132 }
1133
1134 if (retry_fclose (tmpfil) != 0)
1135 fubar = 1;
1136 Lstream_close (istr);
1137 Lstream_close (costr);
1138 Lstream_close (ostr);
1139
1140 Lstream_delete (istr);
1141 Lstream_delete (ostr);
1142 Lstream_delete (costr);
1143
1144 if (fubar)
1145 report_file_error ("Writing temp file", tempfile);
1146
1147 UNGCPRO;
1148 return tempfile;
1149 }
1150 1067
1151 struct color_symbol 1068 struct color_symbol
1152 { 1069 {
1153 Ibyte* name; 1070 Ibyte* name;
1154 GdkColor color; 1071 GdkColor color;
1232 GdkPixmap *pixmap; 1149 GdkPixmap *pixmap;
1233 GdkPixmap *mask = 0; 1150 GdkPixmap *mask = 0;
1234 GdkWindow *window = 0; 1151 GdkWindow *window = 0;
1235 int nsymbols = 0, i = 0; 1152 int nsymbols = 0, i = 0;
1236 struct color_symbol *color_symbols = NULL; 1153 struct color_symbol *color_symbols = NULL;
1237 GdkColor *transparent_color = NULL;
1238 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, 1154 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1239 Q_color_symbols); 1155 Q_color_symbols);
1240 enum image_instance_type type; 1156 enum image_instance_type type;
1241 int force_mono; 1157 int force_mono;
1242 gint w, h; 1158 gint w, h;
1243 Lisp_Object tempfile = Qnil; 1159 struct gcpro gcpro1, gcpro2, gcpro3;
1244 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 1160 const UChar_Binary * volatile dstring;
1245 1161
1246 if (!DEVICE_GTK_P (XDEVICE (device))) 1162 if (!DEVICE_GTK_P (XDEVICE (device)))
1247 gui_error ("Not a Gtk device", device); 1163 gui_error ("Not a Gtk device", device);
1248 1164
1249 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) 1165 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1256 incompatible_image_types (instantiator, dest_mask, 1172 incompatible_image_types (instantiator, dest_mask,
1257 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK 1173 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1258 | IMAGE_POINTER_MASK); 1174 | IMAGE_POINTER_MASK);
1259 force_mono = (type != IMAGE_COLOR_PIXMAP); 1175 force_mono = (type != IMAGE_COLOR_PIXMAP);
1260 1176
1261 GCPRO4 (device, data, color_symbol_alist, tempfile); 1177 GCPRO3 (device, data, color_symbol_alist);
1262 1178
1263 window = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); 1179 window = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device)));
1264 cmap = DEVICE_GTK_COLORMAP (XDEVICE (device)); 1180 cmap = DEVICE_GTK_COLORMAP (XDEVICE (device));
1265 depth = DEVICE_GTK_DEPTH (XDEVICE (device)); 1181 depth = DEVICE_GTK_DEPTH (XDEVICE (device));
1266 visual = DEVICE_GTK_VISUAL (XDEVICE (device)); 1182 visual = DEVICE_GTK_VISUAL (XDEVICE (device));
1267 1183
1268 gtk_initialize_pixmap_image_instance (ii, 1, type); 1184 gtk_initialize_pixmap_image_instance (ii, 1, type);
1269 1185
1270 assert (!NILP (data)); 1186 assert (!NILP (data));
1271 1187
1272 /* Need to get the transparent color here */ 1188 /* Extract all the entries from xpm-color-symbols */
1273 color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, 1189 color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist,
1274 &nsymbols); 1190 &nsymbols);
1275 for (i = 0; i < nsymbols; i++) 1191 assert (!NILP (data));
1276 { 1192
1277 if (!qxestrcasecmp_c (color_symbols[i].name, "BgColor") || 1193 LISP_STRING_TO_EXTERNAL(data, dstring, Qbinary);
1278 !qxestrcasecmp_c (color_symbols[i].name, "None")) 1194
1279 { 1195 /*
1280 transparent_color = &color_symbols[i].color; 1196 * GTK only uses the 'c' color entry of an XPM and doesn't use the symbolic
1281 } 1197 * color names at all. This is unfortunate because the way to change the
1282 } 1198 * colors from lisp is by adding the symbolic names, and the new colors, to
1283 1199 * the variable xpm-color-symbols.
1284 tempfile = write_lisp_string_to_temp_file (data); 1200 *
1201 * To get around this decode the XPM, add a 'c' entry of the desired color
1202 * for each matching symbolic color, recode the XPM and pass it to GTK. The
1203 * decode and recode stages aren't too bad because this also performs the
1204 * external to internal format translation, which avoids contortions like
1205 * writing the XPM back to disk in order to get it processed.
1206 */
1285 { 1207 {
1286 Extbyte *tempfileout; 1208 XpmImage image;
1287 1209 XpmInfo info;
1288 LISP_STRING_TO_EXTERNAL (tempfile, tempfileout, Qfile_name); 1210 char** data;
1289 pixmap = gdk_pixmap_create_from_xpm (window, &mask, transparent_color, 1211
1290 tempfileout); 1212 XpmCreateXpmImageFromBuffer ((char*) dstring, &image, &info);
1213
1214 for (i = 0; i < nsymbols; i++)
1215 {
1216 unsigned j;
1217
1218 for (j = 0; j < image.ncolors; j++)
1219 {
1220 if (image.colorTable[j].symbolic != NULL &&
1221 !qxestrcasecmp_c(color_symbols[i].name, image.colorTable[j].symbolic))
1222 {
1223 image.colorTable[j].c_color = (char*) xmalloc(16);
1224
1225 sprintf(image.colorTable[j].c_color, "#%.4x%.4x%.4x",
1226 color_symbols[i].color.red, color_symbols[i].color.green,
1227 color_symbols[i].color.blue);
1228 }
1229 }
1230 }
1231
1232 XpmCreateDataFromXpmImage (&data, &image, &info);
1233
1234 pixmap = gdk_pixmap_create_from_xpm_d (window, &mask, NULL,
1235 data);
1291 } 1236 }
1292 qxe_unlink (XSTRING_DATA (tempfile));
1293 1237
1294 if (color_symbols) 1238 if (color_symbols)
1295 xfree (color_symbols, struct color_symbol *); 1239 xfree (color_symbols, struct color_symbol *);
1296 1240
1297 if (!pixmap) 1241 if (!pixmap)
1298 signal_image_error ("Error reading pixmap", data); 1242 signal_image_error ("Error reading pixmap", data);
1299 1243
1300 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth); 1244 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth);
1301 1245
1302 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; 1246 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap;
1303 IMAGE_INSTANCE_GTK_MASK (ii) = mask; 1247 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask;
1304 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; 1248 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap;
1305 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; 1249 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0;
1306 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; 1250 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0;
1307 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w; 1251 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1308 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h; 1252 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;