In which we ponder the Great Imponderables of text on Mac OS X, and the subtle, obtuse, and bone-headed means by which we may stymie proper anti-aliasing.

Fig. 1: Basic anti-aliased text, magnified 2x.

Aliasing is a term used in computer graphics to describe artifacts created when a shape is rendered into a grid of pixels; these artifacts are commonly known as “the jaggies.” Anti-aliasing, then, is the process of rendering graphics in a way that conceals these artifacts. Let’s take a brief look at how text is anti-aliased on Mac OS X, and then we’ll look at how things can go wrong.

Completely unaliased text looks horrible (Fig. 2); in the mid- to late-nineties, Mac OS became accustomed to anti-aliased text, as in Fig. 1 (above). LCD displays became widely available and inexpensive enough to push out CRTs at the same time, not just because they are lighter and thinner, but for excellent contrast and very sharp pixels—and sub-pixels.

Each pixel is actually comprised of three components, red, green, and blue, and on LCDs the operating system can take advantage of that fact to improve anti-aliasing through a method called sub-pixel rendering. ClearType is Microsoft’s patented method of sub-pixel rendering; it differs from the method used in Mac OS X primarily in its intent: ClearType is designed to make small text as readable as possible, while Mac OS X attempts to accurately maintain the shape of the individual glyphs. That’s all I will say about ClearType here.

Fig. 2: Aliased text has lots of jagged edges, and crooked curves. This is what most text looked like in 1995.

Fig. 3a: Text with sub-pixel anti-aliasing (Mac OS X). At low magnification (2x here), the eye sees smoother shapes rather than color fringing. Compare the horizontal bars in the letter ‘e’, or the descenders in the letter ‘g’, with those in Fig. 1.

It is possible to draw text on Mac OS X with anti-aliasing completely disabled, as in Fig. 2, by calling CGContextSetShouldAntialias(context, false). To draw text as in figure one, call CGContextSetShouldAntialias(context, true) and CGContextSetShouldSmoothFonts(context, false).

Now let’s take a closer look at sub-pixel anti-aliasing. This is the default drawing method. Figure 3a shows text zoomed to twice its actual size. To see how sub-pixel anti-aliasing works, we need to zoom in more—4x (Figure 3b) or even more (Figure 3c).

Fig. 3b: At 4x magnification, color fringing starts to become apparent, if mostly subtle.

Fig. 3c: 10x magnification. Color-fringing is now obvious.

At 10x magnification, we can clearly see the use of red pixels on the left side of glyphs and blue pixels on the right. But does it always work this way? Consider Figure 3d—white text on a black background.

Fig. 3d: Inverse—white text on a black background. Notice how the red and blue edges are reversed.

Blue on the left, red on the right! The question you might ask: Is this because the text is now white, the background is now black, or both? Well, what do we get if we change the text back to black, and change the background to a moderately dark color?

Fig. 3e: Black on a dark orange background. To the eye, the sub-pixels look similar black-on-white (c.f. Fig. 3c). A more careful look reveals differences: Are the right edges blue here?

We see here that the color of the text matters most. But if we look closely at Figure 3e, we can see that the left edge isn’t the same color as in Figure 3c, and the right edge pixels are very different. This leads us to important, if unexpected lesson:

Sub-pixel anti-aliasing depends on both the color of the text and the color of the background. It is impossible to correctly apply sub-pixel anti-aliasing unless we know what the background contains.

These brings us to the practical portion of this article. Under what conditions will sub-pixel anti-aliasing fail (not appear, or appear incorrectly)?

  • The application has called CGContextSetShouldAntialias(context, false);
  • The application has called CGContextSetShouldSmoothFonts(context, false);
  • The application has called CGContextSetAllowsAntialiasing(context, false);
  • The context has no background (or has been filled with a color with alpha=0)
  • The application draws text first, then later fills in the background color (for example, to highlight text or show the selection). You should always draw highlighting before you draw the text.
  • If you change a view to use a CALayer (for CoreAnimation), you will now be drawing that view without any background, unless that view draws its own background. In Interface Builder, check “Draws Background” and explicitly set the background color, usually to windowBackgroundColor.

There are a couple more “gotchas.” First, Mac OS X Snow Leopard does not recognize all third-party display as being compatible with sub-pixel rendering, and may therefore disable it system wide.1 If you suspect this is happening to you, try the following command at a Terminal prompt:
defaults -currentHost write -globalDomain AppleFontSmoothing -int 2

Also, Core Graphics has, by default, a y-axis that extended upwards, rather than downwards, as in most other graphics systems. It is tempting to reverse the y-axis, draw offscreen, then flip it back when blitting to the screen. But there’s a catch: this breaks text anti-aliasing (the chief symptom is blurry serifs and other horizontal lines). Do not draw upside-down unless you intend the text to be viewed upside-down. I hope I don’t need to tell you that drawing text backwards and flipping will have terrible results.

1 10.6: Re-enable LCD font smoothing for some monitors

Stephen Fry on the iPad

“One melancholy thought occurs as my fingers glide and flow over the surface of this astonishing object: Douglas Adams is not alive to see the closest thing to his Hitchhiker’s Guide [to the Galaxy] that humankind has yet devised.”
– Stephen Fry

Read more

Carl at 2½ months

A new photo set, Carl with his mom, is now on Flickr.

carl-and-anna-6323

Web site browser agents (2010 edition)

Okay, it has now been a year since I published web browser statistics for my various sites, so this seems like a good time to take stock of how things have changed over the past year.

Take Internet Explorer 6 users (please!), for instance. Surely their numbers have fallen?

Here are my overall numbers for March 2009 to March 2010:

  • 64% MSIE
  • 20% Firefox
  • 10% Safari
  • 6% Others (3% Chrome, 2% Opera)

So for the past year, MSIE usage actually increased, Firefox and Safari fell; Others held their own.

The Internet Explorer breakdown:

  • 38% MSIE 6.0
  • 36% MSIE 7.0
  • 26% MSIE 8.0

MSIE 8 has now been released for just over 12 months; and yet, it is only the third most popular version of Internet Explorer. Internet Explorer is the only browser with an upside-down adoption rate. Last year, MSIE 7 was the most popular version; this year, perversely, it is MSIE 6. MSIE 6 went up six points compared to last year.

Sigh.

Firefox:

  • 42% Firefox 3.5
  • 42% Firefox 3.0
  • 8% Firefox 2.0
  • 7% Firefox 3.6

Firefox 3.6 has only been out for about two months, so it’s on track for a 42% share of the Firefox segment. Firefox 2.0 had the most share last year, at 48%. Quite a contrast with MSIE.

Safari:

  • 57% Safari 4.0
  • 15% Safari 4.0 (mobile – iPhone/iPod Touch)
  • 10% Safari 3.2
  • 6% Safari 3.1
  • 5% Safari 3.1 (mobile)
  • 7% Safari 3.0, 4.1, and 2.x

iPhone/iPod share has increased slightly, from 15 to 20%. A year ago, 3.2 was new, and version 3.1 had the largest share.

I thought about blogging about this several months ago, but never got around to it. And don’t skip reading the comments.

« Older entries § Newer entries »