Properly serialize QFont.
Some data was never serialized (styleName, hintingPreference) and some was incorrectly serialized (styleStrategy). This change also adds auto tests for every applicable QDataStream version. [ChangeLog][QtGui][QFont] QFont now serializes its data properly, without any data loss. Task-number: QTBUG-22814 Task-number: QTBUG-22946 Change-Id: I34e61b10662b7ad6c57054dacc7e1f522f5b5c5d Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
This commit is contained in:
parent
bd822bedfe
commit
4f50be8d18
@ -89,7 +89,7 @@ public:
|
||||
Qt_5_1 = 14,
|
||||
Qt_5_2 = 15,
|
||||
Qt_5_3 = Qt_5_2,
|
||||
Qt_5_4 = Qt_5_3
|
||||
Qt_5_4 = 16
|
||||
#if QT_VERSION >= 0x050500
|
||||
#error Add the datastream version for this Qt version
|
||||
#endif
|
||||
|
@ -2163,6 +2163,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
|
||||
s << font.d->request.family.toLatin1();
|
||||
} else {
|
||||
s << font.d->request.family;
|
||||
if (s.version() >= QDataStream::Qt_5_4)
|
||||
s << font.d->request.styleName;
|
||||
}
|
||||
|
||||
if (s.version() >= QDataStream::Qt_4_0) {
|
||||
@ -2183,8 +2185,14 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
|
||||
}
|
||||
|
||||
s << (quint8) font.d->request.styleHint;
|
||||
if (s.version() >= QDataStream::Qt_3_1)
|
||||
s << (quint8) font.d->request.styleStrategy;
|
||||
if (s.version() >= QDataStream::Qt_3_1) {
|
||||
// Continue writing 8 bits for versions < 5.4 so that we don't write too much,
|
||||
// even though we need 16 to store styleStrategy, so there is some data loss.
|
||||
if (s.version() >= QDataStream::Qt_5_4)
|
||||
s << (quint16) font.d->request.styleStrategy;
|
||||
else
|
||||
s << (quint8) font.d->request.styleStrategy;
|
||||
}
|
||||
s << (quint8) 0
|
||||
<< (quint8) font.d->request.weight
|
||||
<< get_font_bits(s.version(), font.d.data());
|
||||
@ -2196,6 +2204,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
|
||||
s << font.d->letterSpacing.value();
|
||||
s << font.d->wordSpacing.value();
|
||||
}
|
||||
if (s.version() >= QDataStream::Qt_5_4)
|
||||
s << (quint8)font.d->request.hintingPreference;
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -2213,7 +2223,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
|
||||
font.d = new QFontPrivate;
|
||||
font.resolve_mask = QFont::AllPropertiesResolved;
|
||||
|
||||
quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
|
||||
quint8 styleHint, charSet, weight, bits;
|
||||
quint16 styleStrategy = QFont::PreferDefault;
|
||||
|
||||
if (s.version() == 1) {
|
||||
QByteArray fam;
|
||||
@ -2221,6 +2232,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
|
||||
font.d->request.family = QString::fromLatin1(fam);
|
||||
} else {
|
||||
s >> font.d->request.family;
|
||||
if (s.version() >= QDataStream::Qt_5_4)
|
||||
s >> font.d->request.styleName;
|
||||
}
|
||||
|
||||
if (s.version() >= QDataStream::Qt_4_0) {
|
||||
@ -2240,8 +2253,15 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
|
||||
font.d->request.pixelSize = pixelSize;
|
||||
}
|
||||
s >> styleHint;
|
||||
if (s.version() >= QDataStream::Qt_3_1)
|
||||
s >> styleStrategy;
|
||||
if (s.version() >= QDataStream::Qt_3_1) {
|
||||
if (s.version() >= QDataStream::Qt_5_4) {
|
||||
s >> styleStrategy;
|
||||
} else {
|
||||
quint8 tempStyleStrategy;
|
||||
s >> tempStyleStrategy;
|
||||
styleStrategy = tempStyleStrategy;
|
||||
}
|
||||
}
|
||||
|
||||
s >> charSet;
|
||||
s >> weight;
|
||||
@ -2271,6 +2291,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
|
||||
s >> value;
|
||||
font.d->wordSpacing.setValue(value);
|
||||
}
|
||||
if (s.version() >= QDataStream::Qt_5_4) {
|
||||
quint8 value;
|
||||
s >> value;
|
||||
font.d->request.hintingPreference = QFont::HintingPreference(value);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ struct QFontDef
|
||||
uint weight : 7; // 0-99
|
||||
uint fixedPitch : 1;
|
||||
uint style : 2;
|
||||
uint stretch : 12; // 0-400
|
||||
uint stretch : 12; // 0-4000
|
||||
|
||||
uint hintingPreference : 2;
|
||||
uint ignorePitch : 1;
|
||||
|
@ -270,7 +270,9 @@ static int NColorRoles[] = {
|
||||
QPalette::ToolTipText + 1, // Qt_5_0
|
||||
QPalette::ToolTipText + 1, // Qt_5_1
|
||||
QPalette::ToolTipText + 1, // Qt_5_2
|
||||
0 // add the correct value for Qt_5_3 here later
|
||||
QPalette::ToolTipText + 1, // Qt_5_3
|
||||
QPalette::ToolTipText + 1, // Qt_5_4
|
||||
0 // add the correct value for Qt_5_5 here later
|
||||
};
|
||||
|
||||
// Testing get/set functions
|
||||
|
@ -77,7 +77,8 @@ private slots:
|
||||
void setFontRaw();
|
||||
void italicOblique();
|
||||
void insertAndRemoveSubstitutions();
|
||||
void serializeSpacing();
|
||||
void serialize_data();
|
||||
void serialize();
|
||||
void lastResortFont();
|
||||
void styleName();
|
||||
void defaultFamily_data();
|
||||
@ -568,7 +569,6 @@ void tst_QFont::insertAndRemoveSubstitutions()
|
||||
QVERIFY(QFont::substitutes("bogusfontfamily").isEmpty());
|
||||
}
|
||||
|
||||
|
||||
static QFont copyFont(const QFont &font1) // copy using a QDataStream
|
||||
{
|
||||
QBuffer buffer;
|
||||
@ -583,29 +583,115 @@ static QFont copyFont(const QFont &font1) // copy using a QDataStream
|
||||
return font2;
|
||||
}
|
||||
|
||||
void tst_QFont::serializeSpacing()
|
||||
Q_DECLARE_METATYPE(QDataStream::Version)
|
||||
|
||||
void tst_QFont::serialize_data()
|
||||
{
|
||||
QFont font;
|
||||
QCOMPARE(font.letterSpacing(), 0.);
|
||||
QCOMPARE(font.wordSpacing(), 0.);
|
||||
QTest::addColumn<QFont>("font");
|
||||
// The version in which the tested feature was added.
|
||||
QTest::addColumn<QDataStream::Version>("minimumStreamVersion");
|
||||
|
||||
QFont basicFont;
|
||||
// Versions <= Qt 2.1 had broken point size serialization,
|
||||
// so we set an integer point size.
|
||||
basicFont.setPointSize(9);
|
||||
|
||||
QFont font = basicFont;
|
||||
QTest::newRow("defaultConstructed") << font << QDataStream::Qt_1_0;
|
||||
|
||||
font.setLetterSpacing(QFont::AbsoluteSpacing, 105);
|
||||
QCOMPARE(font.letterSpacing(), 105.);
|
||||
QCOMPARE(font.letterSpacingType(), QFont::AbsoluteSpacing);
|
||||
QCOMPARE(font.wordSpacing(), 0.);
|
||||
QFont font2 = copyFont(font);
|
||||
QCOMPARE(font2.letterSpacing(), 105.);
|
||||
QCOMPARE(font2.letterSpacingType(), QFont::AbsoluteSpacing);
|
||||
QCOMPARE(font2.wordSpacing(), 0.);
|
||||
QTest::newRow("letterSpacing") << font << QDataStream::Qt_4_5;
|
||||
|
||||
font = basicFont;
|
||||
font.setWordSpacing(50.0);
|
||||
QCOMPARE(font.letterSpacing(), 105.);
|
||||
QCOMPARE(font.wordSpacing(), 50.);
|
||||
QTest::newRow("wordSpacing") << font << QDataStream::Qt_4_5;
|
||||
|
||||
QFont font3 = copyFont(font);
|
||||
QCOMPARE(font3.letterSpacing(), 105.);
|
||||
QCOMPARE(font3.letterSpacingType(), QFont::AbsoluteSpacing);
|
||||
QCOMPARE(font3.wordSpacing(), 50.);
|
||||
font = basicFont;
|
||||
font.setPointSize(20);
|
||||
QTest::newRow("pointSize") << font << QDataStream::Qt_1_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setPixelSize(32);
|
||||
QTest::newRow("pixelSize") << font << QDataStream::Qt_3_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setStyleHint(QFont::Monospace);
|
||||
QTest::newRow("styleHint") << font << QDataStream::Qt_1_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setStretch(4000);
|
||||
QTest::newRow("stretch") << font << QDataStream::Qt_4_3;
|
||||
|
||||
font = basicFont;
|
||||
font.setWeight(99);
|
||||
QTest::newRow("weight") << font << QDataStream::Qt_1_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setUnderline(true);
|
||||
QTest::newRow("underline") << font << QDataStream::Qt_1_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setStrikeOut(true);
|
||||
QTest::newRow("strikeOut") << font << QDataStream::Qt_1_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setFixedPitch(true);
|
||||
// This fails for versions less than this, as ignorePitch is set to false
|
||||
// whenever setFixedPitch() is called, but ignorePitch is considered an
|
||||
// extended bit, which were apparently not available until 4.4.
|
||||
QTest::newRow("fixedPitch") << font << QDataStream::Qt_4_4;
|
||||
|
||||
font = basicFont;
|
||||
font.setLetterSpacing(QFont::AbsoluteSpacing, 10);
|
||||
// Fails for 4.4 because letterSpacing wasn't read until 4.5.
|
||||
QTest::newRow("letterSpacing") << font << QDataStream::Qt_4_5;
|
||||
|
||||
font = basicFont;
|
||||
font.setRawMode(true);
|
||||
QTest::newRow("rawMode") << font << QDataStream::Qt_1_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setKerning(false);
|
||||
QTest::newRow("kerning") << font << QDataStream::Qt_4_0;
|
||||
|
||||
font = basicFont;
|
||||
font.setStyleStrategy(QFont::NoFontMerging);
|
||||
// This wasn't read properly until 5.4.
|
||||
QTest::newRow("styleStrategy") << font << QDataStream::Qt_5_4;
|
||||
|
||||
font = basicFont;
|
||||
font.setHintingPreference(QFont::PreferFullHinting);
|
||||
// This wasn't read until 5.4.
|
||||
QTest::newRow("hintingPreference") << font << QDataStream::Qt_5_4;
|
||||
|
||||
font = basicFont;
|
||||
font.setStyleName("Regular Black Condensed");
|
||||
// This wasn't read until 5.4.
|
||||
QTest::newRow("styleName") << font << QDataStream::Qt_5_4;
|
||||
}
|
||||
|
||||
void tst_QFont::serialize()
|
||||
{
|
||||
QFETCH(QFont, font);
|
||||
QFETCH(QDataStream::Version, minimumStreamVersion);
|
||||
|
||||
QDataStream stream;
|
||||
const int thisVersion = stream.version();
|
||||
|
||||
for (int version = minimumStreamVersion; version <= thisVersion; ++version) {
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
stream.setDevice(&buffer);
|
||||
stream.setVersion(version);
|
||||
stream << font;
|
||||
buffer.close();
|
||||
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QFont readFont;
|
||||
stream >> readFont;
|
||||
QVERIFY2(readFont == font, qPrintable(QString::fromLatin1("Fonts do not compare equal for QDataStream version ") +
|
||||
QString::fromLatin1("%1:\nactual: %2\nexpected: %3").arg(version).arg(readFont.toString()).arg(font.toString())));
|
||||
}
|
||||
}
|
||||
|
||||
// QFont::lastResortFont() may abort with qFatal() on QWS/QPA
|
||||
|
Loading…
Reference in New Issue
Block a user