QPen: port to QESDP

Move from a manually managed d-pointer to QESDP. This is a long overdue
change (QPen is one of the few classes still with manual management).
At the same time: it's also one of the central classes, and in order
to keep the impact minimal (and binary compatible), I'm not switching to
something more sophisticated.

As a drive-by: drop QPenData, a remnant only used by QPen itself, which
nowadays is simply a typedef for QPenPrivate.

Change-Id: I38834116d7d383f29bb69ff20b0a46dfe951bb53
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Giuseppe D'Angelo 2023-09-13 10:30:48 +02:00
parent cf6bccbcf5
commit 74b67c8f84
3 changed files with 64 additions and 89 deletions

View File

@ -10,8 +10,6 @@
QT_BEGIN_NAMESPACE
typedef QPenPrivate QPenData;
/*!
\class QPen
\inmodule QtGui
@ -193,7 +191,7 @@ typedef QPenPrivate QPenData;
*/
QPenPrivate::QPenPrivate(const QBrush &_brush, qreal _width, Qt::PenStyle penStyle,
Qt::PenCapStyle _capStyle, Qt::PenJoinStyle _joinStyle)
: ref(1), dashOffset(0), miterLimit(2),
: dashOffset(0), miterLimit(2),
cosmetic(false)
{
width = _width;
@ -209,17 +207,13 @@ static const Qt::PenJoinStyle qpen_default_join = Qt::BevelJoin;
class QPenDataHolder
{
public:
QPenData *pen;
QPen::DataPtr pen;
QPenDataHolder(const QBrush &brush, qreal width, Qt::PenStyle penStyle,
Qt::PenCapStyle penCapStyle, Qt::PenJoinStyle _joinStyle)
: pen(new QPenData(brush, width, penStyle, penCapStyle, _joinStyle))
: pen(new QPenPrivate(brush, width, penStyle, penCapStyle, _joinStyle))
{ }
~QPenDataHolder()
{
if (!pen->ref.deref())
delete pen;
pen = nullptr;
}
~QPenDataHolder() = default;
Q_DISABLE_COPY_MOVE(QPenDataHolder)
};
Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, defaultPenInstance,
@ -234,7 +228,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, nullPenInstance,
QPen::QPen()
{
d = defaultPenInstance()->pen;
d->ref.ref();
}
/*!
@ -247,9 +240,8 @@ QPen::QPen(Qt::PenStyle style)
{
if (style == Qt::NoPen) {
d = nullPenInstance()->pen;
d->ref.ref();
} else {
d = new QPenData(Qt::black, 1, style, qpen_default_cap, qpen_default_join);
d = new QPenPrivate(Qt::black, 1, style, qpen_default_cap, qpen_default_join);
}
}
@ -262,7 +254,7 @@ QPen::QPen(Qt::PenStyle style)
QPen::QPen(const QColor &color)
{
d = new QPenData(color, 1, Qt::SolidLine, qpen_default_cap, qpen_default_join);
d = new QPenPrivate(color, 1, Qt::SolidLine, qpen_default_cap, qpen_default_join);
}
@ -277,7 +269,7 @@ QPen::QPen(const QColor &color)
QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c, Qt::PenJoinStyle j)
{
d = new QPenData(brush, width, s, c, j);
d = new QPenPrivate(brush, width, s, c, j);
}
/*!
@ -287,10 +279,8 @@ QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c,
*/
QPen::QPen(const QPen &p) noexcept
: d(p.d)
{
d = p.d;
if (d)
d->ref.ref();
}
@ -309,11 +299,9 @@ QPen::QPen(const QPen &p) noexcept
Destroys the pen.
*/
QPen::~QPen()
{
if (d && !d->ref.deref())
delete d;
}
QPen::~QPen() = default;
QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QPenPrivate)
/*!
\fn void QPen::detach()
@ -327,14 +315,7 @@ QPen::~QPen()
void QPen::detach()
{
if (d->ref.loadRelaxed() == 1)
return;
QPenData *x = new QPenData(*static_cast<QPenData *>(d));
if (!d->ref.deref())
delete d;
x->ref.storeRelaxed(1);
d = x;
d.detach();
}
@ -407,9 +388,8 @@ void QPen::setStyle(Qt::PenStyle s)
return;
detach();
d->style = s;
QPenData *dd = static_cast<QPenData *>(d);
dd->dashPattern.clear();
dd->dashOffset = 0;
d->dashPattern.clear();
d->dashOffset = 0;
}
/*!
@ -419,36 +399,35 @@ void QPen::setStyle(Qt::PenStyle s)
*/
QList<qreal> QPen::dashPattern() const
{
QPenData *dd = static_cast<QPenData *>(d);
if (d->style == Qt::SolidLine || d->style == Qt::NoPen) {
return QList<qreal>();
} else if (dd->dashPattern.isEmpty()) {
} else if (d->dashPattern.isEmpty()) {
const qreal space = 2;
const qreal dot = 1;
const qreal dash = 4;
switch (d->style) {
case Qt::DashLine:
dd->dashPattern.reserve(2);
dd->dashPattern << dash << space;
d->dashPattern.reserve(2);
d->dashPattern << dash << space;
break;
case Qt::DotLine:
dd->dashPattern.reserve(2);
dd->dashPattern << dot << space;
d->dashPattern.reserve(2);
d->dashPattern << dot << space;
break;
case Qt::DashDotLine:
dd->dashPattern.reserve(4);
dd->dashPattern << dash << space << dot << space;
d->dashPattern.reserve(4);
d->dashPattern << dash << space << dot << space;
break;
case Qt::DashDotDotLine:
dd->dashPattern.reserve(6);
dd->dashPattern << dash << space << dot << space << dot << space;
d->dashPattern.reserve(6);
d->dashPattern << dash << space << dot << space << dot << space;
break;
default:
break;
}
}
return dd->dashPattern;
return d->dashPattern;
}
/*!
@ -487,13 +466,12 @@ void QPen::setDashPattern(const QList<qreal> &pattern)
return;
detach();
QPenData *dd = static_cast<QPenData *>(d);
dd->dashPattern = pattern;
d->dashPattern = pattern;
d->style = Qt::CustomDashLine;
if ((dd->dashPattern.size() % 2) == 1) {
if ((d->dashPattern.size() % 2) == 1) {
qWarning("QPen::setDashPattern: Pattern not of even length");
dd->dashPattern << 1;
d->dashPattern << 1;
}
}
@ -505,8 +483,7 @@ void QPen::setDashPattern(const QList<qreal> &pattern)
*/
qreal QPen::dashOffset() const
{
QPenData *dd = static_cast<QPenData *>(d);
return dd->dashOffset;
return d->dashOffset;
}
/*!
Sets the dash offset (the starting point on the dash pattern) for this pen
@ -528,13 +505,12 @@ qreal QPen::dashOffset() const
*/
void QPen::setDashOffset(qreal offset)
{
if (qFuzzyCompare(offset, static_cast<QPenData *>(d)->dashOffset))
if (qFuzzyCompare(offset, d->dashOffset))
return;
detach();
QPenData *dd = static_cast<QPenData *>(d);
dd->dashOffset = offset;
d->dashOffset = offset;
if (d->style != Qt::CustomDashLine) {
dd->dashPattern = dashPattern();
d->dashPattern = dashPattern();
d->style = Qt::CustomDashLine;
}
}
@ -547,8 +523,7 @@ void QPen::setDashOffset(qreal offset)
*/
qreal QPen::miterLimit() const
{
const QPenData *dd = static_cast<QPenData *>(d);
return dd->miterLimit;
return d->miterLimit;
}
/*!
@ -570,8 +545,7 @@ qreal QPen::miterLimit() const
void QPen::setMiterLimit(qreal limit)
{
detach();
QPenData *dd = static_cast<QPenData *>(d);
dd->miterLimit = limit;
d->miterLimit = limit;
}
@ -782,8 +756,7 @@ bool QPen::isSolid() const
bool QPen::isCosmetic() const
{
QPenData *dd = static_cast<QPenData *>(d);
return (dd->cosmetic == true) || d->width == 0;
return (d->cosmetic == true) || d->width == 0;
}
@ -797,8 +770,7 @@ bool QPen::isCosmetic() const
void QPen::setCosmetic(bool cosmetic)
{
detach();
QPenData *dd = static_cast<QPenData *>(d);
dd->cosmetic = cosmetic;
d->cosmetic = cosmetic;
}
@ -825,19 +797,17 @@ void QPen::setCosmetic(bool cosmetic)
bool QPen::operator==(const QPen &p) const
{
QPenData *dd = static_cast<QPenData *>(d);
QPenData *pdd = static_cast<QPenData *>(p.d);
return (p.d == d)
|| (p.d->style == d->style
&& p.d->capStyle == d->capStyle
&& p.d->joinStyle == d->joinStyle
&& p.d->width == d->width
&& pdd->miterLimit == dd->miterLimit
&& p.d->miterLimit == d->miterLimit
&& (d->style != Qt::CustomDashLine
|| (qFuzzyCompare(pdd->dashOffset, dd->dashOffset) &&
pdd->dashPattern == dd->dashPattern))
|| (qFuzzyCompare(p.d->dashOffset, d->dashOffset) &&
p.d->dashPattern == d->dashPattern))
&& p.d->brush == d->brush
&& pdd->cosmetic == dd->cosmetic);
&& p.d->cosmetic == d->cosmetic);
}
@ -869,14 +839,13 @@ bool QPen::isDetached()
QDataStream &operator<<(QDataStream &s, const QPen &p)
{
QPenData *dd = static_cast<QPenData *>(p.d);
if (s.version() < 3) {
s << (quint8)p.style();
} else if (s.version() < QDataStream::Qt_4_3) {
s << (quint8)(uint(p.style()) | uint(p.capStyle()) | uint(p.joinStyle()));
} else {
s << (quint16)(uint(p.style()) | uint(p.capStyle()) | uint(p.joinStyle()));
s << (bool)(dd->cosmetic);
s << (bool)(p.d->cosmetic);
}
if (s.version() < 7) {
@ -965,16 +934,15 @@ QDataStream &operator>>(QDataStream &s, QPen &p)
}
p.detach();
QPenData *dd = static_cast<QPenData *>(p.d);
dd->width = width;
dd->brush = brush;
dd->style = Qt::PenStyle(style & Qt::MPenStyle);
dd->capStyle = Qt::PenCapStyle(style & Qt::MPenCapStyle);
dd->joinStyle = Qt::PenJoinStyle(style & Qt::MPenJoinStyle);
dd->dashPattern = dashPattern;
dd->miterLimit = miterLimit;
dd->dashOffset = dashOffset;
dd->cosmetic = cosmetic;
p.d->width = width;
p.d->brush = brush;
p.d->style = Qt::PenStyle(style & Qt::MPenStyle);
p.d->capStyle = Qt::PenCapStyle(style & Qt::MPenCapStyle);
p.d->joinStyle = Qt::PenJoinStyle(style & Qt::MPenJoinStyle);
p.d->dashPattern = dashPattern;
p.d->miterLimit = miterLimit;
p.d->dashOffset = dashOffset;
p.d->cosmetic = cosmetic;
return s;
}

View File

@ -4,6 +4,7 @@
#ifndef QPEN_H
#define QPEN_H
#include <QtCore/qshareddata.h>
#include <QtGui/qtguiglobal.h>
#include <QtGui/qcolor.h>
#include <QtGui/qbrush.h>
@ -21,6 +22,8 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPen &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPen &);
#endif
QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QPenPrivate, Q_GUI_EXPORT)
class Q_GUI_EXPORT QPen
{
public:
@ -34,10 +37,9 @@ public:
~QPen();
QPen &operator=(const QPen &pen) noexcept;
QPen(QPen &&other) noexcept
: d(std::exchange(other.d, nullptr)) {}
QPen(QPen &&other) noexcept = default;
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPen)
void swap(QPen &other) noexcept { qt_ptr_swap(d, other.d); }
void swap(QPen &other) noexcept { d.swap(other.d); }
Qt::PenStyle style() const;
void setStyle(Qt::PenStyle);
@ -79,15 +81,19 @@ public:
operator QVariant() const;
bool isDetached();
private:
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPen &);
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPen &);
public:
using DataPtr = QExplicitlySharedDataPointer<QPenPrivate>;
private:
void detach();
class QPenPrivate *d;
DataPtr d;
public:
typedef QPenPrivate * DataPtr;
inline DataPtr &data_ptr() { return d; }
};

View File

@ -16,14 +16,15 @@
//
#include <QtCore/private/qglobal_p.h>
#include <QtCore/qshareddata.h>
QT_BEGIN_NAMESPACE
class QPenPrivate {
class QPenPrivate : public QSharedData
{
public:
QPenPrivate(const QBrush &brush, qreal width, Qt::PenStyle, Qt::PenCapStyle,
Qt::PenJoinStyle _joinStyle);
QAtomicInt ref;
qreal width;
QBrush brush;
Qt::PenStyle style;