QPainterPath: Make the private class a bit more compact

Rearrange the data members and avoid spending a whole int to store the
1 bit of fillrule information, when it instead can be part of an
already existing bitfield member. Saves 8 bytes.

Change-Id: I2013ff076e38b2bcd414665a2d5aa528f3632670
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Eirik Aavitsland 2024-08-29 16:59:54 +02:00
parent ff7221c677
commit 76b1424048
2 changed files with 27 additions and 36 deletions

View File

@ -1302,7 +1302,7 @@ void QPainterPath::addRegion(const QRegion &region)
*/
Qt::FillRule QPainterPath::fillRule() const
{
return !d_func() ? Qt::OddEvenFill : d_func()->fillRule;
return d_func() && d_func()->hasWindingFill ? Qt::WindingFill : Qt::OddEvenFill;
}
/*!
@ -1325,11 +1325,12 @@ Qt::FillRule QPainterPath::fillRule() const
void QPainterPath::setFillRule(Qt::FillRule fillRule)
{
ensureData();
if (d_func()->fillRule == fillRule)
const bool isWindingRequested = (fillRule == Qt::WindingFill);
if (d_func()->hasWindingFill == isWindingRequested)
return;
detach();
d_func()->fillRule = fillRule;
d_func()->hasWindingFill = isWindingRequested;
}
#define QT_BEZIER_A(bezier, coord) 3 * (-bezier.coord##1 \
@ -1835,7 +1836,7 @@ bool QPainterPath::contains(const QPointF &pt) const
if (last_pt != last_start)
qt_painterpath_isect_line(last_pt, last_start, pt, &winding_number);
return (d->fillRule == Qt::WindingFill
return (d->hasWindingFill
? (winding_number != 0)
: ((winding_number % 2) != 0));
}
@ -2257,13 +2258,13 @@ bool QPainterPath::operator==(const QPainterPath &path) const
if (other_d == d) {
return true;
} else if (!d || !other_d) {
if (!other_d && isEmpty() && elementAt(0) == QPointF() && d->fillRule == Qt::OddEvenFill)
if (!other_d && isEmpty() && elementAt(0) == QPointF() && !d->hasWindingFill)
return true;
if (!d && path.isEmpty() && path.elementAt(0) == QPointF() && other_d->fillRule == Qt::OddEvenFill)
if (!d && path.isEmpty() && path.elementAt(0) == QPointF() && !other_d->hasWindingFill)
return true;
return false;
}
else if (d->fillRule != other_d->fillRule)
else if (d->hasWindingFill != other_d->hasWindingFill)
return false;
else if (d->elements.size() != other_d->elements.size())
return false;
@ -2419,7 +2420,7 @@ QDataStream &operator<<(QDataStream &s, const QPainterPath &p)
s << double(e.x) << double(e.y);
}
s << p.d_func()->cStart;
s << int(p.d_func()->fillRule);
s << int(p.fillRule());
return s;
}
@ -2467,7 +2468,7 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
int fillRule;
s >> fillRule;
Q_ASSERT(fillRule == Qt::OddEvenFill || fillRule == Qt::WindingFill);
p.d_func()->fillRule = Qt::FillRule(fillRule);
p.d_func()->hasWindingFill = (Qt::FillRule(fillRule) == Qt::WindingFill);
if (errorDetected || p.d_func()->elements.isEmpty())
p = QPainterPath(); // Better than to return path with possibly corrupt datastructure, which would likely cause crash
return s;

View File

@ -35,8 +35,8 @@ class QVectorPathConverter;
class QVectorPathConverter
{
public:
QVectorPathConverter(const QList<QPainterPath::Element> &path, uint fillRule, bool convex)
: pathData(path, fillRule, convex),
QVectorPathConverter(const QList<QPainterPath::Element> &path, bool hasWindingFill, bool convex)
: pathData(path, hasWindingFill, convex),
path(pathData.points.data(), path.size(), pathData.elements.data(), pathData.flags)
{
}
@ -46,7 +46,7 @@ public:
}
struct QVectorPathData {
QVectorPathData(const QList<QPainterPath::Element> &path, uint fillRule, bool convex)
QVectorPathData(const QList<QPainterPath::Element> &path, bool hasWindingFill, bool convex)
: elements(path.size()), points(path.size() * 2), flags(0)
{
int ptsPos = 0;
@ -65,7 +65,7 @@ public:
isLines = isLines && e.type == (QPainterPath::ElementType) (i%2);
}
if (fillRule == Qt::WindingFill)
if (hasWindingFill)
flags |= QVectorPath::WindingFill;
else
flags |= QVectorPath::OddEvenFill;
@ -107,43 +107,38 @@ public:
QPainterPathPrivate() noexcept
: QSharedData(),
cStart(0),
fillRule(Qt::OddEvenFill),
require_moveTo(false),
dirtyBounds(false),
dirtyControlBounds(false),
convex(false),
pathConverter(nullptr)
hasWindingFill(false)
{
}
QPainterPathPrivate(QPointF startPoint)
: QSharedData(),
elements{ { startPoint.x(), startPoint.y(), QPainterPath::MoveToElement } },
cStart(0),
fillRule(Qt::OddEvenFill),
bounds(startPoint, QSizeF(0, 0)),
controlBounds(startPoint, QSizeF(0, 0)),
require_moveTo(false),
dirtyBounds(false),
dirtyControlBounds(false),
convex(false),
pathConverter(nullptr)
hasWindingFill(false)
{
}
QPainterPathPrivate(const QPainterPathPrivate &other) noexcept
: QSharedData(other),
elements(other.elements),
cStart(other.cStart),
fillRule(other.fillRule),
bounds(other.bounds),
controlBounds(other.controlBounds),
cStart(other.cStart),
require_moveTo(false),
dirtyBounds(other.dirtyBounds),
dirtyControlBounds(other.dirtyControlBounds),
convex(other.convex),
pathConverter(nullptr)
hasWindingFill(other.hasWindingFill)
{
}
@ -157,25 +152,23 @@ public:
const QVectorPath &vectorPath() {
if (!pathConverter)
pathConverter.reset(new QVectorPathConverter(elements, fillRule, convex));
pathConverter.reset(new QVectorPathConverter(elements, hasWindingFill, convex));
return pathConverter->path;
}
private:
QList<QPainterPath::Element> elements;
int cStart;
Qt::FillRule fillRule;
std::unique_ptr<QVectorPathConverter> pathConverter;
QRectF bounds;
QRectF controlBounds;
uint require_moveTo : 1;
uint dirtyBounds : 1;
uint dirtyControlBounds : 1;
uint convex : 1;
int cStart = 0;
std::unique_ptr<QVectorPathConverter> pathConverter;
bool require_moveTo : 1;
bool dirtyBounds : 1;
bool dirtyControlBounds : 1;
bool convex : 1;
bool hasWindingFill : 1;
};
class QPainterPathStrokerPrivate
@ -218,10 +211,7 @@ inline const QPainterPath QVectorPath::convertToPainterPath() const
}
}
if (m_hints & OddEvenFill)
data->fillRule = Qt::OddEvenFill;
else
data->fillRule = Qt::WindingFill;
data->hasWindingFill = !(m_hints & OddEvenFill);
return path;
}