aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMiles Bader2002-06-09 13:02:16 +0000
committerMiles Bader2002-06-09 13:02:16 +0000
commitb35df831c55eef2f2a4707fb5583fd5abb2c7bc3 (patch)
treecb5adc15fc5844cebaca16b873389e70fbf6ce2c /src
parent6ae315b0d873be00a8d630aebd922b11244d40b8 (diff)
downloademacs-b35df831c55eef2f2a4707fb5583fd5abb2c7bc3.tar.gz
emacs-b35df831c55eef2f2a4707fb5583fd5abb2c7bc3.zip
(Ftty_supports_face_attributes_p): New function.
(parse_rgb_list, tty_lookup_color): New functions. (tty_defined_color): Use `tty_lookup_color' to do all the work. (color_distance, Fcolor_distance): New functions. (TTY_SAME_COLOR_THRESHOLD): New macro. (Qtty_color_standard_values): New variable. (syms_of_xfaces): Initialize new vars & functions.
Diffstat (limited to 'src')
-rw-r--r--src/xfaces.c391
1 files changed, 353 insertions, 38 deletions
diff --git a/src/xfaces.c b/src/xfaces.c
index e9f0b3195ac..4ae49d1cb54 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -1,5 +1,5 @@
1/* xfaces.c -- "Face" primitives. 1/* xfaces.c -- "Face" primitives.
2 Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001 2 Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation. 3 Free Software Foundation.
4 4
5This file is part of GNU Emacs. 5This file is part of GNU Emacs.
@@ -427,7 +427,7 @@ static int lface_id_to_name_size;
427 427
428/* TTY color-related functions (defined in tty-colors.el). */ 428/* TTY color-related functions (defined in tty-colors.el). */
429 429
430Lisp_Object Qtty_color_desc, Qtty_color_by_index; 430Lisp_Object Qtty_color_desc, Qtty_color_by_index, Qtty_color_standard_values;
431 431
432/* The name of the function used to compute colors on TTYs. */ 432/* The name of the function used to compute colors on TTYs. */
433 433
@@ -1305,6 +1305,98 @@ load_face_font (f, face, c)
1305 X Colors 1305 X Colors
1306 ***********************************************************************/ 1306 ***********************************************************************/
1307 1307
1308/* Parse RGB_LIST, and fill in the RGB fields of COLOR.
1309 RGB_LIST should contain (at least) 3 lisp integers.
1310 Return 0 if there's a problem with RGB_LIST, otherwise return 1. */
1311
1312static int
1313parse_rgb_list (rgb_list, color)
1314 Lisp_Object rgb_list;
1315 XColor *color;
1316{
1317#define PARSE_RGB_LIST_FIELD(field) \
1318 if (CONSP (rgb_list) && INTEGERP (XCAR (rgb_list))) \
1319 { \
1320 color->field = XINT (XCAR (rgb_list)); \
1321 rgb_list = XCDR (rgb_list); \
1322 } \
1323 else \
1324 return 0;
1325
1326 PARSE_RGB_LIST_FIELD (red);
1327 PARSE_RGB_LIST_FIELD (green);
1328 PARSE_RGB_LIST_FIELD (blue);
1329
1330 return 1;
1331}
1332
1333
1334/* Lookup on frame F the color described by the lisp string COLOR.
1335 The resulting tty color is returned in TTY_COLOR; if STD_COLOR is
1336 non-zero, then the `standard' definition of the same color is
1337 returned in it. */
1338
1339static int
1340tty_lookup_color (f, color, tty_color, std_color)
1341 struct frame *f;
1342 Lisp_Object color;
1343 XColor *tty_color, *std_color;
1344{
1345 Lisp_Object frame, color_desc;
1346
1347 if (!STRINGP (color) || NILP (Ffboundp (Qtty_color_desc)))
1348 return 0;
1349
1350 XSETFRAME (frame, f);
1351
1352 color_desc = call2 (Qtty_color_desc, color, frame);
1353 if (CONSP (color_desc) && CONSP (XCDR (color_desc)))
1354 {
1355 Lisp_Object rgb;
1356
1357 if (! INTEGERP (XCAR (XCDR (color_desc))))
1358 return 0;
1359
1360 tty_color->pixel = XINT (XCAR (XCDR (color_desc)));
1361
1362 rgb = XCDR (XCDR (color_desc));
1363 if (! parse_rgb_list (rgb, tty_color))
1364 return 0;
1365
1366 /* Should we fill in STD_COLOR too? */
1367 if (std_color)
1368 {
1369 /* Default STD_COLOR to the same as TTY_COLOR. */
1370 *std_color = *tty_color;
1371
1372 /* Do a quick check to see if the returned descriptor is
1373 actually _exactly_ equal to COLOR, otherwise we have to
1374 lookup STD_COLOR separately. If it's impossible to lookup
1375 a standard color, we just give up and use TTY_COLOR. */
1376 if ((!STRINGP (XCAR (color_desc))
1377 || NILP (Fstring_equal (color, XCAR (color_desc))))
1378 && Ffboundp (Qtty_color_standard_values))
1379 {
1380 /* Look up STD_COLOR separately. */
1381 rgb = call1 (Qtty_color_standard_values, color);
1382 if (! parse_rgb_list (rgb, std_color))
1383 return 0;
1384 }
1385 }
1386
1387 return 1;
1388 }
1389 else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
1390 /* We were called early during startup, and the colors are not
1391 yet set up in tty-defined-color-alist. Don't return a failure
1392 indication, since this produces the annoying "Unable to
1393 load color" messages in the *Messages* buffer. */
1394 return 1;
1395 else
1396 /* tty-color-desc seems to have returned a bad value. */
1397 return 0;
1398}
1399
1308/* A version of defined_color for non-X frames. */ 1400/* A version of defined_color for non-X frames. */
1309 1401
1310int 1402int
@@ -1314,52 +1406,28 @@ tty_defined_color (f, color_name, color_def, alloc)
1314 XColor *color_def; 1406 XColor *color_def;
1315 int alloc; 1407 int alloc;
1316{ 1408{
1317 Lisp_Object color_desc;
1318 unsigned long color_idx = FACE_TTY_DEFAULT_COLOR;
1319 unsigned long red = 0, green = 0, blue = 0;
1320 int status = 1; 1409 int status = 1;
1321 1410
1322 if (*color_name && !NILP (Ffboundp (Qtty_color_desc))) 1411 /* Defaults. */
1323 { 1412 color_def->pixel = FACE_TTY_DEFAULT_COLOR;
1324 Lisp_Object frame; 1413 color_def->red = 0;
1414 color_def->blue = 0;
1415 color_def->green = 0;
1325 1416
1326 XSETFRAME (frame, f); 1417 if (*color_name)
1327 status = 0; 1418 status = tty_lookup_color (f, build_string (color_name), color_def, 0);
1328 color_desc = call2 (Qtty_color_desc, build_string (color_name), frame); 1419
1329 if (CONSP (color_desc) && CONSP (XCDR (color_desc))) 1420 if (color_def->pixel == FACE_TTY_DEFAULT_COLOR && *color_name)
1330 {
1331 color_idx = XINT (XCAR (XCDR (color_desc)));
1332 if (CONSP (XCDR (XCDR (color_desc))))
1333 {
1334 red = XINT (XCAR (XCDR (XCDR (color_desc))));
1335 green = XINT (XCAR (XCDR (XCDR (XCDR (color_desc)))));
1336 blue = XINT (XCAR (XCDR (XCDR (XCDR (XCDR (color_desc))))));
1337 }
1338 status = 1;
1339 }
1340 else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
1341 /* We were called early during startup, and the colors are not
1342 yet set up in tty-defined-color-alist. Don't return a failure
1343 indication, since this produces the annoying "Unable to
1344 load color" messages in the *Messages* buffer. */
1345 status = 1;
1346 }
1347 if (color_idx == FACE_TTY_DEFAULT_COLOR && *color_name)
1348 { 1421 {
1349 if (strcmp (color_name, "unspecified-fg") == 0) 1422 if (strcmp (color_name, "unspecified-fg") == 0)
1350 color_idx = FACE_TTY_DEFAULT_FG_COLOR; 1423 color_def->pixel = FACE_TTY_DEFAULT_FG_COLOR;
1351 else if (strcmp (color_name, "unspecified-bg") == 0) 1424 else if (strcmp (color_name, "unspecified-bg") == 0)
1352 color_idx = FACE_TTY_DEFAULT_BG_COLOR; 1425 color_def->pixel = FACE_TTY_DEFAULT_BG_COLOR;
1353 } 1426 }
1354 1427
1355 if (color_idx != FACE_TTY_DEFAULT_COLOR) 1428 if (color_def->pixel != FACE_TTY_DEFAULT_COLOR)
1356 status = 1; 1429 status = 1;
1357 1430
1358 color_def->pixel = color_idx;
1359 color_def->red = red;
1360 color_def->green = green;
1361 color_def->blue = blue;
1362
1363 return status; 1431 return status;
1364} 1432}
1365 1433
@@ -5024,6 +5092,249 @@ prepare_face_for_display (f, face)
5024} 5092}
5025 5093
5026 5094
5095/* Returns the `distance' between the colors X and Y. */
5096
5097static int
5098color_distance (x, y)
5099 XColor *x, *y;
5100{
5101 /* This formula is from a paper title `Colour metric' by Thiadmer Riemersma.
5102 Quoting from that paper:
5103
5104 This formula has results that are very close to L*u*v* (with the
5105 modified lightness curve) and, more importantly, it is a more even
5106 algorithm: it does not have a range of colours where it suddenly
5107 gives far from optimal results.
5108
5109 See <http://www.compuphase.com/cmetric.htm> for more info. */
5110
5111 long r = (x->red - y->red) >> 8;
5112 long g = (x->green - y->green) >> 8;
5113 long b = (x->blue - y->blue) >> 8;
5114 long r_mean = (x->red + y->red) >> 9;
5115
5116 return
5117 (((512 + r_mean) * r * r) >> 8)
5118 + 4 * g * g
5119 + (((767 - r_mean) * b * b) >> 8);
5120}
5121
5122
5123DEFUN ("color-distance", Fcolor_distance, Scolor_distance, 2, 3, 0,
5124 doc: /* Return an integer distance between COLOR1 and COLOR2 on FRAME.
5125COLOR1 and COLOR2 may be either strings containing the color name,
5126or lists of the form (RED GREEN BLUE).
5127If FRAME is unspecified or nil, the current frame is used. */)
5128 (color1, color2, frame)
5129 Lisp_Object color1, color2, frame;
5130{
5131 struct frame *f;
5132 XColor cdef1, cdef2;
5133
5134 if (NILP (frame))
5135 frame = selected_frame;
5136 CHECK_LIVE_FRAME (frame);
5137 f = XFRAME (frame);
5138
5139 if ((CONSP (color1) && !parse_rgb_list (color1, &cdef1))
5140 || !STRINGP (color1)
5141 || !defined_color (f, XSTRING (color1)->data, &cdef1, 0))
5142 signal_error ("Invalid color", color1);
5143 if ((CONSP (color2) && !parse_rgb_list (color2, &cdef2))
5144 || !STRINGP (color2)
5145 || !defined_color (f, XSTRING (color2)->data, &cdef2, 0))
5146 signal_error ("Invalid color", color2);
5147
5148 return make_number (color_distance (&cdef1, &cdef2));
5149}
5150
5151
5152/***********************************************************************
5153 Face capability testing for ttys
5154 ***********************************************************************/
5155
5156
5157/* If the distance (as returned by color_distance) between two colors is
5158 less than this, then they are considered the same, for determining
5159 whether a color is supported or not. The range of values is 0-65535. */
5160
5161#define TTY_SAME_COLOR_THRESHOLD 10000
5162
5163
5164DEFUN ("tty-supports-face-attributes-p",
5165 Ftty_supports_face_attributes_p, Stty_supports_face_attributes_p,
5166 1, 2, 0,
5167 doc: /* Return non-nil if all the face attributes in ATTRIBUTES are supported.
5168The optional argument FRAME is the frame on which to test; if it is nil
5169or unspecified, then the current frame is used. If FRAME is not a tty
5170frame, then nil is returned.
5171
5172The definition of `supported' is somewhat heuristic, but basically means
5173that a face containing all the attributes in ATTRIBUTES, when merged
5174with the default face for display, can be represented in a way that's
5175
5176 \(1) different in appearance than the default face, and
5177 \(2) `close in spirit' to what the attributes specify, if not exact.
5178
5179Point (2) implies that a `:weight black' attribute will be satisified
5180by any terminal that can display bold, and a `:foreground "yellow"' as
5181long as the terminal can display a yellowish color, but `:slant italic'
5182will _not_ be satisified by the tty display code's automatic
5183substitution of a `dim' face for italic. */)
5184 (attributes, frame)
5185 Lisp_Object attributes, frame;
5186{
5187 int weight, i;
5188 struct frame *f;
5189 Lisp_Object val, fg, bg;
5190 XColor fg_tty_color, fg_std_color;
5191 XColor bg_tty_color, bg_std_color;
5192 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5193 unsigned test_caps = 0;
5194
5195 if (NILP (frame))
5196 frame = selected_frame;
5197 CHECK_LIVE_FRAME (frame);
5198 f = XFRAME (frame);
5199
5200 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
5201 attrs[i] = Qunspecified;
5202 merge_face_vector_with_property (f, attrs, attributes);
5203
5204 /* This function only works on ttys. */
5205 if (!FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
5206 return Qnil;
5207
5208 /* First check some easy-to-check stuff; ttys support none of the
5209 following attributes, so we can just return nil if any are requested. */
5210
5211 /* stipple */
5212 val = attrs[LFACE_STIPPLE_INDEX];
5213 if (!UNSPECIFIEDP (val) && !NILP (val))
5214 return Qnil;
5215
5216 /* font height */
5217 val = attrs[LFACE_HEIGHT_INDEX];
5218 if (!UNSPECIFIEDP (val) && !NILP (val))
5219 return Qnil;
5220
5221 /* font width */
5222 val = attrs[LFACE_SWIDTH_INDEX];
5223 if (!UNSPECIFIEDP (val) && !NILP (val)
5224 && face_numeric_swidth (val) != XLFD_SWIDTH_MEDIUM)
5225 return Qnil;
5226
5227 /* overline */
5228 val = attrs[LFACE_OVERLINE_INDEX];
5229 if (!UNSPECIFIEDP (val) && !NILP (val))
5230 return Qnil;
5231
5232 /* strike-through */
5233 val = attrs[LFACE_STRIKE_THROUGH_INDEX];
5234 if (!UNSPECIFIEDP (val) && !NILP (val))
5235 return Qnil;
5236
5237 /* boxes */
5238 val = attrs[LFACE_BOX_INDEX];
5239 if (!UNSPECIFIEDP (val) && !NILP (val))
5240 return Qnil;
5241
5242 /* slant (italics/oblique); We consider any non-default value
5243 unsupportable on ttys, even though the face code actually `fakes'
5244 them using a dim attribute if possible. This is because the faked
5245 result is too different from what the face specifies. */
5246 val = attrs[LFACE_SLANT_INDEX];
5247 if (!UNSPECIFIEDP (val) && !NILP (val)
5248 && face_numeric_slant (val) != XLFD_SLANT_ROMAN)
5249 return Qnil;
5250
5251
5252 /* Test for terminal `capabilities' (non-color character attributes). */
5253
5254 /* font weight (bold/dim) */
5255 weight = face_numeric_weight (attrs[LFACE_WEIGHT_INDEX]);
5256 if (weight >= 0)
5257 {
5258 if (weight > XLFD_WEIGHT_MEDIUM)
5259 test_caps = TTY_CAP_BOLD;
5260 else if (weight < XLFD_WEIGHT_MEDIUM)
5261 test_caps = TTY_CAP_DIM;
5262 }
5263
5264 /* underlining */
5265 val = attrs[LFACE_UNDERLINE_INDEX];
5266 if (!UNSPECIFIEDP (val) && !NILP (val))
5267 {
5268 if (STRINGP (val))
5269 return Qnil; /* ttys don't support colored underlines */
5270 else
5271 test_caps |= TTY_CAP_UNDERLINE;
5272 }
5273
5274 /* inverse video */
5275 val = attrs[LFACE_INVERSE_INDEX];
5276 if (!UNSPECIFIEDP (val) && !NILP (val))
5277 test_caps |= TTY_CAP_INVERSE;
5278
5279
5280 /* Color testing. */
5281
5282 /* Default the color indices in FG_TTY_COLOR and BG_TTY_COLOR, since
5283 we use them when calling `tty_capable_p' below, even if the face
5284 specifies no colors. */
5285 fg_tty_color.pixel = FACE_TTY_DEFAULT_FG_COLOR;
5286 bg_tty_color.pixel = FACE_TTY_DEFAULT_BG_COLOR;
5287
5288 /* Check if foreground color is close enough. */
5289 fg = attrs[LFACE_FOREGROUND_INDEX];
5290 if (STRINGP (fg))
5291 {
5292 if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
5293 return Qnil;
5294 else if (color_distance (&fg_tty_color, &fg_std_color)
5295 > TTY_SAME_COLOR_THRESHOLD)
5296 return Qnil;
5297 }
5298
5299 /* Check if background color is close enough. */
5300 bg = attrs[LFACE_BACKGROUND_INDEX];
5301 if (STRINGP (bg))
5302 {
5303 if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
5304 return Qnil;
5305 else if (color_distance (&bg_tty_color, &bg_std_color)
5306 > TTY_SAME_COLOR_THRESHOLD)
5307 return Qnil;
5308 }
5309
5310 /* If both foreground and background are requested, see if the
5311 distance between them is OK. We just check to see if the distance
5312 between the tty's foreground and background is close enough to the
5313 distance between the standard foreground and background. */
5314 if (STRINGP (fg) && STRINGP (bg))
5315 {
5316 int delta_delta
5317 = (color_distance (&fg_std_color, &bg_std_color)
5318 - color_distance (&fg_tty_color, &bg_tty_color));
5319 if (delta_delta > TTY_SAME_COLOR_THRESHOLD
5320 || delta_delta < -TTY_SAME_COLOR_THRESHOLD)
5321 return Qnil;
5322 }
5323
5324
5325 /* See if the capabilities we selected above are supported, with the
5326 given colors. */
5327 if (test_caps != 0 &&
5328 ! tty_capable_p (f, test_caps, fg_tty_color.pixel, bg_tty_color.pixel))
5329 return Qnil;
5330
5331
5332 /* Hmmm, everything checks out, this terminal must support this face. */
5333 return Qt;
5334}
5335
5336
5337
5027/*********************************************************************** 5338/***********************************************************************
5028 Face Cache 5339 Face Cache
5029 ***********************************************************************/ 5340 ***********************************************************************/
@@ -7238,6 +7549,8 @@ syms_of_xfaces ()
7238 staticpro (&Qmode_line_inactive); 7549 staticpro (&Qmode_line_inactive);
7239 Qtty_color_desc = intern ("tty-color-desc"); 7550 Qtty_color_desc = intern ("tty-color-desc");
7240 staticpro (&Qtty_color_desc); 7551 staticpro (&Qtty_color_desc);
7552 Qtty_color_standard_values = intern ("tty-color-standard-values");
7553 staticpro (&Qtty_color_standard_values);
7241 Qtty_color_by_index = intern ("tty-color-by-index"); 7554 Qtty_color_by_index = intern ("tty-color-by-index");
7242 staticpro (&Qtty_color_by_index); 7555 staticpro (&Qtty_color_by_index);
7243 Qtty_color_alist = intern ("tty-color-alist"); 7556 Qtty_color_alist = intern ("tty-color-alist");
@@ -7270,6 +7583,8 @@ syms_of_xfaces ()
7270 defsubr (&Sinternal_merge_in_global_face); 7583 defsubr (&Sinternal_merge_in_global_face);
7271 defsubr (&Sface_font); 7584 defsubr (&Sface_font);
7272 defsubr (&Sframe_face_alist); 7585 defsubr (&Sframe_face_alist);
7586 defsubr (&Stty_supports_face_attributes_p);
7587 defsubr (&Scolor_distance);
7273 defsubr (&Sinternal_set_font_selection_order); 7588 defsubr (&Sinternal_set_font_selection_order);
7274 defsubr (&Sinternal_set_alternative_font_family_alist); 7589 defsubr (&Sinternal_set_alternative_font_family_alist);
7275 defsubr (&Sinternal_set_alternative_font_registry_alist); 7590 defsubr (&Sinternal_set_alternative_font_registry_alist);