summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2020-05-11 14:34:27 +0200
committerAndy Shaw <andy.shaw@qt.io>2020-07-07 14:34:47 +0200
commit31048d97ac4ebbacd47e8474887a2bf0c232f2dd (patch)
tree899b50f819055ec3e6c241ae3132d7aa2d000e7f
parentbcd544bd7cbf15a7e852852ec83eb9fdd242a0d3 (diff)
downloadqtbase-31048d97ac4ebbacd47e8474887a2bf0c232f2dd.tar.gz
Export the letter and word spacing settings set on the default format
When the default format has letter and word spacing set then these should be exported in the HTML's body tag. This also adds support for the reading of letter-spacing and word-spacing set too, so that the same html outputted can be read back in. Fixes: QTBUG-83718 Change-Id: Ic4afca21eb05efb779dbf99c6b3c13373e851f15 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 96cea3b1681dd24a0ec3a53078b78f902e3211a6)
-rw-r--r--src/gui/text/qcssparser.cpp39
-rw-r--r--src/gui/text/qcssparser_p.h2
-rw-r--r--src/gui/text/qtextdocument.cpp18
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp30
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp43
5 files changed, 131 insertions, 1 deletions
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 50c13d41f6..b1d353a43b 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -127,6 +127,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "image", QtImage },
{ "image-position", QtImageAlignment },
{ "left", Left },
+ { "letter-spacing", LetterSpacing },
{ "line-height", LineHeight },
{ "list-style", ListStyle },
{ "list-style-type", ListStyleType },
@@ -171,7 +172,8 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "top", Top },
{ "vertical-align", VerticalAlignment },
{ "white-space", Whitespace },
- { "width", Width }
+ { "width", Width },
+ { "word-spacing", WordSpacing }
};
static const QCssKnownValue values[NumKnownValues - 1] = {
@@ -386,6 +388,8 @@ static inline bool isInheritable(Property propertyId)
case FontVariant:
case TextTransform:
case LineHeight:
+ case LetterSpacing:
+ case WordSpacing:
return true;
default:
break;
@@ -1247,6 +1251,37 @@ static void setTextDecorationFromValues(const QVector<QCss::Value> &values, QFon
}
}
+static void setLetterSpacingFromValue(const QCss::Value &value, QFont *font)
+{
+ QString s = value.variant.toString();
+ qreal val;
+ bool ok = false;
+ if (s.endsWith(QLatin1String("em"), Qt::CaseInsensitive)) {
+ s.chop(2);
+ val = s.toDouble(&ok);
+ if (ok)
+ font->setLetterSpacing(QFont::PercentageSpacing, (val + 1.0) * 100);
+ } else if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
+ s.chop(2);
+ val = s.toDouble(&ok);
+ if (ok)
+ font->setLetterSpacing(QFont::AbsoluteSpacing, val);
+ }
+}
+
+static void setWordSpacingFromValue(const QCss::Value &value, QFont *font)
+{
+ QString s = value.variant.toString();
+ if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
+ s.chop(2);
+ qreal val;
+ bool ok = false;
+ val = s.toDouble(&ok);
+ if (ok)
+ font->setWordSpacing(val);
+ }
+}
+
static void parseShorthandFontProperty(const QVector<QCss::Value> &values, QFont *font, int *fontSizeAdjustment)
{
font->setStyle(QFont::StyleNormal);
@@ -1319,6 +1354,8 @@ bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment)
case Font: parseShorthandFontProperty(decl.d->values, font, fontSizeAdjustment); break;
case FontVariant: setFontVariantFromValue(val, font); break;
case TextTransform: setTextTransformFromValue(val, font); break;
+ case LetterSpacing: setLetterSpacingFromValue(val, font); break;
+ case WordSpacing: setWordSpacingFromValue(val, font); break;
default: continue;
}
hit = true;
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index ef5ae8c80b..cc33ec883d 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -199,6 +199,8 @@ enum Property {
FontKerning,
QtForegroundTextureCacheKey,
QtIcon,
+ LetterSpacing,
+ WordSpacing,
NumProperties
};
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 64ba01d4e5..b629264ee5 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -2357,6 +2357,24 @@ QString QTextHtmlExporter::toHtml(const QByteArray &encoding, ExportMode mode)
html += (defaultCharFormat.fontItalic() ? QLatin1String("italic") : QLatin1String("normal"));
html += QLatin1Char(';');
+ const bool percentSpacing = (defaultCharFormat.fontLetterSpacingType() == QFont::PercentageSpacing);
+ if (defaultCharFormat.hasProperty(QTextFormat::FontLetterSpacing) &&
+ (!percentSpacing || defaultCharFormat.fontLetterSpacing() != 0.0)) {
+ html += QLatin1String(" letter-spacing:");
+ qreal value = defaultCharFormat.fontLetterSpacing();
+ if (percentSpacing) // Map to em (100% == 0em)
+ value = (value / 100) - 1;
+ html += QString::number(value);
+ html += percentSpacing ? QLatin1String("em;") : QLatin1String("px;");
+ }
+
+ if (defaultCharFormat.hasProperty(QTextFormat::FontWordSpacing) &&
+ defaultCharFormat.fontWordSpacing() != 0.0) {
+ html += QLatin1String(" word-spacing:");
+ html += QString::number(defaultCharFormat.fontWordSpacing());
+ html += QLatin1String("px;");
+ }
+
// do not set text-decoration on the default font since those values are /always/ propagated
// and cannot be turned off with CSS
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 10a627bb82..fdc7997d35 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -105,6 +105,7 @@ private slots:
void toHtmlBodyBgColorTransparent();
void toHtmlRootFrameProperties();
void toHtmlLineHeightProperties();
+ void toHtmlDefaultFontSpacingProperties();
void capitalizationHtmlInExport();
void wordspacingHtmlExport();
@@ -2020,6 +2021,35 @@ void tst_QTextDocument::toHtmlLineHeightProperties()
QCOMPARE(doc.toHtml(), expectedOutput);
}
+void tst_QTextDocument::toHtmlDefaultFontSpacingProperties()
+{
+ CREATE_DOC_AND_CURSOR();
+
+ cursor.insertText("Blah");
+
+ QFont fnt = doc.defaultFont();
+ fnt.setLetterSpacing(QFont::AbsoluteSpacing, 13);
+ fnt.setWordSpacing(15);
+ doc.setDefaultFont(fnt);
+
+ QString expectedOutput = QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+ "<html><head><meta name=\"qrichtext\" content=\"1\" />"
+ "<style type=\"text/css\">\n"
+ "p, li { white-space: pre-wrap; }\n"
+ "</style></head>"
+ "<body style=\" font-family:'%1'; font-size:%2; "
+ "font-weight:%3; font-style:%4; letter-spacing:13px; "
+ "word-spacing:15px;\">\n"
+ "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah</p>"
+ "</body></html>");
+ expectedOutput = expectedOutput.arg(defaultFont.family())
+ .arg(cssFontSizeString(defaultFont))
+ .arg(defaultFont.weight() * 8)
+ .arg((defaultFont.italic() ? "italic" : "normal"));
+ QCOMPARE(doc.toHtml(), expectedOutput);
+}
+
void tst_QTextDocument::capitalizationHtmlInExport()
{
doc->setPlainText("Test");
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index 2f5936cf74..dbfbc328a1 100644
--- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -266,6 +266,7 @@ private slots:
void html_importImageWithoutAspectRatio();
void html_fromFirefox();
void html_emptyInlineInsideBlock();
+ void css_fontAndWordSpacing();
private:
inline void setHtml(const QString &html)
@@ -4251,5 +4252,47 @@ void tst_QTextDocumentFragment::html_emptyInlineInsideBlock()
QVERIFY(doc->firstBlock().blockFormat().leftMargin() > 0);
}
+void tst_QTextDocumentFragment::css_fontAndWordSpacing()
+{
+ {
+ const char html[] = "<body style=\"letter-spacing:13px; word-spacing:15px;\">Foo</span>";
+ doc->setHtml(html);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacing).toInt(), 13);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacingType).toUInt(),
+ (uint)(QFont::AbsoluteSpacing));
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontWordSpacing).toInt(), 15);
+ }
+ {
+ const char html[] = "<body style=\"letter-spacing:1em; word-spacing:0px;\">Foo</span>";
+ doc->setHtml(html);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacing).toInt(), 200);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacingType).toUInt(),
+ (uint)(QFont::PercentageSpacing));
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontWordSpacing).toInt(), 0);
+ }
+ {
+ const char html[] = "<body style=\"letter-spacing:0em;\">Foo</span>";
+ doc->setHtml(html);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacing).toInt(), 100);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacingType).toUInt(),
+ (uint)(QFont::PercentageSpacing));
+ }
+ {
+ const char html[] = "<body style=\"letter-spacing:-0.5em;\">Foo</span>";
+ doc->setHtml(html);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextCharacter);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacing).toInt(), 50);
+ QCOMPARE(cursor.charFormat().property(QTextFormat::FontLetterSpacingType).toUInt(),
+ (uint)(QFont::PercentageSpacing));
+ }
+}
+
QTEST_MAIN(tst_QTextDocumentFragment)
#include "tst_qtextdocumentfragment.moc"