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 <eirik.aavitsland@qt.io>
(cherry picked from commit 77a9a208227ecf750d620b3048053fd4fc4299a4)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2024-08-15 13:12:27 +02:00 committed by Qt Cherry-pick Bot
parent 9313c60cd9
commit aa9a991169
2 changed files with 229 additions and 24 deletions

View File

@ -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())
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::FontWeight) && format.fontWeight() != QFont::Normal) {
}
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 (format.fontWeight() == QFont::Bold)
if (weight == QFont::Bold)
value = QString::fromLatin1("bold");
else
value = QString::number(format.fontWeight());
value = QString::number(weight);
writer.writeAttribute(foNS, QString::fromLatin1("font-weight"), value);
}
if (format.hasProperty(QTextFormat::OldFontFamily))
writer.writeAttribute(foNS, QString::fromLatin1("font-family"), format.fontFamilies().toStringList().value(0, QString()));
else
}
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)) {

View File

@ -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<QFont>("defaultFont");
QTest::addColumn<QTextCharFormat>("charFormat");
QTest::addColumn<QString>("xml");
QTextCharFormat emptyFormat;
QTest::newRow("default")
<< QFont()
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\"/></style:style>";
QTest::newRow("family")
<< QFont(QStringLiteral("Foobar"))
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Foobar\"/></style:style>";
{
QFont font;
font.setPointSizeF(7.5);
QTest::newRow("point-size")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\" fo:font-size=\"7.5pt\"/></style:style>";
}
{
QFont font;
font.setItalic(true);
QTest::newRow("italic")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-style=\"italic\" fo:font-family=\"Sans\"/></style:style>";
}
{
QFont font;
font.setBold(true);
QTest::newRow("bold")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-weight=\"bold\" fo:font-family=\"Sans\"/></style:style>";
}
{
QFont font;
font.setCapitalization(QFont::AllUppercase);
QTest::newRow("capitalization")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\" fo:text-transform=\"uppercase\"/></style:style>";
}
{
QFont font;
font.setLetterSpacing(QFont::PercentageSpacing, 10);
QTest::newRow("letter-spacing")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\" fo:letter-spacing=\"7.5pt\"/></style:style>";
}
{
QFont font;
font.setWordSpacing(10);
QTest::newRow("word-spacing")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\" fo:word-spacing=\"7.5pt\"/></style:style>";
}
{
QFont font;
font.setUnderline(true);
QTest::newRow("underline")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\" style:text-underline-type=\"single\"/></style:style>";
}
{
QFont font;
font.setStrikeOut(true);
QTest::newRow("strike-out")
<< font
<< emptyFormat
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-family=\"Sans\" style:text-line-through-type=\"single\"/></style:style>";
}
{
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
<< "<style:style style:name=\"c4\" style:family=\"text\"><style:text-properties fo:font-style=\"italic\" fo:font-weight=\"300\" fo:font-family=\"Bar\" fo:font-size=\"5.5pt\" fo:text-transform=\"lowercase\" fo:letter-spacing=\"15pt\" fo:word-spacing=\"22.5pt\" style:text-underline-type=\"single\" style:text-line-through-type=\"single\" style:text-underline-style=\"solid\"/></style:style>";
}
}
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);