From 49df693145bbd94afd0b65a57c5b93d7773ff886 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 1 Jun 2020 11:54:45 +0200 Subject: QPainter: replace manual memory management [5/5]: d_ptrs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace a manually-managed pointer + size with QVarLengthArray, allowing use of pre-allocated space. Change-Id: Ife3abea0b3b0f2577bb76c348513d52d46f79641 Reviewed-by: MÃ¥rten Nordheim --- src/gui/painting/qpainter.cpp | 23 +++++------------------ src/gui/painting/qpainter_p.h | 7 +++++-- 2 files changed, 10 insertions(+), 20 deletions(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 82a96960a8..31f8e40381 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -267,20 +267,8 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) // Save the current state of the shared painter and assign // the current d_ptr to the shared painter's d_ptr. sp->save(); - if (!sp->d_ptr->d_ptrs) { - // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent - // redirections within the same paintEvent(), which should be enough - // in 99% of all cases). E.g: A renders B which renders C which renders D. - sp->d_ptr->d_ptrs_size = 4; - sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *)); - Q_CHECK_PTR(sp->d_ptr->d_ptrs); - } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) { - // However, to support corner cases we grow the array dynamically if needed. - sp->d_ptr->d_ptrs_size <<= 1; - const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *); - sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize)); - } - sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data(); + ++sp->d_ptr->refcount; + sp->d_ptr->d_ptrs.push_back(q->d_ptr.data()); q->d_ptr.take(); q->d_ptr.reset(sp->d_ptr.data()); @@ -325,7 +313,9 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q) Q_ASSERT(refcount > 1); Q_ASSERT(q); - QPainterPrivate *original = d_ptrs[--refcount - 1]; + --refcount; + QPainterPrivate *original = d_ptrs.back(); + d_ptrs.pop_back(); if (inDestructor) { inDestructor = false; if (original) @@ -334,7 +324,6 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q) original = new QPainterPrivate(q); } - d_ptrs[refcount - 1] = nullptr; q->restore(); q->d_ptr.take(); q->d_ptr.reset(original); @@ -1515,8 +1504,6 @@ QPainter::~QPainter() Q_ASSERT(d_ptr->inDestructor); d_ptr->inDestructor = false; Q_ASSERT(d_ptr->refcount == 1); - if (d_ptr->d_ptrs) - free(d_ptr->d_ptrs); } } diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 09de84f2b2..7f5fe1a6c5 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -198,7 +198,11 @@ public: ~QPainterPrivate(); QPainter *q_ptr; - QPainterPrivate **d_ptrs = nullptr; + // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent + // redirections within the same paintEvent(), which should be enough + // in 99% of all cases). E.g: A renders B which renders C which renders D. + static constexpr qsizetype NDPtrs = 4; + QVarLengthArray d_ptrs; std::unique_ptr state; template @@ -212,7 +216,6 @@ public: QTransform invMatrix; uint txinv:1; uint inDestructor : 1; - uint d_ptrs_size = 0; uint refcount = 1; enum DrawOperation { StrokeDraw = 0x1, -- cgit v1.2.3