Eyes Above The Waves

Robert O'Callahan. Christian. Repatriate Kiwi. Hacker.

Tuesday 22 January 2008

Subpixel Layout And Rendering

John Resig has discovered that Gecko does subpixel layout and rounds coordinates to device pixels for rendering.

He's right that in some sense, when you have to render a CSS layout to a screen with discrete pixels, all the options are imperfect and browsers are choosing different imperfect options. However I think we need to explain the big picture a little better.

Gecko intentionally supports subpixel layout because for high resolution output devices, especially printers but also high-DPI screens that will become more common, one CSS "px" should be mapped to many device pixels, so you can in fact do sub-CSS-pixel rendering. For those devices, rounding layout units to CSS pixels is actually throwing away information and giving you a strictly worse layout than Gecko will give. For example, try printing John's example in FF3 beta. You should see that in the printout (or generated PDF), no rounding has occurred and each child DIV looks identical.

Because we think this is important and we don't want layout to vary unnecessarily across devices, we do subpixel layout on all devices. When we have to draw to a regular-DPI screen, we then have to round the edges of drawn objects to the nearest screen pixel. This explains the results John sees. Note that our approach of rounding at drawing time is optimal for avoiding gross layout changes due to rounding; it limits the impact of rounding to moving object edges by one pixel in some direction. It avoids gross layout changes like IE moving a DIV to the next line, or Safari leaving a 2px strip vacant at the end of the line. Thus I believe our approach is better than the alternatives in important ways.

The preceding paragraph is actually a slight oversimplification. We do have to do some rounding during layout simply due to the fact that computer arithmetic has limited precision. So during layout we round measurements to the nearest 1/60th of a CSS pixel. This number was chosen so that common fractions of a CSS pixel can be represented exactly --- for gory details, check out the great "units" bug and my comments about its landing. Note that rounding to 1/60th of a CSS pixel is far more benign than rounding to CSS pixels; 1/60th of a CSS pixel is approximately 1/5760th of an inch, not something most people are going to worry about!

In practice, we have seen very few Web compatibility issues caused by this scheme. Web authors should just not worry about the rounding we do, and should not attempt to round coordinates themselves. The new getBoundingClientRect and getClientRects APIs in FF3 can return fractional coordinates, just go with the flow. Feel free to position elements at those fractional boundaries, they will line up visually. If you insist on consistent rendering down to the pixel, then the only way to go is to specify px values for everything, including line-heights, and avoid percentage units. Or better still, use SVG. Or a PNG.


Justin Dolske
Rounding to 1/60th of a CSS pixel is also useful for drawing to Sumerian clay tablets. Hooray for sexagesimal number systems!
Reminds me very much of the platform differences of the font rendering technologies:
Whereas with fonts, it's acceptable to have a little blur - but with CSS box borders it's not acceptable.
Hrm. Gecko trunk (WinXP, 2008011403, 1280x1024 screen) shows the end of your entry "still, use SVG. Or a PNG." underneath the first column, rather than ending the third column. Regression since the 1.8 branch.
Before I go track down a regression range, any idea if that's filed already?
Jon Smirl
How about subpixel rendering/positioning on LCDs for objects as well as text? MS Cleartype subpixel positions the text, I don't believe Cairo/Pango subpixel position, they only subpixel render.
Robert O'Callahan
Sander: I don't think it is!
Jon: actually that reminds me --- we do use horizontal subpixel offsets for text rendering on Mac and GTK. We have to round vertical offsets for tricky reasons to do with underlines. And yes, in theory we could have subpixel rendering of everything, but it wouldn't look good since we don't want fringing on horizontal or vertical object edges and there are hardly any other kinds of edges in most Web content.
roc: it actually disappeared on the reload right after posting (I _thought_ I'd reloaded the page before posting, but apparently not (or something was cached quite well)), and I haven't been able to reproduce since. It's still weird, but with no reproducible test case or way to test regression range, I guess we'll have to leave it at that. (I'll keep my eye out for it re-appearing, though.)
I saw the misplaced line on first load, but it went away after I adjusted the text size up and down again. (Using Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b3pre) Gecko/2008011910 Minefield/3.0b3pr)
For what it's worth, I've also seen the problem Sander is describing...
Jon Smirl
Fringing is getting really hard to see on current generation LCDs. I have to use a magnifying glass to see it on my $200 22in monitors.
Sometimes people will complain about fringing when the real problem is that they don't have an RGB panel, it may be BGR or vertically oriented. Use the display control widget to set the correct pixel orientation for your monitor. If this is set wrong fringing will be visible.
Look at the bottom of this page and you can see microscope photos of subpixel rendering.
Click on the photos and they get bigger.
Note that the OPLC uses PenTile.
Same as Sander and Boris, and it disappeared on refresh
Happened here to; also, when I tried to zoom (ctrl+wheel) the homepage shrunk to half it's height. Disappeared after reload.
Screen of the first problem