comparison src/faces.c @ 446:1ccc32a20af4 r21-2-38

Import from CVS: tag r21-2-38
author cvs
date Mon, 13 Aug 2007 11:37:21 +0200
parents 576fb035e263
children 0784d089fdc9
comparison
equal deleted inserted replaced
445:34f3776fcf0e 446:1ccc32a20af4
1152 fm->width = fi->width; 1152 fm->width = fi->width;
1153 } 1153 }
1154 } 1154 }
1155 } 1155 }
1156 1156
1157 /* Called when the updated flag has been cleared on a cachel. */
1158
1159 void
1160 update_face_cachel_data (struct face_cachel *cachel,
1161 Lisp_Object domain,
1162 Lisp_Object face)
1163 {
1164 if (XFACE (face)->dirty || UNBOUNDP (cachel->face))
1165 {
1166 int default_face = EQ (face, Vdefault_face);
1167 cachel->face = face;
1168
1169 /* We normally only set the _specified flags if the value was
1170 actually bound. The exception is for the default face where
1171 we always set it since it is the ultimate fallback. */
1172
1173 #define FROB(field) \ 1157 #define FROB(field) \
1174 do { \ 1158 do { \
1175 Lisp_Object new_val = \ 1159 Lisp_Object new_val = \
1176 FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero); \ 1160 FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero); \
1177 int bound = 1; \ 1161 int bound = 1; \
1186 cachel->dirty = 1; \ 1170 cachel->dirty = 1; \
1187 } \ 1171 } \
1188 cachel->field##_specified = (bound || default_face); \ 1172 cachel->field##_specified = (bound || default_face); \
1189 } while (0) 1173 } while (0)
1190 1174
1175 /*
1176 * A face's background pixmap will override the face's
1177 * background color. But the background pixmap of the
1178 * default face should not override the background color of
1179 * a face if the background color has been specified or
1180 * inherited.
1181 *
1182 * To accomplish this we remove the background pixmap of the
1183 * cachel and mark it as having been specified so that cachel
1184 * merging won't override it later.
1185 */
1186 #define MAYBE_UNFROB_BACKGROUND_PIXMAP \
1187 do \
1188 { \
1189 if (! default_face \
1190 && cachel->background_specified \
1191 && ! cachel->background_pixmap_specified) \
1192 { \
1193 cachel->background_pixmap = Qunbound; \
1194 cachel->background_pixmap_specified = 1; \
1195 } \
1196 } while (0)
1197
1198
1199 /* Add a cachel for the given face to the given window's cache. */
1200
1201 static void
1202 add_face_cachel (struct window *w, Lisp_Object face)
1203 {
1204 int must_finish_frobbing = ! WINDOW_FACE_CACHEL (w, DEFAULT_INDEX);
1205 struct face_cachel new_cachel;
1206 Lisp_Object domain;
1207
1208 reset_face_cachel (&new_cachel);
1209 XSETWINDOW (domain, w);
1210 update_face_cachel_data (&new_cachel, domain, face);
1211 Dynarr_add (w->face_cachels, new_cachel);
1212
1213 /* The face's background pixmap have not yet been frobbed (see comment
1214 int update_face_cachel_data), so we have to do it now */
1215 if (must_finish_frobbing)
1216 {
1217 int default_face = EQ (face, Vdefault_face);
1218 struct face_cachel *cachel
1219 = Dynarr_atp (w->face_cachels, Dynarr_length (w->face_cachels) - 1);
1220
1221 FROB (background_pixmap);
1222 MAYBE_UNFROB_BACKGROUND_PIXMAP;
1223 }
1224 }
1225
1226 /* Called when the updated flag has been cleared on a cachel.
1227 This function returns 1 if the caller must finish the update (see comment
1228 below), 0 otherwise.
1229 */
1230
1231 void
1232 update_face_cachel_data (struct face_cachel *cachel,
1233 Lisp_Object domain,
1234 Lisp_Object face)
1235 {
1236 if (XFACE (face)->dirty || UNBOUNDP (cachel->face))
1237 {
1238 int default_face = EQ (face, Vdefault_face);
1239 cachel->face = face;
1240
1241 /* We normally only set the _specified flags if the value was
1242 actually bound. The exception is for the default face where
1243 we always set it since it is the ultimate fallback. */
1244
1191 FROB (foreground); 1245 FROB (foreground);
1192 FROB (background); 1246 FROB (background);
1193 FROB (display_table); 1247 FROB (display_table);
1194 FROB (background_pixmap); 1248
1195 1249 /* #### WARNING: the background pixmap property of faces is currently
1196 /* 1250 the only one dealing with images. The problem we have here is that
1197 * A face's background pixmap will override the face's 1251 frobbing the background pixmap might lead to image instantiation
1198 * background color. But the background pixmap of the 1252 which in turn might require that the cache we're building be up to
1199 * default face should not override the background color of 1253 date, hence a crash. Here's a typical scenario of this:
1200 * a face if the background color has been specified or 1254
1201 * inherited. 1255 - a new window is created and it's face cache elements are
1202 * 1256 initialized through a call to reset_face_cachels[1]. At that point,
1203 * To accomplish this we remove the background pixmap of the 1257 the cache for the default and modeline faces (normaly taken care of
1204 * cachel and mark it as having been specified so that cachel 1258 by redisplay itself) are null.
1205 * merging won't override it later. 1259 - the default face has a background pixmap which needs to be
1206 */ 1260 instantiated right here, as a consequence of cache initialization.
1207 if (! default_face 1261 - the background pixmap image happens to be instantiated as a string
1208 && cachel->background_specified 1262 (this happens on tty's for instance).
1209 && ! cachel->background_pixmap_specified) 1263 - In order to do this, we need to compute the string geometry.
1264 - In order to do this, we might have to access the window's default
1265 face cache. But this is the cache we're building right now, it is
1266 null.
1267 - BARF !!!!!
1268
1269 To sum up, this means that it is in general unsafe to instantiate
1270 images before face cache updating is complete (appart from image
1271 related face attributes). The solution we use below is to actually
1272 detect whether we're building the window's face_cachels for the first
1273 time, and simply NOT frob the background pixmap in that case. If
1274 other image-related face attributes are ever implemented, they should
1275 be protected the same way right here.
1276
1277 One note:
1278 * See comment in `default_face_font_info' in face.c. Who wrote it ?
1279 Maybe we have the begining of an answer here ?
1280
1281 Footnotes:
1282 [1] See comment at the top of `allocate_window' in window.c.
1283
1284 -- didier
1285 */
1286 if (! WINDOWP (domain)
1287 || WINDOW_FACE_CACHEL (DOMAIN_XWINDOW (domain), DEFAULT_INDEX))
1210 { 1288 {
1211 cachel->background_pixmap = Qunbound; 1289 FROB (background_pixmap);
1212 cachel->background_pixmap_specified = 1; 1290 MAYBE_UNFROB_BACKGROUND_PIXMAP;
1213 } 1291 }
1214
1215 #undef FROB 1292 #undef FROB
1293 #undef MAYBE_UNFROB_BACKGROUND_PIXMAP
1216 1294
1217 ensure_face_cachel_contains_charset (cachel, domain, Vcharset_ascii); 1295 ensure_face_cachel_contains_charset (cachel, domain, Vcharset_ascii);
1218 1296
1219 #define FROB(field) \ 1297 #define FROB(field) \
1220 do { \ 1298 do { \
1315 } 1393 }
1316 cachel->display_table = Qunbound; 1394 cachel->display_table = Qunbound;
1317 cachel->background_pixmap = Qunbound; 1395 cachel->background_pixmap = Qunbound;
1318 } 1396 }
1319 1397
1320 /* Add a cachel for the given face to the given window's cache. */
1321
1322 static void
1323 add_face_cachel (struct window *w, Lisp_Object face)
1324 {
1325 struct face_cachel new_cachel;
1326 Lisp_Object window;
1327
1328 reset_face_cachel (&new_cachel);
1329 XSETWINDOW (window, w);
1330 update_face_cachel_data (&new_cachel, window, face);
1331 Dynarr_add (w->face_cachels, new_cachel);
1332 }
1333
1334 /* Retrieve the index to a cachel for window W that corresponds to 1398 /* Retrieve the index to a cachel for window W that corresponds to
1335 the specified face. If necessary, add a new element to the 1399 the specified face. If necessary, add a new element to the
1336 cache. */ 1400 cache. */
1337 1401
1338 face_index 1402 face_index