QWidget: set brushOrigin in paintBackground() only when really needed

When painting the background for a QAbstractScrollArea, the brushOrigin
was calculated for every brush type although it was not needed. Since
this can be very time consuming (e.g for a QTreeView with non-uniform
row sizes) it should be avoided when possible.
Therefore check if the brush is a texture and skip the calculation if
it is not the case. Also do not restore the old brushOrigin since the
painter is not used at all afterwards.

Task-number: QTBUG-61763
Change-Id: I66cbe1b796cb5cad4c78e656fb86d199d8e4bde9
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
bb10
Christian Ehrlicher 2018-10-07 20:36:05 +02:00
parent fedcaf0256
commit 2672a9a767
2 changed files with 18 additions and 14 deletions

View File

@ -2416,29 +2416,34 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus
}
}
void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
{
Q_Q(const QWidget);
#if QT_CONFIG(scrollarea)
bool resetBrushOrigin = false;
QPointF oldBrushOrigin;
Q_Q(const QWidget);
//If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
return false;
QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
if (scrollArea && scrollArea->viewport() == q) {
QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
oldBrushOrigin = painter->brushOrigin();
resetBrushOrigin = true;
painter->setBrushOrigin(-priv->contentsOffset());
}
#endif // QT_CONFIG(scrollarea)
return true;
}
void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
{
Q_Q(const QWidget);
bool brushOriginSet = false;
const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
const QBrush bg = q->palette().brush(QPalette::Window);
if (!brushOriginSet)
brushOriginSet = updateBrushOrigin(painter, bg);
if (!(flags & DontSetCompositionMode)) {
//copy alpha straight in
QPainter::CompositionMode oldMode = painter->compositionMode();
@ -2450,8 +2455,11 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int
}
}
if (q->autoFillBackground())
if (q->autoFillBackground()) {
if (!brushOriginSet)
brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
fillRegion(painter, rgn, autoFillBrush);
}
if (q->testAttribute(Qt::WA_StyledBackground)) {
painter->setClipRegion(rgn);
@ -2459,11 +2467,6 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int
opt.initFrom(q);
q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
}
#if QT_CONFIG(scrollarea)
if (resetBrushOrigin)
painter->setBrushOrigin(oldBrushOrigin);
#endif // QT_CONFIG(scrollarea)
}
/*

View File

@ -400,6 +400,7 @@ public:
void setUpdatesEnabled_helper(bool );
bool updateBrushOrigin(QPainter *, const QBrush &brush) const;
void paintBackground(QPainter *, const QRegion &, int flags = DrawAsRoot) const;
bool isAboutToShow() const;
QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);