[Development] High-dpi Qt best practices

Sorvig Morten Morten.Sorvig at digia.com
Wed Oct 10 11:39:59 CEST 2012

On Oct 9, 2012, at 1:55 PM, Christoph Feck <christoph at maxiom.de> wrote:

> On Tuesday 09 October 2012 10:37:50 Sorvig Morten wrote:
>> While preparing an upcoming blog entry I've collected some best
>> practices regarding raster graphics (QImage and QPixmap). These
>> apply to internal Qt development as well. The patch is still
>> pending so they are open for discussion.
> From what I know, OS X applications do not use something similar to 
> QLayout. Widgets are positioned in absolute pixel coordinates, so they 
> cannot adapt to different font sizes. To make it less of a burden to 
> port those applications, Apple decided to keep the metrics, and let 
> the OS scale them to larger pixels.
> To be honest, I do not like the idea to introduce the same artificial 
> scaling factor to Qt. Our layout system already adapts to different 
> text pixel sizes automatically. The added API looks complicated and I 
> am irritated where I have to apply a scaling factor, and where not. 
> Additionally, it is not clear, if I have to multiply with or divide by 
> that factor.
> Examples:
> Lets say I want to draw text to a high resolution pixmap. What should 
> I be doing? Does fontMetrics.height() return physical pixels or 
> artificial points? Do I have to multiply the font point size, or use 
> the font size the user has configured unmodified? What if I place text 
> besides a pixmap that has text rendered into it, i.e. how can I make 
> sure they are equally sized? How does font.setPixelSize() work?

This is actually really simple:
1) Keep your existing code/write it as you otherwise would
2) Double the width and hight of the pixmap
3) call setDpiScaleFactor(2)

If you're drawing to the backing store then 2) and 3) is done for you. We could add a function for automatically creating a pixmap suitable for caching.

> Can widgets be positioned exactly on high-DPI applications, not only 
> in steps of 2 pixels (widget coordinates are integers)? This could 
> introduce gaps, which can be visible even on high-DPI displays 
> (imagine a white line between two black boxes).

I'm going for steps of two pixels, which gives a clear "pixel ownership" model. I think this is one of the drawbacks of free-scaling dpi - there's a potential for introducing painting error gaps.

> What happens when I save() a pixmap to a file? Is the scaling factor 
> kept in a way, so that loading it again results in pixel-identical 
> resolution? Is the DPI reported by the file changed as well?

Save the file with a "@2x" filename suffix and the dpi will be set on load. Sounds like a hack and is, but works well in practice for the more common case of loading high-dpi artwork.

> If I understand correctly, existing applications will automatically be 
> upscaled by the Quartz compositor, so here we do (and cannot) change 
> anything.

Yes and no. You describe the default behaviour. However, you can set the "wants high-dpi" flag and get high-dpi text, vector graphics and mac style for for free without further modifications to the application.

Seeing Qt Creator run with high-dpi content without changing it or Qt was what sold me on this approach.

> For new applications, that say they are aware of high-DPI displays, we 
> want to address each pixel on the screen individually. To do this, the 
> dimensions of pixmaps must be in pixels. How big they eventually 
> appear physically on screen is controlled by the screen's DPI setting, 
> which is also used to convert font point sizes to pixel sizes. 
> Applications that want to use units such as "cm", need to query the 
> screen's DPI setting anyway.
> What I would be doing is this: For applications that say they are 
> high-DPI aware, simply return the screen's DPI, which could be 144 
> dpi, or even 384 dpi. For other applications, return a legacy DPI 
> (e.g. half the value, depending on what scaling factor the compositor 
> uses for legacy applications).
> QStyle has functions to return different icon sizes, and the values 
> they return should be bigger for aware applications. If the graphics 
> supplied is not large enough, Qt should automatically scale it (as far 
> as I know, it refuses to do it in current versions).
> To me this sounds much less work to adapt an application. What am I 
> missing?

See point about Qt Creator above. 

Also I don't think I've been sufficiently clear that what I'm implementing is a 2x scaling of the _physical_ dpi or "pixels per inch". The logical dpi is left as-is.


More information about the Development mailing list