[plasma/union/Plasma/6.7] src/output/qtquick/plugin: output/quick: Align icon to device pixels
Arjen Hiemstra <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 1e562866a6734c68160fae1e23250aae95b264e0 by Arjen Hiemstra. Committed on 04/08/2026 at 07:49. Pushed by ahiemstra into branch 'Plasma/6.7'. output/quick: Align icon to device pixels This aligns the image node of Icon to device pixels based on scene coordinates. This ensures we never render on fractional pixels, which causes rendering artifacts. (cherry picked from commit 13f0908d1c1133efdfd00291330194e16aaa05b6) Co-authored-by: Arjen Hiemstra <[email protected]> M +17 -12 src/output/qtquick/plugin/Icon.cpp https://invent.kde.org/plasma/union/-/commit/1e562866a6734c68160fae1e23250aae95b264e0 diff --git a/src/output/qtquick/plugin/Icon.cpp b/src/output/qtquick/plugin/Icon.cpp index df43ae7f..9195f568 100644 --- a/src/output/qtquick/plugin/Icon.cpp +++ b/src/output/qtquick/plugin/Icon.cpp @@ -46,6 +46,7 @@ Icon::Icon(QQuickItem *parent) : QQuickItem(parent) { setFlag(QQuickItem::ItemHasContents, true); + setFlag(QQuickItem::ItemObservesViewport, true); setSmooth(false); } @@ -173,12 +174,18 @@ QSGNode *Icon::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) auto imageNode = static_cast<QSGImageNode *>(node); - auto bounds = boundingRect(); + auto renderWindow = QQuickRenderControl::renderWindowFor(window()); + if (!renderWindow) { + renderWindow = window(); + } - imageNode->setRect(QRectF{std::round(bounds.x() + (bounds.width() - m_iconSize.width()) / 2.0), - std::round(bounds.y() + (bounds.height() - m_iconSize.height()) / 2.0), - qreal(m_iconSize.width()), - qreal(m_iconSize.height())}); + auto dpr = renderWindow->devicePixelRatio(); + + auto bounds = boundingRect(); + auto centerPos = mapToScene(QPointF{std::round(bounds.x() + (bounds.width() - m_iconSize.width()) / 2.0), // + std::round(bounds.y() + (bounds.height() - m_iconSize.height()) / 2.0)}); + auto correctedPos = mapFromScene(QPointF{std::round(centerPos.x() * dpr) / dpr, std::round(centerPos.y() * dpr) / dpr}); + imageNode->setRect(QRectF{correctedPos, m_iconSize.toSizeF()}); imageNode->setOwnsTexture(true); if (smooth()) { @@ -187,18 +194,12 @@ QSGNode *Icon::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) imageNode->setFiltering(QSGTexture::Nearest); } - auto renderWindow = QQuickRenderControl::renderWindowFor(window()); - if (!renderWindow) { - renderWindow = window(); - } - - auto dpr = renderWindow->devicePixelRatio(); - if (m_iconChanged || !imageNode->texture() || !qFuzzyCompare(m_iconDpr, dpr)) { const auto mode = isEnabled() ? QIcon::Mode::Normal : QIcon::Mode::Disabled; auto image = m_icon.pixmap(m_iconSize, dpr, mode).toImage(); imageNode->setTexture(window()->createTextureFromImage(image, QQuickWindow::TextureCanUseAtlas)); m_iconChanged = false; + m_iconDpr = dpr; } return node; @@ -221,6 +222,10 @@ void Icon::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChang update(); } + if (change == QQuickItem::ItemChange::ItemTransformHasChanged) { + update(); + } + QQuickItem::itemChange(change, value); }