Details
-
Bug
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
6.5, dev
-
None
Description
Most noticeable with small rectangles, full corner radius, and HiDPI screens (or alternatively QT_SCALE_FACTOR=5 env).
QSGBasicInternalRectangleNode (instantiated, for example, by a plain QtQuick/Rectangle QML type) does not account for Device Pixel Ratio of its render window, resulting in poor quality circles on Retina-like displays:
(scale factor 5, QtQuick/Rectangle on top vs. Kirigami/ShadowedRectangle — a rectangle with custom shaders — on the bottom)
The culprit is here, in QSGBasicInternalRectangleNode::updateGeometry method:
float outerRadius = radius; // Number of segments per corner, approximately one per 3 pixels. int segments = qBound(3, qCeil(outerRadius * (M_PI / 6)), 18);
If you change that lower bound from 3 to, say, 10, then you'll get higher quality small circles.
But this radius thing does not account for HiDPI. even though in QQuickRectangle::updatePaintNode there's one mention of scaling:
qreal penWidth = d->pen->width(); if (d->pen->pixelAligned()) { qreal dpr = window() ? window()->effectiveDevicePixelRatio() : 1.0; penWidth = qRound(penWidth * dpr) / dpr; // Ensures integer width after dpr scaling } rectangle->setPenWidth(penWidth); rectangle->setAligned(false); // width rounding already done, so the Node should not do it
and what's even more interesting, software rendered can access such data via QPainter API:
void QSGSoftwareInternalRectangleNode::paint(QPainter *painter) { //We can only check for a device pixel ratio change when we know what //paint device is being used. if (!qFuzzyCompare(painter->device()->devicePixelRatio(), m_devicePixelRatio)) { m_devicePixelRatio = painter->device()->devicePixelRatio(); generateCornerPixmap(); }
But I can't find anything suitable in SGNode or context classes. Maybe m_devicePixelRatio has to be uplifted from QSGSoftwareInternalRectangleNode to its parent class QSGInternalRectangleNode?