2

Emacs's faces let you set :distant-foreground, which according to the docs, "is like :foreground but the color is only used as a foreground when the background color is near to the foreground that would have been used."

I'm not really sure how "near" is computed, but it doesn't seem to be good enough. I would like to use it with my region face, so that the text is in the same face it's normally in, except when it's unreadable. My region is currently set to :background "lightgoldenrod2". Selecting some white text with this makes it unreadable. When I set :distant-foreground "black", it doesn't change.

How is "near" calculated here? How can I adjust this calculation to be a more reasonable contrast calculation?

  • Ancillary question: what is an easy way to create a buffer with text of all different faces that can be selected so I can test this? – asmeurer Feb 4 '15 at 20:24
  • When you set :distant-foreground of what - face region? Try to give a recipe to repro the symptoms you see, preferably starting from emacs -Q. And for a buffer showing different faces, try list-faces-display. – Drew Feb 5 '15 at 1:56
  • Yes, setting it on region. It's not hard to repro: M-x customize, search for region, set the properties, try selecting colored text. – asmeurer Feb 5 '15 at 3:09
2

I found part of the answer by reading the source code. In xfaces.c, there is (in load_face_colors)

  dfg = attrs[LFACE_DISTANT_FOREGROUND_INDEX];
  if (!NILP (dfg) && !UNSPECIFIEDP (dfg)
      && color_distance (&xbg, &xfg) < NEAR_SAME_COLOR_THRESHOLD)
    {
      if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
        face->background = load_color (f, face, dfg, LFACE_BACKGROUND_INDEX);
      else
        face->foreground = load_color (f, face, dfg, LFACE_FOREGROUND_INDEX);
    }

where

/* Returns the `distance' between the colors X and Y.  */

static int
color_distance (XColor *x, XColor *y)
{
  /* This formula is from a paper titled `Colour metric' by Thiadmer Riemersma.
     Quoting from that paper:

     This formula has results that are very close to L*u*v* (with the
     modified lightness curve) and, more importantly, it is a more even
     algorithm: it does not have a range of colors where it suddenly
     gives far from optimal results.

     See <http://www.compuphase.com/cmetric.htm> for more info.  */

  long r = (x->red   - y->red)   >> 8;
  long g = (x->green - y->green) >> 8;
  long b = (x->blue  - y->blue)  >> 8;
  long r_mean = (x->red + y->red) >> 9;

  return
    (((512 + r_mean) * r * r) >> 8)
    + 4 * g * g
    + (((767 - r_mean) * b * b) >> 8);
}

and

#define NEAR_SAME_COLOR_THRESHOLD 30000

Since this is in C, I think this means that this is not really customizable (maybe by rewriting the C function in lisp).

Doing some research, it would be nice to get an algorithm that uses http://web.mst.edu/~rhall/web_design/color_readability.html (the "Algorithm" section), which gives a formula and a good recommended contrast ratio from W3C.

1

It works for me, but yes, you need to pick a color that is "nearer" than that for it to take effect. From emacs -Q.

I set face default to have a white foreground and a background of #000000004. And I set face region to have a distant foreground of black and a background of #ffffffff3.

Selecting white text shows the region with black text (foreground). Selecting another color of text (e.g. green foreground) shows the region with that same color (green) as foreground.

Try closer colors to see if it at least works in your Emacs version. I'm on MS Windows and using a dev version of Emacs 25 from last October (2014).

And while you're at it, you might consider filing an Emacs bug (M-x report-emacs-bug) for (at least) insufficient doc. If there isn't already (and I couldn't find any in the doc or in NEWS), there should perhaps be a user option, to let you control how close "near" needs to be for :distant-foreground to kick in.

  • I'm not denying that it doesn't work. I'm asking how to make it useful. Your "try closer colors" advice is strange. I have lots of colors from lots of faces. I want my region face to work well with all of them. Obviously if I only had one face then distant-foreground would be useless, because it's easy to find two colors that aren't close. – asmeurer Feb 5 '15 at 16:38
  • I understand. How to make it useful is precisely the question. That's why I suggested M-x report-emacs-bug. That's for bug reports and enhancement requests. However you want to look at this issue, there is room for improvement, IMO. Users should be able to customize how near "near" is, etc., and be guided in that. Currently, I see no relevant doc or user options. – Drew Feb 5 '15 at 16:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.