diff options
author | Daniel Teske <qt@squorn.de> | 2016-11-22 10:39:26 +0100 |
---|---|---|
committer | Morten Johan Sørvig <morten.sorvig@qt.io> | 2017-03-28 05:23:53 +0000 |
commit | 3398d9d40cb0dae2dc2a1a4f7dc3b4b9cceae903 (patch) | |
tree | bc16fcbf89cbc9cee847269fabcfac95adfc1465 /src/widgets | |
parent | 9292ea17a0fc62406ba751e1c0cca462b373e7ae (diff) |
Fix clipping of graphics effects in high dpi mode
Consider this pseudo code:
setSystemClip(region);
setSystemTransform( scale 2x );
setSystemTransform( scale 2x );
The second call to setSystemTransform should be a noop. Yet, with
the current code in setSystemTransform, the region would be scaled
twice by 2x and thus the clipping would be incorrect.
Fix that by saving the original untransformed clip and in
setSystemTransform recalculate the effective transform.
This is also a better fix for QTBUG-44067 /
sha: 083a945c166b325298a43ba591b1338d1b0f99b6, since with this patch
the order in which system clip, viewport and transform are set does
no longer matter.
Task-number: QTBUG-57257
Task-number: QTBUG-55698
Change-Id: Ibc232822e97ab116f7173a0cc50bba5a367619d8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 27 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 2 |
2 files changed, 16 insertions, 13 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 1452bb36ae..7c62edeb2f 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -2102,14 +2102,15 @@ QRegion QWidgetPrivate::clipRegion() const return r; } -void QWidgetPrivate::setSystemClip(QPaintDevice *paintDevice, const QRegion ®ion) +void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion ®ion) { // Transform the system clip region from device-independent pixels to device pixels - QPaintEngine *paintEngine = paintDevice->paintEngine(); QTransform scaleTransform; - const qreal devicePixelRatio = paintDevice->devicePixelRatioF(); scaleTransform.scale(devicePixelRatio, devicePixelRatio); - paintEngine->d_func()->systemClip = scaleTransform.map(region); + + paintEngine->d_func()->baseSystemClip = region; + paintEngine->d_func()->setSystemTransform(scaleTransform); + } #ifndef QT_NO_GRAPHICSEFFECT @@ -5189,6 +5190,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, // Save current system clip, viewport and transform, const QTransform oldTransform = enginePriv->systemTransform; const QRegion oldSystemClip = enginePriv->systemClip; + const QRegion oldBaseClip = enginePriv->baseSystemClip; const QRegion oldSystemViewport = enginePriv->systemViewport; // This ensures that all painting triggered by render() is clipped to the current engine clip. @@ -5202,9 +5204,8 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, d->render(target, targetOffset, toBePainted, renderFlags); // Restore system clip, viewport and transform. - enginePriv->setSystemViewport(oldSystemViewport); - enginePriv->setSystemTransform(oldTransform); - enginePriv->systemClip = oldSystemClip; + enginePriv->baseSystemClip = oldBaseClip; + enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport); // Restore shared painter. d->setSharedPainter(oldPainter); @@ -5495,12 +5496,12 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore); sourced->context = &context; if (!sharedPainter) { - setSystemClip(pdev, rgn.translated(offset)); + setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset)); QPainter p(pdev); p.translate(offset); context.painter = &p; graphicsEffect->draw(&p); - setSystemClip(pdev, QRegion()); + setSystemClip(pdev->paintEngine(), 1, QRegion()); } else { context.painter = sharedPainter; if (sharedPainter->worldTransform() != sourced->lastEffectTransform) { @@ -5509,7 +5510,9 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } sharedPainter->save(); sharedPainter->translate(offset); + setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatioF(), rgn.translated(offset)); graphicsEffect->draw(sharedPainter); + setSystemClip(sharedPainter->paintEngine(), 1, QRegion()); sharedPainter->restore(); } sourced->context = 0; @@ -5561,7 +5564,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP #endif if (sharedPainter) - setSystemClip(pdev, toBePainted); + setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted); else paintEngine->d_func()->systemRect = q->data->crect; @@ -5579,7 +5582,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } if (!sharedPainter) - setSystemClip(pdev, toBePainted.translated(offset)); + setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted.translated(offset)); if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) { #ifndef QT_NO_OPENGL @@ -5647,7 +5650,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP else paintEngine->d_func()->currentClipDevice = 0; - setSystemClip(pdev, QRegion()); + setSystemClip(pdev->paintEngine(), 1, QRegion()); } q->setAttribute(Qt::WA_WState_InPaintEvent, false); if (Q_UNLIKELY(q->paintingActive())) diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 858328e618..2c397aec88 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -409,7 +409,7 @@ public: QRect clipRect() const; QRegion clipRegion() const; - void setSystemClip(QPaintDevice *paintDevice, const QRegion ®ion); + void setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion ®ion); void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const; void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0, bool alsoNonOpaque = false) const; |