I noticed that Skia calculates alpha correction table in SkFont_FreeType.c as follows:
static void build_gamma_table(uint8_t table[256], int srcI) {
const float src = (float)srcI / 255.0f;
const float linSrc = lin(src);
const float linDst = 1.0f  linSrc;
The objective of the calculation here produces a table for replacing the source alpha value with a corrected alpha value for improving blending result when text is drawn using the component color srcI. The calculation for linDst makes the assumption that the background component is the inverse of the foreground component, and then calculates the alpha value that will produce the right blending using a linear component blend based on what the correct result of such blend would have been if sRGB aware blend had been used instead.
This technique improves the average error relative to performing a naive blend by quite a bit, and for the very important cases of white on black, and black on white, the result is in fact exact within the numerical precision. In many other cases, however, there will be some degree of error, because the background assumption is not always correct, and this tends to appear as coloration in LCD rendering.
Is the bg assumption the best possible? I submit that it is not necessary to make the assumption of dst = 1  src: it is possible to simply approach the problem numerically and to exhaustively try every possible corrected alpha against every possible background choice for every (fg, alpha) pair, and calculate the error made relative to true sRGB blending result. The error can be measured as difference of the numerical value of the component either in linear or sRGB space, and then aggregated using typical statistical tools like root mean square or maximum error. I have chosen root mean square of component values in sRGB.
Attached, I have a couple of captures of the (fg, alpha) > alpha_correction mapping colored with the RMS error made, showing that for a truly unknown background case  a reasonable assumption to make for sake of generality  the resulting blending can be significantly improved in average.
Here is a github project calculating what I expect to be the optimal mapping table: http://bel.fi/alankila/liblcdglyph/src/build_table.c (The github project is just a fairly young prototype/reference implementation I am working on in the hopes that it might be useful for someone eventually.)
When using FreeType and LCD rendering, I also noticed that the kernel is probably not optimal. Skia appears to use FreeType's default 5tap kernel, which appears to impart some degree of color fringing if used. The optimal 5tap kernels should be of the following form: [a  c, a + c, 2 * a, a + c, a  c]. To generate a 1sum kernel, a should be set to 1/6, and c is bounded to 0 <= c <= a.
This formulation produces equal excitation of all color components, and the degree of blurring can be adjusted by the freely chosen tunable c. The filter is colorless because all color components under the kernel receive a total excitation of 2*a: the central pixel is the only one of that color, so its weight is directly 2*a, and the other color pairs are weighted with a+c and ac for total of 2*a.

Deleted:
inverse_bg_assumption.png
153 KB


Deleted:
no_bg_assumption.png
149 KB

Comment 1 by alank...@gmail.com, Mar 25 2013