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>
This commit is contained in:
parent
9292ea17a0
commit
3398d9d40c
@ -929,11 +929,11 @@ QPoint QPaintEngine::coordinateOffset() const
|
|||||||
void QPaintEngine::setSystemClip(const QRegion ®ion)
|
void QPaintEngine::setSystemClip(const QRegion ®ion)
|
||||||
{
|
{
|
||||||
Q_D(QPaintEngine);
|
Q_D(QPaintEngine);
|
||||||
d->systemClip = region;
|
d->baseSystemClip = region;
|
||||||
// Be backward compatible and only call d->systemStateChanged()
|
// Be backward compatible and only call d->systemStateChanged()
|
||||||
// if we currently have a system transform/viewport set.
|
// if we currently have a system transform/viewport set.
|
||||||
|
d->updateSystemClip();
|
||||||
if (d->hasSystemTransform || d->hasSystemViewport) {
|
if (d->hasSystemTransform || d->hasSystemViewport) {
|
||||||
d->transformSystemClip();
|
|
||||||
d->systemStateChanged();
|
d->systemStateChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ public:
|
|||||||
|
|
||||||
QPaintDevice *pdev;
|
QPaintDevice *pdev;
|
||||||
QPaintEngine *q_ptr;
|
QPaintEngine *q_ptr;
|
||||||
|
QRegion baseSystemClip;
|
||||||
QRegion systemClip;
|
QRegion systemClip;
|
||||||
QRect systemRect;
|
QRect systemRect;
|
||||||
QRegion systemViewport;
|
QRegion systemViewport;
|
||||||
@ -79,8 +80,9 @@ public:
|
|||||||
uint hasSystemTransform : 1;
|
uint hasSystemTransform : 1;
|
||||||
uint hasSystemViewport : 1;
|
uint hasSystemViewport : 1;
|
||||||
|
|
||||||
inline void transformSystemClip()
|
inline void updateSystemClip()
|
||||||
{
|
{
|
||||||
|
systemClip = baseSystemClip;
|
||||||
if (systemClip.isEmpty())
|
if (systemClip.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -104,15 +106,30 @@ public:
|
|||||||
inline void setSystemTransform(const QTransform &xform)
|
inline void setSystemTransform(const QTransform &xform)
|
||||||
{
|
{
|
||||||
systemTransform = xform;
|
systemTransform = xform;
|
||||||
if ((hasSystemTransform = !xform.isIdentity()) || hasSystemViewport)
|
hasSystemTransform = !xform.isIdentity();
|
||||||
transformSystemClip();
|
updateSystemClip();
|
||||||
systemStateChanged();
|
if (q_ptr->state)
|
||||||
|
systemStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setSystemViewport(const QRegion ®ion)
|
inline void setSystemViewport(const QRegion ®ion)
|
||||||
{
|
{
|
||||||
systemViewport = region;
|
systemViewport = region;
|
||||||
hasSystemViewport = !systemViewport.isEmpty();
|
hasSystemViewport = !systemViewport.isEmpty();
|
||||||
|
updateSystemClip();
|
||||||
|
if (q_ptr->state)
|
||||||
|
systemStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setSystemTransformAndViewport(const QTransform &xform, const QRegion ®ion)
|
||||||
|
{
|
||||||
|
systemTransform = xform;
|
||||||
|
hasSystemTransform = !xform.isIdentity();
|
||||||
|
systemViewport = region;
|
||||||
|
hasSystemViewport = !systemViewport.isEmpty();
|
||||||
|
updateSystemClip();
|
||||||
|
if (q_ptr->state)
|
||||||
|
systemStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void systemStateChanged() { }
|
virtual void systemStateChanged() { }
|
||||||
|
@ -2102,14 +2102,15 @@ QRegion QWidgetPrivate::clipRegion() const
|
|||||||
return r;
|
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
|
// Transform the system clip region from device-independent pixels to device pixels
|
||||||
QPaintEngine *paintEngine = paintDevice->paintEngine();
|
|
||||||
QTransform scaleTransform;
|
QTransform scaleTransform;
|
||||||
const qreal devicePixelRatio = paintDevice->devicePixelRatioF();
|
|
||||||
scaleTransform.scale(devicePixelRatio, devicePixelRatio);
|
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
|
#ifndef QT_NO_GRAPHICSEFFECT
|
||||||
@ -5189,6 +5190,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
|
|||||||
// Save current system clip, viewport and transform,
|
// Save current system clip, viewport and transform,
|
||||||
const QTransform oldTransform = enginePriv->systemTransform;
|
const QTransform oldTransform = enginePriv->systemTransform;
|
||||||
const QRegion oldSystemClip = enginePriv->systemClip;
|
const QRegion oldSystemClip = enginePriv->systemClip;
|
||||||
|
const QRegion oldBaseClip = enginePriv->baseSystemClip;
|
||||||
const QRegion oldSystemViewport = enginePriv->systemViewport;
|
const QRegion oldSystemViewport = enginePriv->systemViewport;
|
||||||
|
|
||||||
// This ensures that all painting triggered by render() is clipped to the current engine clip.
|
// 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);
|
d->render(target, targetOffset, toBePainted, renderFlags);
|
||||||
|
|
||||||
// Restore system clip, viewport and transform.
|
// Restore system clip, viewport and transform.
|
||||||
enginePriv->setSystemViewport(oldSystemViewport);
|
enginePriv->baseSystemClip = oldBaseClip;
|
||||||
enginePriv->setSystemTransform(oldTransform);
|
enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
|
||||||
enginePriv->systemClip = oldSystemClip;
|
|
||||||
|
|
||||||
// Restore shared painter.
|
// Restore shared painter.
|
||||||
d->setSharedPainter(oldPainter);
|
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);
|
QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
|
||||||
sourced->context = &context;
|
sourced->context = &context;
|
||||||
if (!sharedPainter) {
|
if (!sharedPainter) {
|
||||||
setSystemClip(pdev, rgn.translated(offset));
|
setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset));
|
||||||
QPainter p(pdev);
|
QPainter p(pdev);
|
||||||
p.translate(offset);
|
p.translate(offset);
|
||||||
context.painter = &p;
|
context.painter = &p;
|
||||||
graphicsEffect->draw(&p);
|
graphicsEffect->draw(&p);
|
||||||
setSystemClip(pdev, QRegion());
|
setSystemClip(pdev->paintEngine(), 1, QRegion());
|
||||||
} else {
|
} else {
|
||||||
context.painter = sharedPainter;
|
context.painter = sharedPainter;
|
||||||
if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
|
if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
|
||||||
@ -5509,7 +5510,9 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
|
|||||||
}
|
}
|
||||||
sharedPainter->save();
|
sharedPainter->save();
|
||||||
sharedPainter->translate(offset);
|
sharedPainter->translate(offset);
|
||||||
|
setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatioF(), rgn.translated(offset));
|
||||||
graphicsEffect->draw(sharedPainter);
|
graphicsEffect->draw(sharedPainter);
|
||||||
|
setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
|
||||||
sharedPainter->restore();
|
sharedPainter->restore();
|
||||||
}
|
}
|
||||||
sourced->context = 0;
|
sourced->context = 0;
|
||||||
@ -5561,7 +5564,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
if (sharedPainter)
|
if (sharedPainter)
|
||||||
setSystemClip(pdev, toBePainted);
|
setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted);
|
||||||
else
|
else
|
||||||
paintEngine->d_func()->systemRect = q->data->crect;
|
paintEngine->d_func()->systemRect = q->data->crect;
|
||||||
|
|
||||||
@ -5579,7 +5582,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!sharedPainter)
|
if (!sharedPainter)
|
||||||
setSystemClip(pdev, toBePainted.translated(offset));
|
setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted.translated(offset));
|
||||||
|
|
||||||
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
|
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
|
||||||
#ifndef QT_NO_OPENGL
|
#ifndef QT_NO_OPENGL
|
||||||
@ -5647,7 +5650,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
|
|||||||
else
|
else
|
||||||
paintEngine->d_func()->currentClipDevice = 0;
|
paintEngine->d_func()->currentClipDevice = 0;
|
||||||
|
|
||||||
setSystemClip(pdev, QRegion());
|
setSystemClip(pdev->paintEngine(), 1, QRegion());
|
||||||
}
|
}
|
||||||
q->setAttribute(Qt::WA_WState_InPaintEvent, false);
|
q->setAttribute(Qt::WA_WState_InPaintEvent, false);
|
||||||
if (Q_UNLIKELY(q->paintingActive()))
|
if (Q_UNLIKELY(q->paintingActive()))
|
||||||
|
@ -409,7 +409,7 @@ public:
|
|||||||
|
|
||||||
QRect clipRect() const;
|
QRect clipRect() const;
|
||||||
QRegion clipRegion() 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 subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
|
||||||
void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
|
void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
|
||||||
bool alsoNonOpaque = false) const;
|
bool alsoNonOpaque = false) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user