Widget to device pixel alignment under fractional DPI scaling

Alvin Wong alvinhochun at gmail.com
Wed Oct 17 11:02:13 BST 2018


Dear all,

I have some questions on fractional DPI handling. I know fractional
DPI scaling isn't officially supported on Windows (waiting for
[QTBUG-53022][1] to be picked up again), but from what I hear KDE does
support actual fractional DPI scaling. Anyway, it is possible to test
fractional DPI on Windows with these environment variables (this
forces Qt to treat the first monitor as 1.5x scaling and the second
monitor as 1x), and does work kind of fine when it matches native
settings and using the Fusion style:

    QT_AUTO_SCREEN_SCALE_FACTOR=0
    QT_SCREEN_SCALE_FACTORS=1.5;1

I am trying to help get Krita to render the canvas in 1:1 device pixel
mapping. At this point it's certain that it can be made to work under
integer scaling (2x) but now I have some concerns on getting it to
work under fractional scaling (1.5x for example):

1. Does Qt align widgets positions to device pixels? In my
understanding, widget positions are specified in device-independent
pixels (I'll call it DIP for short), which can fall in between whole
device pixels. E.g. if a widget is at (31, 31) DIP, it would be placed
at (46.5, 46.5) px, which is at half pixels. Theoretically, painting a
0.6667 DIP line should result in a pixel-perfect 1px line, but will
this be broken due to the widget position not aligning to device
pixels?
2. Does Qt align widgets dimensions to device pixels? Like above, if a
widget has a width of 123 DIP, it would really be 184.5px. In this
case, and assuming that the left edge lies on a full device pixel,
what would happen to the right edge of the widget? And what if the
left edge is on half of a device pixel? Also, if an application wants
to create a pixel-perfect QBitmap (of devicePixelRatio=1, since the
aim is to paint in device pixels not DIP,) to be painted onto the
widget in full, what should its dimensions be?
3. On QOpenGLWidget: It creates the FBO in device pixels in
`QOpenGLWidgetPrivate::recreateFbo`, but with the code `const QSize
deviceSize = q->size() * q->devicePixelRatioF();` the FBO size is
implicitly truncated to integer. In
`QOpenGLWidgetPrivate::invokeUserPaint`, the OpenGL viewport
dimensions are also truncated to integer. Is there a possibility of
rounding errors, especially when the QOpenGLWidget is not using its
own native window?

The lowest Qt version we target is 5.9.x LTS if it makes any differences.

Best Regards,
Alvin

[1]: https://bugreports.qt.io/browse/QTBUG-53022


More information about the kimageshop mailing list