6 ms·
I worked on resolution independence on OS X over a period of years. I think the above comment is not made with full appreciation of the difficulty of the proble
by ridiculous_fish 12y ago
I worked on resolution independence on OS X over a period of years. I think the above comment is not made with full appreciation of the difficulty of the problem. Supporting arbitrary resolutions well is very difficult.
The underlying frameworks (e.g. CoreGraphics) are absolutely capable of rendering at arbitrary resolutions, and have been for a long time. It's not particularly hard: you interpose an affine transform which converts from local to device coordinates, apply it to all your geometry, and it falls out.
But "rendering at arbitrary resolutions" is not the same as "looks good at arbitrary resolutions." For example, a line 1 px wide at 1x will be 1.5 pixels wide at 1.5x. That means at least one edge must be aligned on a partial pixel, and there's the potential for weird antialiasing effects. There's also a behavior change: you cannot redraw half a pixel, so now "dirtying" a pixel requires redrawing more components at 1.5x than at 1x, which can cause performance problems and other bugs. And there's also a question of which pixels get the partial alignment: do you round in a direction? If so, which one? Or maybe you don't round and you have two pixels that are a quarter covered?
Which leads to the problem of centering. I wish to center a bitmap image within a button's border. The image is 101 logical points high, and the border is 200 logical points high. With a 2x scale factor, I can center absolutely, and still be aligned to device pixels. With a 1x, 1.25, 1.33, etc. scale factor, centering will align me on a partial pixel, which looks like crap. So I have to round. Which way? If the goal is "make it look good," then the answer is "whichever way looks good," which depends on the visual style of the bezel, i.e. whether the top or bottom has more visual weight. So now we need hinting.
And that's where things start to get really nasty. In order to make things look good at arbitrary resolutions, we want to round to device pixels. But the rounding direction is not a local question! Consider what happens if we have two visual elements abutting in logical coordinates, and they round in opposite directions: now there's a device pixel between them. That's very visible: you get a pixel crack! So you have to coordinate rounding.
WPF is a good example of a framework that attempted resolution independence and encountered this problem. Initially it has the "SnapsToDevicePixels" property, which triggers rounding behavior at draw time. But draw time is too late, because of the "abutting elements rounding in opposite directions" problem. So they introduced the "UseLayoutRounding" property, which does...something. And the guidance is basically "turn it on and see if it helps, if not, disable it." Great.
The web also has this problem in spades. Websites break in all sorts of fun ways when you zoom in or out. We tolerate this because, frankly, the bar is super-low for websites.
As I see it, the two options are:
1. Make everything vectors. You'll have to choose between weird antialiasing artifacts and potential pixel cracks; either way things will look bad. And you'll encounter bitmaps eventually, and have to deal with the necessities of resampling and pixel aligning at that point.
2. Scale only to integral sizes, and resample. You'll avoid antialiasing and pixel alignment issues, but pay a performance penalty, and things may look slightly blurry.
So which option is better? #1 has the potential for the highest-quality output, but at a significant price: developers must test their apps at more scale factors, and the failure mode is ugly drawing artifacts or outright bugs. #2 is more utilitarian: the output is not as nice, and you incur a perf penalty, but that's borne by the system instead of the apps, and the overall system is more consistent. #2 is also more forward looking: if you expect that pixel densities will continue to increase, then resampling artifacts will eventually be indiscernible, but a pixel crack will always be visible.
Apple took the practical and forward-looking approach to this problem. I can't fault them: to my knowledge, nobody has successfully implemented true resolution independence in a framework with wide adoption. If they have, I'd love to know how!
- jordanthoms 12y agoWhat about Android? The layout managers there attempt to get good placing of items, dealing with these issues. Agreed it's a hard problem and that comment was certainly reductionist, but at the same time it's depressing to have this be the issue that makes fonts blurry - the hardware is fine but the software side is letting it down.
- acqq 12y ago> at the same time it's depressing to have this be the issue that makes fonts blurry Wait, have you actually seen blurry fonts on the iPhone 6 Plus? Do you know of any photograph which demonstrates them?
- rsynnott 12y agoSomebody with abnormally good eyesight probably could if they knew what they were looking for.
- acqq 12y agoI'm asking for a photo, even with a microscope. I'm really curious, because I still believe the difference can't be seen for the text sizes that are actually readable by humans that don't use magnifying glasses.
- ridiculous_fish 12y agoMy understanding is that Android uses essentially the same strategy as iOS: don't attempt to support full resolution independence, but instead enumerate a set of supported DPIs. See the DisplayMetrics class: there's an enumeration of supported densities, and the 'density' property itself is noted as being a "gross" measure that is rounded to nice values, like 1.5. Of course extra space can absorbed into the screen size instead of its density. Android and iOS support this via their respective mechanisms, like autoresizing masks or autolayout on iOS, and I guess layout managers on Android. If you were to make a new device with unusual screen metrics, you have a few options for app compatibility. You could report an unusual density, and risk ugly antialiasing or pixel cracks. Alternatively, you could report an unusual size, and get bad layouts, where lots of apps will have UI elements overly small, and excessive unused space. Or you could compromise: report sane (but inaccurate) sizes and densities, and resample. This maximizes compatibility, with some quality and performance cost. (The idealized option is true resolution independence, where apps look great at any density and size. To my knowledge, nobody has achieved that.) I figure Apple realized that the iPhone 6+ would be very heavily reviewed, and so wanted to ensure that existing apps would work really well on it. That's what their scaling approach enables.