Fix assert in QPainterPath after clear()

The newly introduced clear() method left the path in an undefined
state: d_ptr allocated, but no elements. The elements vector is
otherwise never empty, since ensureData() inserts a dummy initial
moveTo element.

Fix by making sure that clear() leaves the path in the same state as
ensureData() (i.e. "empty" but not "null"), except possibly more
capacity allocated in the elements vector.

Fixes: QTBUG-76534
Change-Id: I7ad8b312913f5eb6e22023f5d2fd873e54b1e23c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
Eirik Aavitsland 2019-06-28 14:40:04 +02:00
parent a4567c9058
commit 697910e5fb
3 changed files with 15 additions and 6 deletions

View File

@ -661,6 +661,7 @@ void QPainterPath::clear()
detach();
d_func()->clear();
d_func()->elements.append( {0, 0, MoveToElement} );
}
/*!
@ -2337,12 +2338,12 @@ bool QPainterPath::operator==(const QPainterPath &path) const
{
QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
QPainterPathData *other_d = path.d_func();
if (other_d == d)
if (other_d == d) {
return true;
else if (!d || !other_d) {
if (!d && other_d->elements.empty() && other_d->fillRule == Qt::OddEvenFill)
} else if (!d || !other_d) {
if (!other_d && isEmpty() && elementAt(0) == QPointF() && d->fillRule == Qt::OddEvenFill)
return true;
if (!other_d && d && d->elements.empty() && d->fillRule == Qt::OddEvenFill)
if (!d && path.isEmpty() && path.elementAt(0) == QPointF() && other_d->fillRule == Qt::OddEvenFill)
return true;
return false;
}

View File

@ -298,7 +298,7 @@ inline void QPainterPathData::clear()
elements.clear();
cStart = 0;
fillRule = Qt::OddEvenFill;
bounds = {};
controlBounds = {};

View File

@ -161,10 +161,18 @@ void tst_QPainterPath::clear()
p1.clear();
QCOMPARE(p1, p2);
p1.lineTo(50, 50);
QPainterPath p3;
QCOMPARE(p1.elementCount(), 2);
p3.lineTo(50, 50);
QCOMPARE(p1, p3);
QCOMPARE(p1.fillRule(), Qt::OddEvenFill);
p1.setFillRule(Qt::WindingFill);
QVERIFY(p1 != p3);
p1.clear();
QCOMPARE(p1.fillRule(), Qt::WindingFill);
QCOMPARE(p1.fillRule(), Qt::OddEvenFill);
QCOMPARE(p1, p2);
}
void tst_QPainterPath::reserveAndCapacity()