From 2523f62939948f383178054c2d061711c0413348 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 24 Jun 2015 02:04:09 +0200 Subject: [PATCH] QPainter: replace an inefficient QList with QVector QPainterClipInfo is larger than a void*, so holding it in QLists is needlessly inefficient. Worse, the code could come to depend on the fragile property of (inefficient) QLists that references to elements therein never are invalidated. Fix by marking it movable and holding it in a QVector instead. Port from op<< to append() to reap rvalue push_back(). Change-Id: I3af17eca2443d26a795381635510b8b9a5795e5f Reviewed-by: Gunnar Sletta --- src/gui/painting/qpaintengineex.cpp | 9 ++---- src/gui/painting/qpainter.cpp | 32 +++++++++---------- src/gui/painting/qpainter_p.h | 4 ++- .../direct2d/qwindowsdirect2dpaintengine.cpp | 2 +- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 5fb94f1dc3..f3c9b92bae 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -182,12 +182,11 @@ void QPaintEngineExPrivate::replayClipOperations() if (!p || !p->d_ptr) return; - QList clipInfo = p->d_ptr->state->clipInfo; + const QVector &clipInfo = p->d_ptr->state->clipInfo; QTransform transform = q->state()->matrix; - for (int i = 0; i < clipInfo.size(); ++i) { - const QPainterClipInfo &info = clipInfo.at(i); + for (const QPainterClipInfo &info : clipInfo) { if (info.matrix != q->state()->matrix) { q->state()->matrix = info.matrix; @@ -233,9 +232,7 @@ bool QPaintEngineExPrivate::hasClipOperations() const if (!p || !p->d_ptr) return false; - QList clipInfo = p->d_ptr->state->clipInfo; - - return !clipInfo.isEmpty(); + return !p->d_ptr->state->clipInfo.isEmpty(); } /******************************************************************************* diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 927cc5bb56..bcef14ca61 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -403,8 +403,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio if (q->hasClipping()) { bool hasPerspectiveTransform = false; - for (int i = 0; i < state->clipInfo.size(); ++i) { - const QPainterClipInfo &info = state->clipInfo.at(i); + for (const QPainterClipInfo &info : qAsConst(state->clipInfo)) { if (info.matrix.type() == QTransform::TxProject) { hasPerspectiveTransform = true; break; @@ -1635,8 +1634,7 @@ void QPainter::restore() tmp->clipPath = QPainterPath(); d->engine->updateState(*tmp); // replay the list of clip states, - for (int i=0; istate->clipInfo.size(); ++i) { - const QPainterClipInfo &info = d->state->clipInfo.at(i); + for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) { tmp->matrix = info.matrix; tmp->matrix *= d->state->redirectionMatrix; tmp->clipOperation = info.operation; @@ -2512,8 +2510,7 @@ QRegion QPainter::clipRegion() const const_cast(this)->d_ptr->updateInvMatrix(); // ### Falcon: Use QPainterPath - for (int i=0; istate->clipInfo.size(); ++i) { - const QPainterClipInfo &info = d->state->clipInfo.at(i); + for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) { switch (info.clipType) { case QPainterClipInfo::RegionClip: { @@ -2627,7 +2624,7 @@ QPainterPath QPainter::clipPath() const } // No clip, return empty - if (d->state->clipInfo.size() == 0) { + if (d->state->clipInfo.isEmpty()) { return QPainterPath(); } else { @@ -2679,9 +2676,9 @@ QRectF QPainter::clipBoundingRect() const // precise, but it fits within the guarantee and it is reasonably // fast. QRectF bounds; - for (int i=0; istate->clipInfo.size(); ++i) { + bool first = true; + for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) { QRectF r; - const QPainterClipInfo &info = d->state->clipInfo.at(i); if (info.clipType == QPainterClipInfo::RectClip) r = info.rect; @@ -2694,10 +2691,11 @@ QRectF QPainter::clipBoundingRect() const r = info.matrix.mapRect(r); - if (i == 0) + if (first) bounds = r; else if (info.operation == Qt::IntersectClip) bounds &= r; + first = false; } @@ -2745,7 +2743,7 @@ void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op) d->extended->clip(vp, op); if (op == Qt::ReplaceClip || op == Qt::NoClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); + d->state->clipInfo.append(QPainterClipInfo(rect, op, d->state->matrix)); d->state->clipOperation = op; return; } @@ -2794,7 +2792,7 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) d->extended->clip(rect, op); if (op == Qt::ReplaceClip || op == Qt::NoClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); + d->state->clipInfo.append(QPainterClipInfo(rect, op, d->state->matrix)); d->state->clipOperation = op; return; } @@ -2806,7 +2804,7 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); + d->state->clipInfo.append(QPainterClipInfo(rect, op, d->state->matrix)); d->state->clipEnabled = true; d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; d->updateState(d->state); @@ -2853,7 +2851,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) d->extended->clip(r, op); if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); + d->state->clipInfo.append(QPainterClipInfo(r, op, d->state->matrix)); d->state->clipOperation = op; return; } @@ -2865,7 +2863,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); + d->state->clipInfo.append(QPainterClipInfo(r, op, d->state->matrix)); d->state->clipEnabled = true; d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; d->updateState(d->state); @@ -3257,7 +3255,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) d->extended->clip(path, op); if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); + d->state->clipInfo.append(QPainterClipInfo(path, op, d->state->matrix)); d->state->clipOperation = op; return; } @@ -3269,7 +3267,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); + d->state->clipInfo.append(QPainterClipInfo(path, op, d->state->matrix)); d->state->clipEnabled = true; d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled; d->updateState(d->state); diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index b916d0a428..23ab5db7b4 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -97,6 +97,7 @@ inline bool qbrush_has_transform(const QBrush &b) { return data_ptr(b)->transfor class QPainterClipInfo { public: + QPainterClipInfo() {} // for QVector, don't use enum ClipType { RegionClip, PathClip, RectClip, RectFClip }; QPainterClipInfo(const QPainterPath &p, Qt::ClipOperation op, const QTransform &m) : @@ -134,6 +135,7 @@ public: }; +Q_DECLARE_TYPEINFO(QPainterClipInfo, Q_MOVABLE_TYPE); class Q_GUI_EXPORT QPainterState : public QPaintEngineState { @@ -153,7 +155,7 @@ public: QPainterPath clipPath; Qt::ClipOperation clipOperation; QPainter::RenderHints renderHints; - QList clipInfo; // ### Make me smaller and faster to copy around... + QVector clipInfo; // ### Make me smaller and faster to copy around... QTransform worldMatrix; // World transformation matrix, not window and viewport QTransform matrix; // Complete transformation matrix, QTransform redirectionMatrix; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index bb01e054a8..730d5de450 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -1687,7 +1687,7 @@ void QWindowsDirect2DPaintEngine::rasterFill(const QVectorPath &path, const QBru p.setPen(state()->pen); QPaintEngineEx *extended = static_cast(engine); - foreach (const QPainterClipInfo &info, state()->clipInfo) { + for (const QPainterClipInfo &info : qAsConst(state()->clipInfo)) { extended->state()->matrix = info.matrix; extended->transformChanged();