summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Michaël Celerier <jeanmichael.celerier@gmail.com>2017-07-09 19:27:35 +0200
committerJean-Michaël Celerier <jean-michael.celerier@kdab.com>2019-01-08 08:25:02 +0000
commite6a7b61d273c2985dee63df34e5941ee90754e2a (patch)
treedc27b083dcb810e70b9616b12adab7a9c64c0efe
parent4e6a42cdd050c8714686fa53b3246c4fc66d18fd (diff)
Add clear, reserve and capacity methods to QPainterPath
This allows anticipating and reusing internal allocations of QPainterPathElements instead of using the common `m_myPath = QPainterPath{}` pattern. [ChangeLog][QtGui][QPainterPath] Added clear(), reserve(), capacity(). clear() removes allocated QPainterPath elements but preserves allocated memory, which can be useful for application with complex paths that are often recreated. reserve() and capacity() follow QVector semantics. Change-Id: I763461e2a421feda9053d3eb512af2fcf07ade2b Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--src/gui/painting/qpainterpath.cpp67
-rw-r--r--src/gui/painting/qpainterpath.h5
-rw-r--r--src/gui/painting/qpainterpath_p.h20
-rw-r--r--tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp43
4 files changed, 129 insertions, 6 deletions
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index c5ccf0003d..3687bcf7d0 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -629,6 +629,55 @@ QPainterPath::~QPainterPath()
}
/*!
+ Clears the path elements stored.
+
+ This allows the path to reuse previous memory allocations.
+
+ \sa reserve(), capacity()
+ \since 5.13
+*/
+void QPainterPath::clear()
+{
+ if (!d_ptr)
+ return;
+
+ detach();
+ d_func()->clear();
+}
+
+/*!
+ Reserves a given amount of elements in QPainterPath's internal memory.
+
+ Attempts to allocate memory for at least \a size elements.
+
+ \sa clear(), capacity(), QVector::reserve()
+ \since 5.13
+*/
+void QPainterPath::reserve(int size)
+{
+ Q_D(QPainterPath);
+ if ((!d && size > 0) || (d && d->elements.capacity() < size)) {
+ detach();
+ d->elements.reserve(size);
+ }
+}
+
+/*!
+ Returns the number of elements allocated by the QPainterPath.
+
+ \sa clear(), reserve()
+ \since 5.13
+*/
+int QPainterPath::capacity() const
+{
+ Q_D(QPainterPath);
+ if (d)
+ return d->elements.capacity();
+
+ return 0;
+}
+
+/*!
Closes the current subpath by drawing a line to the beginning of
the subpath, automatically starting a new path. The current point
of the new path is (0, 0).
@@ -2271,13 +2320,19 @@ static inline bool epsilonCompare(const QPointF &a, const QPointF &b, const QSiz
bool QPainterPath::operator==(const QPainterPath &path) const
{
QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
- if (path.d_func() == d)
+ QPainterPathData *other_d = path.d_func();
+ if (other_d == d)
return true;
- else if (!d || !path.d_func())
+ else if (!d || !other_d) {
+ if (!d && other_d->elements.empty() && other_d->fillRule == Qt::OddEvenFill)
+ return true;
+ if (!other_d && d && d->elements.empty() && d->fillRule == Qt::OddEvenFill)
+ return true;
return false;
- else if (d->fillRule != path.d_func()->fillRule)
+ }
+ else if (d->fillRule != other_d->fillRule)
return false;
- else if (d->elements.size() != path.d_func()->elements.size())
+ else if (d->elements.size() != other_d->elements.size())
return false;
const qreal qt_epsilon = sizeof(qreal) == sizeof(double) ? 1e-12 : qreal(1e-5);
@@ -2287,8 +2342,8 @@ bool QPainterPath::operator==(const QPainterPath &path) const
epsilon.rheight() *= qt_epsilon;
for (int i = 0; i < d->elements.size(); ++i)
- if (d->elements.at(i).type != path.d_func()->elements.at(i).type
- || !epsilonCompare(d->elements.at(i), path.d_func()->elements.at(i), epsilon))
+ if (d->elements.at(i).type != other_d->elements.at(i).type
+ || !epsilonCompare(d->elements.at(i), other_d->elements.at(i), epsilon))
return false;
return true;
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index db39c1c5a0..770b8f48d0 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -97,8 +97,13 @@ public:
{ qSwap(d_ptr, other.d_ptr); return *this; }
#endif
~QPainterPath();
+
inline void swap(QPainterPath &other) Q_DECL_NOEXCEPT { d_ptr.swap(other.d_ptr); }
+ void clear();
+ void reserve(int size);
+ int capacity() const;
+
void closeSubpath();
void moveTo(const QPointF &p);
diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h
index aab318bcab..a36c8005bc 100644
--- a/src/gui/painting/qpainterpath_p.h
+++ b/src/gui/painting/qpainterpath_p.h
@@ -194,6 +194,7 @@ public:
inline bool isClosed() const;
inline void close();
inline void maybeMoveTo();
+ inline void clear();
const QVectorPath &vectorPath() {
if (!pathConverter)
@@ -290,6 +291,25 @@ inline void QPainterPathData::maybeMoveTo()
}
}
+inline void QPainterPathData::clear()
+{
+ Q_ASSERT(ref.load() == 1);
+
+ elements.clear();
+
+ cStart = 0;
+
+ bounds = {};
+ controlBounds = {};
+
+ require_moveTo = false;
+ dirtyBounds = false;
+ dirtyControlBounds = false;
+ convex = false;
+
+ delete pathConverter;
+ pathConverter = nullptr;
+}
#define KAPPA qreal(0.5522847498)
diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
index 16215714f3..69c961c1a1 100644
--- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
+++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
@@ -43,6 +43,8 @@ public slots:
void cleanupTestCase();
private slots:
void getSetCheck();
+ void clear();
+ void reserveAndCapacity();
void swap();
void contains_QPointF_data();
@@ -148,6 +150,47 @@ void tst_QPainterPath::swap()
QCOMPARE(p2.boundingRect().toRect(), QRect( 0, 0,10,10));
}
+void tst_QPainterPath::clear()
+{
+ QPainterPath p1;
+ QPainterPath p2;
+ p1.clear();
+ QCOMPARE(p1, p2);
+
+ p1.addRect(0, 0, 10, 10);
+ p1.clear();
+ QCOMPARE(p1, p2);
+
+ QCOMPARE(p1.fillRule(), Qt::OddEvenFill);
+ p1.setFillRule(Qt::WindingFill);
+ p1.clear();
+ QCOMPARE(p1.fillRule(), Qt::WindingFill);
+}
+
+void tst_QPainterPath::reserveAndCapacity()
+{
+ QPainterPath p;
+ QVERIFY(p.capacity() == 0);
+
+ p.addRect(0, 0, 10, 10);
+ QVERIFY(p.capacity() > 0);
+
+ p.clear();
+ QVERIFY(p.capacity() > 0);
+
+ p = QPainterPath{};
+ QVERIFY(p.capacity() == 0);
+
+ p.moveTo(100, 100);
+ QVERIFY(p.capacity() > 1);
+
+ p.reserve(1000);
+ QVERIFY(p.capacity() >= 1000);
+
+ p.reserve(0);
+ QVERIFY(p.capacity() >= 1000);
+}
+
Q_DECLARE_METATYPE(QPainterPath)
void tst_QPainterPath::currentPosition()