I found part of the answer by reading the source code. In
xfaces.c, there is (in
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);
face->foreground = load_color (f, face, dfg, LFACE_FOREGROUND_INDEX);
/* Returns the `distance' between the colors X and Y. */
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;
(((512 + r_mean) * r * r) >> 8)
+ 4 * g * g
+ (((767 - r_mean) * b * b) >> 8);
#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.