Eyes Above The Waves

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

Wednesday 7 February 2007

Units Patch Landed

Eli Friedman has landed his "units patch" (bug 177805).

This was a monumental effort spanning two years from posting the first patch to finally landing. The original design was proposed (by me, as it happens) back in 2002. Congratulations to Eli for pushing this through to resolution.

This patch is a major cleanup of the way we work with length units in Gecko. The new design is very clean and gives us some important new capabilities. The design revolves around CSS pixels. Think of a CSS pixel as 1/96 of an inch, rounded to the nearest device pixel, assuming the user is looking at a typical desktop screen. It's an abstract measurement that we use to make sure Web sites using measurements in "px" look reasonable. In particular, if the user has a (say) 200dpi screen, we don't want to set one CSS pixel to be one device pixel (as we currently do), because Web pages will simply look too small.

The new design focuses on three clearly defined quantities:

  • The number of "application units" per CSS pixel. We make the "application units" we use for internal layout smaller than CSS pixels because we want to support subpixel positioning of elements. This value is device-independent and currently set to 60.
  • The number of device pixels per CSS pixel. This is device dependent and depends on the device DPI. For devices up to 144 DPI, the value is 1. For 144 up to 240 DPI, the value is 2, and so on, increasing by 1 every 96 DPI. This means that effectively on a 144-240 DPI device, everything is specified by CSS pixels is scaled up by a factor of 2.
  • The number of device pixels per inch. This is just the device DPI. This value is used to convert CSS length-based measurements (e.g., CSS "in" units) to device pixels and then to application units.

The net results are that if you have a high DPI screen, trunk builds will be scaling everything up by a factor of two or more, including Firefox UI. This is basically a good thing except that for now, there are some bugs that make it hard to use. If you can't bear it, you can use about:config to set the preference "layout.css.dpi" to something like 100 to turn the scaling off. (For a good time, you can use this preference to test the scaling feature if you have only a regular screen.)

Also, whatever your DPI, we now support much better matching of CSS physical length values to your actual device. If you draw a 1in x 1in box on the screen, it should really be a square inch if your system DPI is set correctly or you set the preference in Firefox. Up until now it has been a rather poor approximation.

Another benefit of this patch, by the way, is that scaling in printing and print preview has been reimplemented so that you can use any scale factor you like. Up until now only we've only been able to scale at certain mysterious predefined ratios.

This is not the end of the story about scaling, however. User-controlled zooming into Web pages is a separate feature that we will implement for Firefox 3.

For people working with Gecko layout code, this means that the old pixels-to-twips (and back again) conversions have been replaced with new conversion functions in nsPresContext, that convert between application units, CSS pixels and device pixels. Whenever you work with pixels you need to know which sort of pixels you're dealing with. In lower level code without access to an nsPresContext, you can get similar information from an nsIDeviceContext. Note that because the application units to CSS pixels ratio is device independent, you can access it via static methods of nsPresContext and nsIDeviceContext.


That sounds great. Does that mean firefox is moving to SVG icons?
And when are we getting the ability to set the angle of a DIV? I want my text to be like on Tony Hawks, all at slightly different angles between -5' and 5'
Robert O'Callahan
I don't think we're moving to SVG icons anytime soon. They still take up more resources than bitmapped icons.
You can rotate DIVs today (in trunk builds) using SVG and foreignobject.
Jesse Ruderman
Will Gecko 1.9 give web pages a way to point to high-resolution versions of images, without forcing users with normal screens to download and scale? Preferably with the same syntax as Webkit?
Will Firefox 3 include higher-resolution icon toolbar button icons?
Robert O'Callahan
I don't know about the icons. It would be easy to include higher-res icons.
What syntax does Webkit use? In bug 177805 I suggested including the device-to-CSS-pixel ratio in the useragent string so that servers can send higher-res images. Another alternative would be a new HTTP header for image loads.
Niels Leenheer
Webkit uses a combination of CSS3 features:
- the new background-size css property
- the ::marker pseudo element
- media queries for requesting a high res stylesheet
More info:
@ Jesse: You mean bring back the old "lowsrc" attribute? :)
Peter Van der Beken
Roc: Safari uses media queries, see the "Conditional Inclusion" section in http://webkit.org/blog/?p=55
Matt Smith
Very interesting. Did this get into Alpha 2 or was it just after like the reflow branch in Alpha 1?
Robert O'Callahan
This landed after we branched for Alpha 2.
media queries would be a good way to go. Relying on UA strings is open to abuse and misinterpretation, as for http headers, most people often don't have enough control over their servers.
BTW David Baron was working on media queries in bug 156716. Would be nice to have that in Gecko 1.9 (parity with Opera and Webkit)
Eugene Lazutkin
1/96 in. works perfectly for 96 DPI displays. Not so well for anything else (120 DPI, 150, and so on). Just out of curiosity: why don't you use smaller units? For example typographers use twips (1/20 pt. => 1/1440 in) for ages. It is a well-known real-world unit. 96 DPI pixel is exactly 14 twips, 120 DPI is exactly 12 twips, and so on.
Eugene Lazutkin
Oh, I missed the last paragraph, which talks about twips. Please disregard my previous question.
Justin Dolske
I'm curious how this might affect mobile devices?
On a high-dpi desktop display, it makes sense to draw things bigger (pixel-wise) so that they don't look abnormally small.
But on a mobile device, part of the advantage of a high-dpi display is that you can squeeze more into a smaller space. For example, my Nokia N800 has 800x480 screen with a ~4" diagonal, which works out to 225dpi.
I suppose it would be easy to just lie to Firefox about the real dpi of the display, although I wonder if that's always what a user would want.
Axel Hecht
To forward a report from #firefox.de, we had a user with a DPI setting of 106 complaining about images jumping a few pixels left and right when moving over them with the mouse. Resetting the DPIs to something less odd fixed that. Tomcat and I made him test a post-Eli trunk build, too, which fixes that issue. YAY.
Thanks to Araeon for putting a minefield on his machine.
Rolf Bode-Meyer
How does Gecko know the resolution of the disply device? Once upon a time there was some line to measure and an edit field to enter the result. But I can't find it in the current Seamonkey trunk nightly (Linux).
Robert O'Callahan
We use OS-specific APIs to get that information.
Jason Bourke
I have had terrible trouble with DPI in firefox after switching from Windows to Linux. IE seems to respect the DPI setting and Firefox not. Most sites in Firefox are displayed too small on my laptop, using only half the screen.
So I've downloaded both the latest and the 3.0 alpha nightly after reading about this update, and I was disappointed. the doesn't seem to do anything different. The 3 alpha displays at one resolution for DPI numbers up to 143 and then flips to another resolution for DPI numbers 144 and above. The first is too small and the second is too big.
Am I missing something?
I had exact same problem as Robert O'Callahan. While I couldn't find a solution to it, I found a workaround by setting the tools/options/content/Fonts and colors/advanced/font sizes to a higher number like 16 or 18. The text become readable, but the problem with graphics rendering stays on.
Btw, my screen is a 15.4" UXGA(1920x1200)