Modern operating systems use a little trick called subpixel rendering or subpixel font hinting to make glyphs look better on LCD screens that display a square pixel as three vertical stripes. These stripes are called subpixels and display the colors red, green and blue and usually in RGB order (although some displays use a BGR subpixel order):
![]()
So if your TFT display has a horizontal resolution of 1024 pixels, there are really 1024*3=3072 pixels in each row. This physical feature of LCD displays can be exploited to enhance the resolution at which font glyphs can be rendered. A typical problem of pixel based displays is drawing diagonal lines. While horizontal and vertical lines can be displayed very sharply due to the physical matrix layout of the pixels on the screen, diagonal lines often look very "edgy". Subpixel rendering works by "borrowing" neighbor subpixels to make things look smoother.
Unfortunately, subpixel font hinting is not enabled in Freetype. So if you need subpixel rendering for your web application, but cannot recompile Freetype, here's some PHP code you can apply to an image.
// How blurry do we want it?
$c = array(1,2,3,2,1);
// Precalc
$sum = array_sum($c);
foreach ($c as $k => $v)
$c[$k]= $v/$sum;
// Subpixel rendering
for ($y=0; $y<$height; $y++) {
for($x=0; $x<$width-1; $x++) {
// Neighbors
$source = array(imagecolorsforindex($im, imagecolorat($im, $x-1, $y)),
imagecolorsforindex($im, imagecolorat($im, $x, $y)),
imagecolorsforindex($im, imagecolorat($im, $x+1, $y)));
// New red value
$r = $c[0]*$source[0]['green'] +
$c[1]*$source[0]['blue'] +
$c[2]*$source[1]['red'] +
$c[3]*$source[1]['green'] +
$c[4]*$source[1]['blue'];
// New green value
$g = $c[0]*$source[0]['blue'] +
$c[1]*$source[1]['red'] +
$c[2]*$source[1]['green'] +
$c[3]*$source[1]['blue'] +
$c[4]*$source[2]['red'];
// New blue value
$b = $c[0]*$source[1]['red'] +
$c[1]*$source[1]['green'] +
$c[2]*$source[1]['blue'] +
$c[3]*$source[2]['red'] +
$c[4]*$source[2]['green'];
// Set the new color
imagesetpixel($im, $x, $y, imageColorAllocate($im, $r, $g, $b));
}
}
Of course there are two things to consider: 1) You want to cache the rendering results 2) This will only work on monitors with RGB subpixel ordering (or CRTs). For that matter, there are more situations where this does not work. Most TFTs (including the iPhone) have their subpixels RGB-ordered and the font hinting will look gorgeous (as a semi-bald man would say) - until you rotate the screen, which is a common thing at least on the iPhone. So there is no subpixel rendering on the iPhone. Fonts still look good on the iPhone because it has a higher resolution than most other displays: 160dpi (dots/pixels per inch). For comparison: Standard TFTs have roughly 90dpi, a 20 inch Cinema Display has 97dpi.
This is a close look at glyphs rendered by the above PHP snipped.
![]()
In the above detail of the letter a you can see that the border of the letter is not only anti-aliased. On the left edge you see a slight red coloring, while on the right edge you see a blue coloring. On a screen with RGB subpixel ordering this makes the edge of the glyph look a lot smoother.
Here is a close look at subpixel rendering for the letter X.
![]()
If I did not scare you away yet and you're interested in all this stuff, I suggest you visit these pages:
I think that was the longest blog article I ever wrote. I hope I did not bore you :-)