The default QML coordinates / size units
-
Hi,
I'm having trouble finding out about what the size units / coordinates used in QML are. I mean the ones you use when writing sizes/positions without specifying any unit extension, for example:
Rectangle { x: 10; y: 20; width: 30; height: 40 }
The assumptions I have so far, which I've gathered from reading bits here and there, are as follow:
- The units for those coordinates are called "logical dots" (Are logical dots and "device-independent pixels" the same thing?)
- They have a relationship to "physical dots", defined by values you can query from QScreen: http://doc.qt.io/qt-5/qscreen.html
- "Physical dots" are the actual hardware screen pixels on the device (This one I'm not sure about, is this so? Or is there another layer of abstraction?)
- The relationship between "logical dots" (also "device-independent pixels"?) and "physical dots" is undefined - that is, you can query it at run time, but you can't, in general, say that "logical dots" has some constant dpi, so that the "logical"/"physical" ratio is always the ratio between the constant logical dpi and the actual screen dpi of the current device you're running on (like Android "Density-independent pixels" which are logical units always guaranteed to be 160dpi: http://developer.android.com/guide/practices/screens_support.html)
But I can't find a resource that explicitly states / corrects any of this.
Anyone care to confirm / correct any of these, or explain / point me to a resource that explains this?
Basically, is there a way of specifying sizes in some simple units that will guarantee a certain physical size on any (iOS/Android) device, without doing the math based on what QScreen returns manually?
Thanks!
-
Alright, after some experimentation - most of that is just wrong :)
What the "logical dots" and "device-independent" pixels are, I still don't know, but the units used by default by QML seem to be "physical dots". These do not match actual screen pixels though, at least not always. It seems you need to multiply "physical dots" by QScreen::devicePixelRatio to get the actual on screen pixels (and even then, on newer "Retina" type displays you will get some, hardware forced I assume, downsampling before going to the actual physical pixels on the screen: http://www.paintcodeapp.com/news/iphone-6-screens-demystified). On Android, "physical dots" seem to match actual on screen pixels 1:1 though, but I'd recommend still multiplying by devicePixelRatio, just to be safe against future Android devices where this does not hold.
In short, for a fullscreen app:
- QScreen::size()*QScreen::devicePixelRatio() will give you the actual screen resolution in actual hardware pixels
- QScreen::physicalDotsPerInch()*QScreen::devicePixelRatio() will give you the actual physical pixel ppi/dpi, of course
- numInches*QScreen::physicalDotsPerInch() will give you the number of "physical dots" (the value you should give to QML), if you want something to be "numInches" inches long
- numPixels/QScreen::devicePixelRatio() will give you the number of "physical dots", if you want something to be "numPixels" actual pixels long on the actual screen.
Keep in mind though, that on iPhone 6 Plus (and other similar newer "Retina" type displays, I assume) even this will not give you direct access to actual on screen pixels 1:1 - it's just not possible. You will be rendering with 1:1 pixel precision to a 1242×2208 buffer, which will then get downsampled by a factor of 1.15 to 1080×1920 when actually displayed on screen, see: http://www.paintcodeapp.com/news/iphone-6-screens-demystified - it might not be that bad, everything you draw will simply have some hardware forced "anti-aliasing" of sorts, which might be bad or good, you decide, but there is no way of getting directly 1:1 to actual hardware pixels, AFAIK.
Please feel free to correct me if I'm still wrong somewhere, or confirm, so this can be more trustworthy and useful to someone in the future.