Fix distribution of font properties in QTextFormat
The area reserved for font properties was too small for the properties we needed, and as a result font properties were added outside of the area and special-cased (in the case of FontLetterSpacingType) or ignored (in the case of FontStretch) by conditions that check if the property is within the designated area. We reorganize the enum values now that we can, and allocate some more space for the font properties area. Fixes: QTBUG-65345 Change-Id: I8121ff7f72102d8022c6a6d2f8ed9c35dcdbb321 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
1ef8470c80
commit
761197e9d2
@ -201,10 +201,9 @@ public:
|
||||
inline void insertProperty(qint32 key, const QVariant &value)
|
||||
{
|
||||
hashDirty = true;
|
||||
if ((key >= QTextFormat::FirstFontProperty && key <= QTextFormat::LastFontProperty)
|
||||
|| key == QTextFormat::FontLetterSpacingType) {
|
||||
if (key >= QTextFormat::FirstFontProperty && key <= QTextFormat::LastFontProperty)
|
||||
fontDirty = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < props.count(); ++i)
|
||||
if (props.at(i).key == key) {
|
||||
props[i].value = value;
|
||||
@ -218,10 +217,8 @@ public:
|
||||
for (int i = 0; i < props.count(); ++i)
|
||||
if (props.at(i).key == key) {
|
||||
hashDirty = true;
|
||||
if ((key >= QTextFormat::FirstFontProperty && key <= QTextFormat::LastFontProperty)
|
||||
|| key == QTextFormat::FontLetterSpacingType) {
|
||||
if (key >= QTextFormat::FirstFontProperty && key <= QTextFormat::LastFontProperty)
|
||||
fontDirty = true;
|
||||
}
|
||||
props.remove(i);
|
||||
return;
|
||||
}
|
||||
@ -444,7 +441,22 @@ void QTextFormatPrivate::recalcFont() const
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextFormat &fmt)
|
||||
{
|
||||
stream << fmt.format_type << fmt.properties();
|
||||
QMap<int, QVariant> properties = fmt.properties();
|
||||
if (stream.version() < QDataStream::Qt_6_0) {
|
||||
auto it = properties.find(QTextFormat::FontLetterSpacingType);
|
||||
if (it != properties.end()) {
|
||||
properties[QTextFormat::OldFontLetterSpacingType] = it.value();
|
||||
properties.erase(it);
|
||||
}
|
||||
|
||||
it = properties.find(QTextFormat::FontStretch);
|
||||
if (it != properties.end()) {
|
||||
properties[QTextFormat::OldFontStretch] = it.value();
|
||||
properties.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
stream << fmt.format_type << properties;
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -459,8 +471,14 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
|
||||
fmt.d = new QTextFormatPrivate();
|
||||
|
||||
for (QMap<qint32, QVariant>::ConstIterator it = properties.constBegin();
|
||||
it != properties.constEnd(); ++it)
|
||||
fmt.d->insertProperty(it.key(), it.value());
|
||||
it != properties.constEnd(); ++it) {
|
||||
qint32 key = it.key();
|
||||
if (key == QTextFormat::OldFontLetterSpacingType)
|
||||
key = QTextFormat::FontLetterSpacingType;
|
||||
else if (key == QTextFormat::OldFontStretch)
|
||||
key = QTextFormat::FontStretch;
|
||||
fmt.d->insertProperty(key, it.value());
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
@ -620,6 +638,8 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
|
||||
\value IsAnchor
|
||||
\value AnchorHref
|
||||
\value AnchorName
|
||||
\omitvalue OldFontLetterSpacingType
|
||||
\omitvalue OldFontStretch
|
||||
\value ObjectType
|
||||
|
||||
List properties
|
||||
|
@ -184,16 +184,16 @@ public:
|
||||
// character properties
|
||||
FirstFontProperty = 0x1FE0,
|
||||
FontCapitalization = FirstFontProperty,
|
||||
FontLetterSpacingType = 0x2033,
|
||||
FontLetterSpacing = 0x1FE1,
|
||||
FontWordSpacing = 0x1FE2,
|
||||
FontStretch = 0x2034,
|
||||
FontStyleHint = 0x1FE3,
|
||||
FontStyleStrategy = 0x1FE4,
|
||||
FontKerning = 0x1FE5,
|
||||
FontHintingPreference = 0x1FE6,
|
||||
FontFamilies = 0x1FE7,
|
||||
FontStyleName = 0x1FE8,
|
||||
FontLetterSpacingType = 0x1FE9,
|
||||
FontStretch = 0x1FEA,
|
||||
FontFamily = 0x2000,
|
||||
FontPointSize = 0x2001,
|
||||
FontSizeAdjustment = 0x2002,
|
||||
@ -207,7 +207,7 @@ public:
|
||||
FontPixelSize = 0x2009,
|
||||
LastFontProperty = FontPixelSize,
|
||||
|
||||
TextUnderlineColor = 0x2010,
|
||||
TextUnderlineColor = 0x2020,
|
||||
TextVerticalAlignment = 0x2021,
|
||||
TextOutline = 0x2022,
|
||||
TextUnderlineStyle = 0x2023,
|
||||
@ -216,6 +216,12 @@ public:
|
||||
IsAnchor = 0x2030,
|
||||
AnchorHref = 0x2031,
|
||||
AnchorName = 0x2032,
|
||||
|
||||
// Included for backwards compatibility with old QDataStreams.
|
||||
// Should not be referenced in user code.
|
||||
OldFontLetterSpacingType = 0x2033,
|
||||
OldFontStretch = 0x2034,
|
||||
|
||||
ObjectType = 0x2f00,
|
||||
|
||||
// list properties
|
||||
|
@ -40,6 +40,10 @@
|
||||
#include <qtextlayout.h>
|
||||
#include <qabstracttextdocumentlayout.h>
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
# include <qdatastream.h>
|
||||
#endif
|
||||
|
||||
class tst_QTextFormat : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -61,6 +65,10 @@ private slots:
|
||||
void setFont_collection_data();
|
||||
void setFont_collection();
|
||||
void clearCollection();
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
void dataStreamCompatibility();
|
||||
#endif
|
||||
};
|
||||
|
||||
/*! \internal
|
||||
@ -677,5 +685,125 @@ void tst_QTextFormat::clearCollection()
|
||||
QCOMPARE(collection.defaultFont(), f); // kept, QTextDocument::clear or setPlainText should not reset the font set by setDefaultFont
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
void tst_QTextFormat::dataStreamCompatibility()
|
||||
{
|
||||
// Make sure that we are still compatible with the old values of QTextFormat::FontLetterSpacingType
|
||||
// and QTextFormat::FontStretch, when used with earlier QDataStream versions
|
||||
QTextCharFormat format;
|
||||
format.setFontStretch(42);
|
||||
format.setFontLetterSpacingType(QFont::AbsoluteSpacing);
|
||||
|
||||
// Sanity check
|
||||
{
|
||||
QMap<int, QVariant> properties = format.properties();
|
||||
QVERIFY(properties.contains(QTextFormat::FontLetterSpacingType));
|
||||
QVERIFY(properties.contains(QTextFormat::FontStretch));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontLetterSpacingType));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontStretch));
|
||||
}
|
||||
|
||||
QByteArray memory;
|
||||
|
||||
// Current stream version
|
||||
{
|
||||
{
|
||||
QBuffer buffer(&memory);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
|
||||
QDataStream stream(&buffer);
|
||||
stream << format;
|
||||
}
|
||||
|
||||
{
|
||||
QBuffer buffer(&memory);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
QDataStream stream(&buffer);
|
||||
|
||||
QTextFormat other;
|
||||
stream >> other;
|
||||
|
||||
{
|
||||
QMap<int, QVariant> properties = other.properties();
|
||||
QVERIFY(properties.contains(QTextFormat::FontLetterSpacingType));
|
||||
QVERIFY(properties.contains(QTextFormat::FontStretch));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontLetterSpacingType));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontStretch));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QBuffer buffer(&memory);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
QDataStream stream(&buffer);
|
||||
|
||||
quint32 type;
|
||||
stream >> type;
|
||||
|
||||
QMap<qint32, QVariant> properties;
|
||||
stream >> properties;
|
||||
QVERIFY(properties.contains(QTextFormat::FontLetterSpacingType));
|
||||
QVERIFY(properties.contains(QTextFormat::FontStretch));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontLetterSpacingType));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontStretch));
|
||||
}
|
||||
}
|
||||
|
||||
// Qt 5.15 stream version
|
||||
memory.clear();
|
||||
{
|
||||
{
|
||||
QBuffer buffer(&memory);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
|
||||
QDataStream stream(&buffer);
|
||||
stream.setVersion(QDataStream::Qt_5_15);
|
||||
stream << format;
|
||||
}
|
||||
|
||||
{
|
||||
QBuffer buffer(&memory);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
QDataStream stream(&buffer);
|
||||
stream.setVersion(QDataStream::Qt_5_15);
|
||||
|
||||
QTextFormat other;
|
||||
stream >> other;
|
||||
|
||||
{
|
||||
QMap<int, QVariant> properties = other.properties();
|
||||
QVERIFY(properties.contains(QTextFormat::FontLetterSpacingType));
|
||||
QVERIFY(properties.contains(QTextFormat::FontStretch));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontLetterSpacingType));
|
||||
QVERIFY(!properties.contains(QTextFormat::OldFontStretch));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QBuffer buffer(&memory);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
QDataStream stream(&buffer);
|
||||
stream.setVersion(QDataStream::Qt_5_15);
|
||||
|
||||
quint32 type;
|
||||
stream >> type;
|
||||
|
||||
// Verify that old data stream still has the compatibility values
|
||||
QMap<qint32, QVariant> properties;
|
||||
stream >> properties;
|
||||
QVERIFY(!properties.contains(QTextFormat::FontLetterSpacingType));
|
||||
QVERIFY(!properties.contains(QTextFormat::FontStretch));
|
||||
QVERIFY(properties.contains(QTextFormat::OldFontLetterSpacingType));
|
||||
QVERIFY(properties.contains(QTextFormat::OldFontStretch));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif // QT_NO_DATASTREAM
|
||||
|
||||
QTEST_MAIN(tst_QTextFormat)
|
||||
#include "tst_qtextformat.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user