This document contains a proposal to make the high-dpi scaling approach Qt uses on the Apple platforms a cross-platform solution. It is intended to be a working document where we keep a record of the ongoing discussion.
This high-dpi mode is an alternative to the traditional DPI scaling. In the traditional approach the application is presented with an DPI value used to multiply font sizes, layouts etc. In the new mode the operating system provides Qt with a scale factor which is used to scale graphics output: allocate larger buffers and set a scaling transform.
The advantage of this approach is that that vector graphics and fonts scale automatically and existing applications tend to work unmodified. Raster content handling is a neutral point - the app author needs to provide high-resolution artwork but this is manageable. A typical disadvantage is confusion caused by the existence of two coordinate systems: “Are these style hints in device independent or device pixels?"
Key points of this proposal are:
Scaling is implemented for the QtQuick and QtWidgets stacks, as well as general support in QtGui and the Cocoa platform plugin.
The OS scales window, event, and desktop geometry. The cocoa platform plugin sets the scaling factor as QWindow/QScreen::devicePixelRatio, as well as on the backing store.
On the QtWidget side QPainter picks up devicePixelRatio from the backing store and interprets it as a scaling factor.
On the QtQuick side [TODO]
OpenGL is special and is always in device pixels. Geometry passed to for example glViewport() needs to be scaled by devicePixelRatio().
Fonts: The specified font sizes (in points or pixels) does not change. The fonts are scaled as a part of painting.
A 12pt font is effectively 24pt with 2x scaling. A string retains its relative size compared to the rest of the UI.
A 12px font also effectively 24px with 2x scaling. px is interpreted as device-independent pixels. This is debatable, but doing it this way preserves the property that things don’t suddenly get smaller when you move to a high-dpi screen, which is important.
We can build on the existing Mac work. There are two ways to make this happen:
The suggestion is to do both. Additional QtWidgets and QtQuick work is not needed, in the sense that we in any case have to do general bugfixing and development for OS X and iOS.
1. OS / Platform plugin support
WinRT (merged) and Wayland (patches)
2. Cross-platform support
Add a coordinate scaling layer to QtGui. The scale factor can controlled by either the the developer/user (env. variable) or the platform. The change is opt-in.
Patch series: https://codereview.qt-project.org/#/c/86107/
The benefits of adding scaling to QtGui is:
At some costs:
Future work
Non-integer scale factors is not guaranteed to give glitch-free graphics. This needs to be investigated further. It should be noted that OS X supports a variant of this with the “larger text” <-> “more space” setting in the system preferences. The resolution is then further virtualized: the app still sees a 2X scale factor.
Q&A
Q: Why not expose a scaling factor to the application, which it can then use to scale layouts?
A: This has several drawbacks:
Q: Why not use physical measurement units like mm?
A: This is problematic:
Together this makes using physical units impractical as the only scaling API. We can still provide this for special cases, for example when the target device specs are known.