-
Suggestion
-
Resolution: Done
-
Not Evaluated
-
None
-
None
-
None
We're faced with a number of different problems. Various screens have different physical sizes and various actual pixel densities. There is also the problem of distance from the the viewer to the screen. In addition to this, Apple platforms have introduced "device pixel ratio" which applies an integer scale factor to while reporting a fake lower dpi, to provide a compatibility layer so applications can just scale up automatically to take advantage of the higher DPI.
The device pixel ratio concept is flawed as it only works on dpis that are close to integer multiples of the base dpi. For anything else it will either result in physical dimensions being wrong on screen or we must apply non-integer scale factors which result in pixelation artifacts.
The dpr idea is further complicated by that our aliased QPainter drawing mode follows X11 and win32 fill rules and will typically snap towards lower-right for single-pixel wide graphics. (CoreGraphics uses a 50% coverage rule and doesn't have this problem. Raster had this in the very beginning, but all our styles looked horrible and we didn't quite understand the full problem at the time, so we use X11 and win32 fill rules for aliased)
So as a general solution, dpr will never be an acceptable solution for Qt. It runs on an arbitrary range of dps from 50-400+ and we need something that can work for all.
Consider also a TV set 5 meters away from the viewer. In theory we want a unit that can represent that sensibly as well as handling the 300 dpi phone we are holding at a hands distance.
One idea is to expose pixels per centimeter and pixels per inch, and this does cover all dpis, but it fails to factor in distance to the viewer and the height the TV has compared to the hand held phone.
If we instead look at the viewing angle and base the unit on that, it all becomes more sensible. Say our horizontal viewing angle is about 180 degrees (reference needed) and the vertical one is 120 degrees. In terms of degrees, both the phone and the TV take up about 20-30 degrees of our vertical viewing angle. A 1 cm tall button might take up 2 degrees and the default font size could be maybe 0.5 degrees.
If we don't want to burder our users with a public API for this, one way to solve this in QML is to set "unit" as a QML context property. The unit represents how many pixels per degrees of the viewing angle. We can of course also throw in "cm" and "inch" into the context for apps that don't care about the distance to the viewer, and that is nice for convenience.
Screen changes are a bit tricky.. Either we update the unit and everything is laid out again when moving from one screen to the next (which is probably not what anyone wants). Alternatively we pick this based on primary screen and stick with. At least that will give us 99% of what we need. Incidentally this also solves the project case as well..
Now what about retina screens? Well, if preserve the dpr on the retina screen and let QQuickWindow scale up for while giving the user the degrees based unit based on the base dpi (non-retina) it "should just work".
Distance to the observer is pretty much only known by the app developer though, so this is more a documentation task than anything else. Qt can internally make the assumption that monitors are 80cm away, phones and tables are 40cm away. Televisions are 5 meters away, but that would have to be set through QScreen::setDistanceToObserver() or similar API. Or we just document that this is how to tackle the problem.
TLDR: introduce a unit based on pixels / degrees of viewing angle. Either by documenting how with examples or by adding convenience API.