From aa9a99116988d6cc56df63ff53fc6b3ce752b0f7 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 15 Aug 2024 13:12:27 +0200 Subject: [PATCH] Respect QTextDocument::defaultFont() in ODF writer The ODF writer would ignore the default font set on the document and just output default values according to spec, such as "Sans" for the font family. With this patch, any settings set explicitly on the default font will be taken into account, granted that they are not overridden by any properties in the QTextCharFormat. [ChangeLog][Text] The ODF backend to QTextDocumentWriter will now respect the default font set on the QTextDocument. Fixes: QTBUG-124570 Change-Id: Ia937420f7f721bbf3264661160cb0a593907358c Reviewed-by: Eirik Aavitsland (cherry picked from commit 77a9a208227ecf750d620b3048053fd4fc4299a4) Reviewed-by: Qt Cherry-pick Bot --- src/gui/text/qtextodfwriter.cpp | 111 +++++++++++--- .../qtextodfwriter/tst_qtextodfwriter.cpp | 142 ++++++++++++++++++ 2 files changed, 229 insertions(+), 24 deletions(-) diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index b50771c12f0..e980e1bb4ee 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -635,24 +635,59 @@ void QTextOdfWriter::writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFor writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("c%1").arg(formatIndex)); writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("text")); writer.writeEmptyElement(styleNS, QString::fromLatin1("text-properties")); - if (format.fontItalic()) - writer.writeAttribute(foNS, QString::fromLatin1("font-style"), QString::fromLatin1("italic")); - if (format.hasProperty(QTextFormat::FontWeight) && format.fontWeight() != QFont::Normal) { - QString value; - if (format.fontWeight() == QFont::Bold) - value = QString::fromLatin1("bold"); - else - value = QString::number(format.fontWeight()); - writer.writeAttribute(foNS, QString::fromLatin1("font-weight"), value); + + const QFont defaultFont = m_document->defaultFont(); + const uint defaultFontResolveMask = defaultFont.resolveMask(); + + if (format.hasProperty(QTextFormat::FontItalic) + || (defaultFontResolveMask & QFont::StyleResolved)) { + const bool italic = format.hasProperty(QTextFormat::FontItalic) ? format.fontItalic() : defaultFont.italic(); + if (italic) + writer.writeAttribute(foNS, QString::fromLatin1("font-style"), QString::fromLatin1("italic")); } - if (format.hasProperty(QTextFormat::OldFontFamily)) - writer.writeAttribute(foNS, QString::fromLatin1("font-family"), format.fontFamilies().toStringList().value(0, QString())); - else + + if (format.hasProperty(QTextFormat::FontWeight) + || (defaultFontResolveMask & QFont::WeightResolved)) { + int weight = format.hasProperty(QTextFormat::FontWeight) + ? format.fontWeight() + : defaultFont.weight(); + + if (weight != QFont::Normal) { + QString value; + if (weight == QFont::Bold) + value = QString::fromLatin1("bold"); + else + value = QString::number(weight); + writer.writeAttribute(foNS, QString::fromLatin1("font-weight"), value); + } + } + + if (format.hasProperty(QTextFormat::OldFontFamily) + || format.hasProperty(QTextFormat::FontFamilies) + || (defaultFontResolveMask & QFont::FamiliesResolved)) { + const QString fontFamily = (format.hasProperty(QTextFormat::OldFontFamily) + || format.hasProperty(QTextFormat::FontFamilies)) + ? format.fontFamilies().toStringList().value(0, QString()) + : defaultFont.family(); + writer.writeAttribute(foNS, QString::fromLatin1("font-family"), fontFamily); + } else { writer.writeAttribute(foNS, QString::fromLatin1("font-family"), QString::fromLatin1("Sans")); // Qt default - if (format.hasProperty(QTextFormat::FontPointSize)) - writer.writeAttribute(foNS, QString::fromLatin1("font-size"), QString::fromLatin1("%1pt").arg(format.fontPointSize())); - if (format.hasProperty(QTextFormat::FontCapitalization)) { - switch(format.fontCapitalization()) { + } + + if (format.hasProperty(QTextFormat::FontPointSize) + || (defaultFontResolveMask & QFont::SizeResolved)) { + const qreal pointSize = format.hasProperty(QTextFormat::FontPointSize) + ? format.fontPointSize() + : defaultFont.pointSizeF(); + writer.writeAttribute(foNS, QString::fromLatin1("font-size"), QString::fromLatin1("%1pt").arg(pointSize)); + } + + if (format.hasProperty(QTextFormat::FontCapitalization) + || (defaultFontResolveMask & QFont::CapitalizationResolved)) { + QFont::Capitalization capitalization = format.hasProperty(QTextFormat::FontCapitalization) + ? format.fontCapitalization() + : defaultFont.capitalization(); + switch(capitalization) { case QFont::MixedCase: writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("none")); break; case QFont::AllUppercase: @@ -665,19 +700,47 @@ void QTextOdfWriter::writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFor writer.writeAttribute(foNS, QString::fromLatin1("font-variant"), QString::fromLatin1("small-caps")); break; } } - if (format.hasProperty(QTextFormat::FontLetterSpacing)) - writer.writeAttribute(foNS, QString::fromLatin1("letter-spacing"), pixelToPoint(format.fontLetterSpacing())); - if (format.hasProperty(QTextFormat::FontWordSpacing) && format.fontWordSpacing() != 0) - writer.writeAttribute(foNS, QString::fromLatin1("word-spacing"), pixelToPoint(format.fontWordSpacing())); - if (format.hasProperty(QTextFormat::FontUnderline)) + + if (format.hasProperty(QTextFormat::FontLetterSpacing) || + (defaultFontResolveMask & QFont::LetterSpacingResolved)) { + const qreal letterSpacing = format.hasProperty(QTextFormat::FontLetterSpacing) + ? format.fontLetterSpacing() + : defaultFont.letterSpacing(); + writer.writeAttribute(foNS, QString::fromLatin1("letter-spacing"), pixelToPoint(letterSpacing)); + } + + if (format.hasProperty(QTextFormat::FontWordSpacing) + || (defaultFontResolveMask & QFont::WordSpacingResolved)) { + const qreal wordSpacing = format.hasProperty(QTextFormat::FontWordSpacing) + ? format.fontWordSpacing() + : defaultFont.wordSpacing(); + if (wordSpacing != 0) + writer.writeAttribute(foNS, QString::fromLatin1("word-spacing"), pixelToPoint(wordSpacing)); + } + + if (format.hasProperty(QTextFormat::FontUnderline) + || ((defaultFontResolveMask & QFont::UnderlineResolved) + && !format.hasProperty(QTextFormat::TextUnderlineStyle))) { + const bool underline = format.hasProperty(QTextFormat::FontUnderline) + ? format.fontUnderline() + : defaultFont.underline(); writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-type"), - format.fontUnderline() ? QString::fromLatin1("single") : QString::fromLatin1("none")); + underline ? QString::fromLatin1("single") : QString::fromLatin1("none")); + } + if (format.hasProperty(QTextFormat::FontOverline)) { // bool fontOverline () const TODO } - if (format.hasProperty(QTextFormat::FontStrikeOut)) + + if (format.hasProperty(QTextFormat::FontStrikeOut) + || (defaultFontResolveMask & QFont::StrikeOutResolved)) { + const bool strikeOut = format.hasProperty(QTextFormat::FontStrikeOut) + ? format.fontStrikeOut() + : defaultFont.strikeOut(); writer.writeAttribute(styleNS,QString::fromLatin1( "text-line-through-type"), - format.fontStrikeOut() ? QString::fromLatin1("single") : QString::fromLatin1("none")); + strikeOut ? QString::fromLatin1("single") : QString::fromLatin1("none")); + } + if (format.hasProperty(QTextFormat::TextUnderlineColor)) writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-color"), format.underlineColor().name()); if (format.hasProperty(QTextFormat::FontFixedPitch)) { diff --git a/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp b/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp index 6b56e7c7274..8957d0d21cb 100644 --- a/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp +++ b/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp @@ -32,6 +32,8 @@ private slots: void testWriteSection(); void testWriteTable(); void testWriteFrameFormat(); + void testWriteDefaultFont_data(); + void testWriteDefaultFont(); private: /// closes the document and returns the part of the XML stream that the test wrote @@ -144,6 +146,146 @@ void tst_QTextOdfWriter::testWriteStyle1_data() } +void tst_QTextOdfWriter::testWriteDefaultFont_data() +{ + QTest::addColumn("defaultFont"); + QTest::addColumn("charFormat"); + QTest::addColumn("xml"); + + QTextCharFormat emptyFormat; + + QTest::newRow("default") + << QFont() + << emptyFormat + << ""; + + QTest::newRow("family") + << QFont(QStringLiteral("Foobar")) + << emptyFormat + << ""; + + { + QFont font; + font.setPointSizeF(7.5); + QTest::newRow("point-size") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setItalic(true); + QTest::newRow("italic") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setBold(true); + QTest::newRow("bold") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setCapitalization(QFont::AllUppercase); + QTest::newRow("capitalization") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setLetterSpacing(QFont::PercentageSpacing, 10); + QTest::newRow("letter-spacing") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setWordSpacing(10); + QTest::newRow("word-spacing") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setUnderline(true); + QTest::newRow("underline") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setStrikeOut(true); + QTest::newRow("strike-out") + << font + << emptyFormat + << ""; + } + + { + QFont font; + font.setFamily(QStringLiteral("Foo")); + font.setPointSizeF(7.5); + font.setStrikeOut(false); + font.setItalic(false); + font.setUnderline(false); + font.setLetterSpacing(QFont::PercentageSpacing, 10); + font.setWordSpacing(20); + font.setWeight(QFont::Bold); + font.setCapitalization(QFont::AllUppercase); + + QTextCharFormat format; + format.setFontItalic(true); + format.setFontFamilies(QStringList() << QStringLiteral("Bar")); + format.setFontPointSize(5.5); + format.setFontStrikeOut(true); + format.setFontLetterSpacing(20); + format.setFontWordSpacing(30); + format.setFontWeight(QFont::Light); + format.setUnderlineStyle(QTextCharFormat::SingleUnderline); + format.setFontCapitalization(QFont::AllLowercase); + + QTest::newRow("char-format-precedence") + << font + << format + << ""; + } + +} + +void tst_QTextOdfWriter::testWriteDefaultFont() +{ + QFETCH(QFont, defaultFont); + QFETCH(QTextCharFormat, charFormat); + QFETCH(QString, xml); + + document->clear(); + document->setDefaultFont(defaultFont); + + QTextCursor cursor(document); + cursor.setCharFormat(charFormat); + cursor.insertText(QStringLiteral("Test")); + + odfWriter->writeCharacterFormat(*xmlWriter, cursor.charFormat(), 4); + QCOMPARE( getContentFromXml(), xml); + + +} + void tst_QTextOdfWriter::testWriteStyle1() { QFETCH(QString, htmlInput);