From 71faedc5b4c1f95f47fba6d65b8f619602964d6f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 12 Nov 2021 08:14:25 +0100 Subject: [PATCH] Fix deserializing Qt 5.x fonts through QDataStream In Qt 5, fonts had both singular family and plural families properties, and both were stored separately when streaming through QDataStream. The families list was treated as an extension of family in this case, and the primary font family was always the singular family property. In Qt 6, it has been merged into one and family() is now just a convenience for families().at(0). But when reading files generated with Qt 5, we would ignore the fact that these were previously separated. We would first read the family entry into the families list, and then we would later overwrite this with an empty families list. Instead, we detect streams created with Qt 5.15 or lower and make sure we append the families list instead of overwriting it in this case. In addition, we need to make sure we split up the list again when outputting to Qt 5.x. This adds a file generated with QDataStream in Qt 5.15 to the test to verify. [ChangeLog][Fonts] Fixed a problem deserializing the family of fonts that had been serialized using QDataStream in Qt 5. Pick-to: 6.2 Fixes: QTBUG-97995 Change-Id: Id3c6e13fc2375685643caee5f8e3009c00918ccb Reviewed-by: Qt CI Bot Reviewed-by: Andy Shaw --- src/gui/text/qfont.cpp | 13 ++++++-- tests/auto/gui/text/qfont/CMakeLists.txt | 1 + tests/auto/gui/text/qfont/datastream.515 | Bin 0 -> 121 bytes tests/auto/gui/text/qfont/testfont.qrc | 1 + tests/auto/gui/text/qfont/tst_qfont.cpp | 38 +++++++++++++++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 tests/auto/gui/text/qfont/datastream.515 diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index ba36b0790d..ae0c495dcf 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2387,8 +2387,12 @@ QDataStream &operator<<(QDataStream &s, const QFont &font) s << (quint8)font.d->request.hintingPreference; if (s.version() >= QDataStream::Qt_5_6) s << (quint8)font.d->capital; - if (s.version() >= QDataStream::Qt_5_13) - s << font.d->request.families; + if (s.version() >= QDataStream::Qt_5_13) { + if (s.version() < QDataStream::Qt_6_0) + s << font.d->request.families.mid(1); + else + s << font.d->request.families; + } return s; } @@ -2498,7 +2502,10 @@ QDataStream &operator>>(QDataStream &s, QFont &font) if (s.version() >= QDataStream::Qt_5_13) { QStringList value; s >> value; - font.d->request.families = value; + if (s.version() < QDataStream::Qt_6_0) + font.d->request.families.append(value); + else + font.d->request.families = value; } return s; } diff --git a/tests/auto/gui/text/qfont/CMakeLists.txt b/tests/auto/gui/text/qfont/CMakeLists.txt index 05c6ca8270..6e0583bc30 100644 --- a/tests/auto/gui/text/qfont/CMakeLists.txt +++ b/tests/auto/gui/text/qfont/CMakeLists.txt @@ -16,6 +16,7 @@ qt_internal_add_test(tst_qfont # Resources: set(testfont_resource_files + "datastream.515" "weirdfont.otf" ) diff --git a/tests/auto/gui/text/qfont/datastream.515 b/tests/auto/gui/text/qfont/datastream.515 new file mode 100644 index 0000000000000000000000000000000000000000..acd99e7e9bd4e37c20ceccea4c4eb2558b68d493 GIT binary patch literal 121 zcmZQzU=U+)W5{GEVkl-P0kRSqa)G=YhRXjy;Gn?(1|T*o10#cx00WRj224PX1cN_N SYX(Cq&=4d87!2{q836#uY!-(A literal 0 HcmV?d00001 diff --git a/tests/auto/gui/text/qfont/testfont.qrc b/tests/auto/gui/text/qfont/testfont.qrc index cf51e4a2b4..7a7b66f984 100644 --- a/tests/auto/gui/text/qfont/testfont.qrc +++ b/tests/auto/gui/text/qfont/testfont.qrc @@ -1,5 +1,6 @@ weirdfont.otf + datastream.515 diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp index 6bae45e5c3..e0ece40bdf 100644 --- a/tests/auto/gui/text/qfont/tst_qfont.cpp +++ b/tests/auto/gui/text/qfont/tst_qfont.cpp @@ -62,6 +62,7 @@ private slots: void insertAndRemoveSubstitutions(); void serialize_data(); void serialize(); + void deserializeQt515(); void styleName(); void defaultFamily_data(); @@ -511,6 +512,43 @@ void tst_QFont::serialize() } } +void tst_QFont::deserializeQt515() +{ + QFile file; + file.setFileName(QFINDTESTDATA("datastream.515")); + QVERIFY(file.open(QIODevice::ReadOnly)); + + QFont font; + { + QDataStream stream(&file); + stream.setVersion(QDataStream::Qt_5_15); + stream >> font; + } + + QCOMPARE(font.family(), QStringLiteral("FirstFamily")); + QCOMPARE(font.families().size(), 3); + QCOMPARE(font.families().at(0), QStringLiteral("FirstFamily")); + QCOMPARE(font.families().at(1), QStringLiteral("OtherFamily1")); + QCOMPARE(font.families().at(2), QStringLiteral("OtherFamily2")); + QCOMPARE(font.pointSize(), 12); + + QVERIFY(file.reset()); + QByteArray fileContent = file.readAll(); + QByteArray serializedContent; + { + QBuffer buffer(&serializedContent); + QVERIFY(buffer.open(QIODevice::WriteOnly)); + + QDataStream stream(&buffer); + stream.setVersion(QDataStream::Qt_5_15); + stream << font; + } + + QCOMPARE(serializedContent, fileContent); + + file.close(); +} + void tst_QFont::styleName() { #if !defined(Q_OS_MAC)