Let’s say we have a 4″ inch phone and a 8″ tablet, both 1280×720 and we want to draw an icon on them. If we only take into consideration their ppi the button on both devices will have the exact same size. If we blindly use the same pixel size on both devices our icon would be double on the tablet compared to the phone.
In reality we actually need a bit bigger control on the tablet, because the viewer holds the tablet a bit farther away but not double the size.
The problem of units is a big one and until now nobody has solved it well enough. Pixels aren’t the right answer, obviously because of variable pixel densities. Real-life length units aren’t either because of varying viewing distances. 1cm on a phone is huge, on the TV is tiny.
The answer is viewing angle: the proportion of the user’s viewport the control takes.
There is a certain threshold of ppi below which, the actual number of pixels dictates the size of the components, because there isn’t enough detail when trying to do smaller things. This is around 125ppi. On a 96ppi computer screen, you can’t make the favicon any smaller, not because the user would have to squint, but because 16×16 pixels are barely enough to hold the icon. When going over 200ppi, the minimum size of things start to be dictated by what the human eye can distinguish comfortably, i.e. without squinting.
Phones and tablets have mostly got over with such lowly ppi’s so I will not bother again with this problem. If you’re trying to port nemo to a device that has so low ppi that it restricts the minimum size of text and icons, you’ll have to compensate by faking a smaller screen size so that everything is drawn a little bit bigger.
In this particular point in time a weird thing is happening. Almost everything, from your 5″ flagship phone, your 13″ ultrabook, the 24″ inch pc monitor and the 55″ TV, has 1080p. This makes things easy: design a button to be 100x100px and it will be about the same perceived size on any screen. Here’s a table with calculations of the field of view that a 100px element occupies in all the above devices: roughly 1.4 degrees.
|diagonal (in)||height (in)||width (in)||height (cm)||width (in)||ppc (width)||ppc (height)||control size (px)||control size (cm)||viewer distance (m)||control size (angle)|
but this while very nice for our example, isn’t true for everything: lowend phones still have HVGA’s, high end tv’s have 4K and the retina Mac’s have something in-between. We still want to keep the same view angle for the same controls though, and because we can’t measure the viewing distance, it’s wise to infer it.
|Device||Viewing distance (m)|
Now let’s take a small button, like the back button of the N9 browser. It measures around 50px which translates to roughly 0.5cm (N9 has ~100 pixels per cm) so it has a viewing angle of ~1.1°
If the N9 had a 1280×720 resolution, we’d still want 0.5cm to fill a 1.1° viewing angle so we would have to bump up the pixel size to 75px.
On our 8″ tablet with the same 1280×720 resolution we will need a 0.73cm control (52px).
We need a unit of measurment that takes these calculations off the mind of the developer. There are two ways to do this: either patch Qt so that pixel sizes are being multiplied by a size factor, or by having an SIZE_FACTOR constant that the developer has to multiply all sizes with, and that will be different in each device. This size factor will be computed as following:
reference_px_per_mm = 10; reference_viewing_distance = 0.250; viewing_distance = ???; //in meters from above table reference_viewing_angle = atan(1/(reference_px_per_mm*reference_viewing_distance)); viewing_angle = atan(1/(px_per_mm*viewing_distance)); size_factor = reference_viewing_angle/viewing_angle;
here’s a table for some common devices
|Pixels per mm||viewing distance||size of 1px in mm||veiwing angle of 1px||factor|