aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2020-11-27 14:14:39 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2020-11-30 16:38:14 +0100
commitc24f5232ab3672e538259264c83b46671142c318 (patch)
treef8ce2b4fb4584d2892ae8dc0529da28be5e66e14 /src
parent84c44a805adbd12401c645869a73c3cb92f44544 (diff)
qquickstyleitem: let the image size be aligned with dpr
The size of the image we paint the item on should have a size that will return a whole number when it's divided by the current dpr. Otherwise the texture mapping that occurs in the scenegraph later will work on fractions that will cause drawing glitches to occur. Fixes: QTBUG-89006 Pick-to: 6.0 6.0.0 Change-Id: I5e65aebbda9598d88bef7af2398b3fe3f2d16a87 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/imports/nativestyle/items/qquickstyleitem.cpp51
-rw-r--r--src/imports/nativestyle/items/qquickstyleitem.h2
2 files changed, 45 insertions, 8 deletions
diff --git a/src/imports/nativestyle/items/qquickstyleitem.cpp b/src/imports/nativestyle/items/qquickstyleitem.cpp
index 2397525a..cabc6631 100644
--- a/src/imports/nativestyle/items/qquickstyleitem.cpp
+++ b/src/imports/nativestyle/items/qquickstyleitem.cpp
@@ -79,6 +79,26 @@ QDebug operator<<(QDebug debug, const StyleItemGeometry &cg)
return debug;
}
+int QQuickStyleItem::dprAlignedSize(const int size) const
+{
+ // Return the first value equal to or bigger than size
+ // that is a whole number when multiplied with the dpr.
+ static int multiplier = [&]() {
+ const qreal dpr = window()->devicePixelRatio();
+ for (int m = 1; m <= 10; ++m) {
+ const qreal v = m * dpr;
+ if (v == int(v))
+ return m;
+ }
+
+ qWarning() << "The current dpr (" << dpr << ") is not supported"
+ << "by the style and might result in drawing artifacts";
+ return 1;
+ }();
+
+ return int(qCeil(qreal(size) / qreal(multiplier)) * multiplier);
+}
+
QQuickStyleItem::QQuickStyleItem(QQuickItem *parent)
: QQuickItem(parent)
{
@@ -280,17 +300,32 @@ void QQuickStyleItem::updateGeometry()
void QQuickStyleItem::paintControlToImage()
{
qqc2InfoHeading("PAINT");
- if (m_styleItemGeometry.minimumSize.isEmpty())
+ const QSize imgSize = imageSize();
+ if (imgSize.isEmpty())
return;
m_dirty.setFlag(DirtyFlag::Image, false);
- const qreal scale = window()->devicePixelRatio();
- const QSize imgSize = imageSize();
- const QSize scaledImageSize = imgSize * scale;
- if (m_paintedImage.size() != scaledImageSize) {
- m_paintedImage = QImage(scaledImageSize, QImage::Format_ARGB32_Premultiplied);
- m_paintedImage.setDevicePixelRatio(scale);
+ // The size of m_paintedImage should normally be imgSize * dpr. The problem is
+ // that the dpr can be e.g 1.25, which means that the size can end up having a
+ // fraction. But an image cannot have a size with a fraction, so it would need
+ // to be rounded. But on the flip side, rounding the size means that the size
+ // of the scene graph node (which is, when the texture is not scaled,
+ // m_paintedImage.size() / dpr), will end up with a fraction instead. And this
+ // causes rendering artifacts in the scene graph when the texture is mapped
+ // to physical screen coordinates. So for that reason we calculate an image size
+ // that might be slightly larger than imgSize, so that imgSize * dpr lands on a
+ // whole number. The result is that neither the image size, nor the scene graph
+ // node, ends up with a size that has a fraction.
+ const qreal dpr = window()->devicePixelRatio();
+ const int alignedW = int(dprAlignedSize(imgSize.width()) * dpr);
+ const int alignedH = int(dprAlignedSize(imgSize.height()) * dpr);
+ const QSize alignedSize = QSize(alignedW, alignedH);
+
+ if (m_paintedImage.size() != alignedSize) {
+ m_paintedImage = QImage(alignedSize, QImage::Format_ARGB32_Premultiplied);
+ m_paintedImage.setDevicePixelRatio(dpr);
+ qqc2Info() << "created image with dpr aligned size:" << alignedSize;
}
m_paintedImage.fill(Qt::transparent);
@@ -302,7 +337,7 @@ void QQuickStyleItem::paintControlToImage()
if (m_debugFlags != NoDebug) {
painter.setPen(QColor(255, 0, 0, 255));
if (m_debugFlags.testFlag(ImageRect))
- painter.drawRect(QRect(QPoint(0, 0), imgSize));
+ painter.drawRect(QRect(QPoint(0, 0), alignedSize / dpr));
if (m_debugFlags.testFlag(LayoutRect)) {
const auto m = layoutMargins();
QRect rect = QRect(QPoint(0, 0), imgSize);
diff --git a/src/imports/nativestyle/items/qquickstyleitem.h b/src/imports/nativestyle/items/qquickstyleitem.h
index f7659a5c..fdfd7012 100644
--- a/src/imports/nativestyle/items/qquickstyleitem.h
+++ b/src/imports/nativestyle/items/qquickstyleitem.h
@@ -269,6 +269,8 @@ private:
inline void updateGeometry();
inline void paintControlToImage();
+ int dprAlignedSize(const int size) const;
+
#ifdef QT_DEBUG
void addDebugInfo();
#endif