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

View File

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