summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <[email protected]>2025-06-02 12:38:55 +0200
committerEskil Abrahamsen Blomfeldt <[email protected]>2025-06-06 16:27:54 +0200
commitfb89d498a967a53b4347f6db5f9a5426d60d2a01 (patch)
treeca86423ead5aabea73486baedccf02f0567928ec
parent9b9a2398f30b6c35ef6be3ce929c352afb682910 (diff)
Add support for font features and variable axes to QTextCharFormat
These can be set on the font directly, but had not been added to QTextCharFormat, so there would be no way to override them by formatting in a rich text document. Fixes: QTBUG-134060 Change-Id: I4494e24cb9b99d84fb376ba895e2461fc3cd054b Reviewed-by: Eirik Aavitsland <[email protected]>
-rw-r--r--src/corelib/serialization/qdatastream.h2
-rw-r--r--src/gui/text/qtextformat.cpp112
-rw-r--r--src/gui/text/qtextformat.h10
-rw-r--r--tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp1
-rw-r--r--tests/auto/gui/text/qtextformat/tst_qtextformat.cpp152
5 files changed, 267 insertions, 10 deletions
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index ea8ab1f16f0..aed3888b5c6 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -91,7 +91,7 @@ public:
Qt_6_8 = Qt_6_7,
Qt_6_9 = Qt_6_7,
Qt_6_10 = 23,
- Qt_6_11 = Qt_6_10,
+ Qt_6_11 = 24,
Qt_DefaultCompiledVersion = Qt_6_11
#if QT_VERSION >= QT_VERSION_CHECK(6, 12, 0)
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 73b0e769169..06ae00123f0 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -388,6 +388,20 @@ void QTextFormatPrivate::recalcFont() const
case QTextFormat::FontKerning:
f.setKerning(props.at(i).value.toBool());
break;
+ case QTextFormat::FontFeatures:
+ {
+ const auto fontFeatures = props.at(i).value.value<QHash<QFont::Tag, quint32>>();
+ for (auto it = fontFeatures.constBegin(); it != fontFeatures.constEnd(); ++it)
+ f.setFeature(it.key(), it.value());
+ break;
+ }
+ case QTextFormat::FontVariableAxes:
+ {
+ const auto fontVariableAxes = props.at(i).value.value<QHash<QFont::Tag, float>>();
+ for (auto it = fontVariableAxes.constBegin(); it != fontVariableAxes.constEnd(); ++it)
+ f.setVariableAxis(it.key(), it.value());
+ break;
+ }
default:
break;
}
@@ -404,6 +418,16 @@ void QTextFormatPrivate::recalcFont() const
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextFormat &fmt)
{
QMap<int, QVariant> properties = fmt.properties();
+ if (stream.version() < QDataStream::Qt_6_11) {
+ auto it = properties.constFind(QTextFormat::FontFeatures);
+ if (it != properties.cend())
+ properties.erase(it);
+
+ it = properties.constFind(QTextFormat::FontVariableAxes);
+ if (it != properties.cend())
+ properties.erase(it);
+ }
+
if (stream.version() < QDataStream::Qt_6_0) {
auto it = properties.constFind(QTextFormat::FontLetterSpacingType);
if (it != properties.cend()) {
@@ -447,14 +471,17 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
for (QMap<qint32, QVariant>::ConstIterator it = properties.constBegin();
it != properties.constEnd(); ++it) {
qint32 key = it.key();
- if (key == QTextFormat::OldFontLetterSpacingType)
- key = QTextFormat::FontLetterSpacingType;
- else if (key == QTextFormat::OldFontStretch)
- key = QTextFormat::FontStretch;
- else if (key == QTextFormat::OldTextUnderlineColor)
- key = QTextFormat::TextUnderlineColor;
- else if (key == QTextFormat::OldFontFamily)
- key = QTextFormat::FontFamilies;
+
+ if (stream.version() < QDataStream::Qt_6_0) {
+ if (key == QTextFormat::OldFontLetterSpacingType)
+ key = QTextFormat::FontLetterSpacingType;
+ else if (key == QTextFormat::OldFontStretch)
+ key = QTextFormat::FontStretch;
+ else if (key == QTextFormat::OldTextUnderlineColor)
+ key = QTextFormat::TextUnderlineColor;
+ else if (key == QTextFormat::OldFontFamily)
+ key = QTextFormat::FontFamilies;
+ }
fmt.d->insertProperty(key, it.value());
}
@@ -653,6 +680,10 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextTableCellFormat &
\value FontKerning Specifies whether the font has kerning turned on.
\value FontHintingPreference Controls the use of hinting according to values
of the QFont::HintingPreference enum.
+ \value FontFeatures [since 6.11] Assigns integer numbers to typographical features. See
+ \l{QFont::setFeature()} for additional information.
+ \value FontVariableAxes [since 6.11] Assigns floating point numbers to variable axes in variable
+ fonts. See \l{QFont::setVariableAxis()} for additional information.
\omitvalue FirstFontProperty
\omitvalue LastFontProperty
@@ -1810,6 +1841,55 @@ void QTextCharFormat::setUnderlineStyle(UnderlineStyle style)
*/
/*!
+ \since 6.11
+
+ Sets the typographical features of the text format's font to be \a fontFeatures.
+
+ \sa QFont::setFeature()
+*/
+void QTextCharFormat::setFontFeatures(const QHash<QFont::Tag, quint32> &fontFeatures)
+{
+ setProperty(FontFeatures, QVariant::fromValue(fontFeatures));
+}
+
+/*!
+ \since 6.11
+
+ Gets the typographical features of the text format's font.
+
+ \sa setFontFeatures()
+*/
+QHash<QFont::Tag, quint32> QTextCharFormat::fontFeatures() const
+{
+ return property(FontFeatures).value<QHash<QFont::Tag, quint32>>();
+}
+
+/*!
+ \since 6.11
+
+ Sets the variable axes of the text format's font to be \a fontVariableAxes.
+
+ \sa QFont::setVariableAxis()
+*/
+void QTextCharFormat::setFontVariableAxes(const QHash<QFont::Tag, float> &fontVariableAxes)
+{
+ setProperty(FontVariableAxes, QVariant::fromValue(fontVariableAxes));
+}
+
+/*!
+ \since 6.11
+
+ Gets the variable axes of the text format's font.
+
+ \sa setFontVariableAxes()
+*/
+QHash<QFont::Tag, float> QTextCharFormat::fontVariableAxes() const
+{
+ return property(FontVariableAxes).value<QHash<QFont::Tag, float>>();
+}
+
+
+/*!
\fn QPen QTextCharFormat::textOutline() const
Returns the pen used to draw the outlines of characters in this format.
@@ -2145,6 +2225,22 @@ void QTextCharFormat::setFont(const QFont &font, FontPropertiesInheritanceBehavi
setFontHintingPreference(font.hintingPreference());
if (mask & QFont::KerningResolved)
setFontKerning(font.kerning());
+ if (mask & QFont::FeaturesResolved) {
+ const auto tags = font.featureTags();
+
+ QHash<QFont::Tag, quint32> fontFeatures;
+ for (QFont::Tag tag : tags)
+ fontFeatures.insert(tag, font.featureValue(tag));
+ setFontFeatures(fontFeatures);
+ }
+ if (mask & QFont::VariableAxesResolved) {
+ const auto tags = font.variableAxisTags();
+
+ QHash<QFont::Tag, float> fontVariableAxes;
+ for (QFont::Tag tag : tags)
+ fontVariableAxes.insert(tag, font.variableAxisValue(tag));
+ setFontVariableAxes(fontVariableAxes);
+ }
}
/*!
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index 2fa86ed0d1b..d521968ad6c 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -14,6 +14,7 @@
#include <QtCore/qlist.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
@@ -159,7 +160,9 @@ public:
FontStrikeOut = 0x2007,
FontFixedPitch = 0x2008,
FontPixelSize = 0x2009,
- LastFontProperty = FontPixelSize,
+ FontFeatures = 0x2010, // Note: Same as OldTextUnderlineColor
+ FontVariableAxes = 0x2011,
+ LastFontProperty = FontVariableAxes,
TextUnderlineColor = 0x2020,
TextVerticalAlignment = 0x2021,
@@ -518,6 +521,11 @@ public:
return static_cast<QFont::HintingPreference>(intProperty(FontHintingPreference));
}
+ void setFontFeatures(const QHash<QFont::Tag, quint32> &fontFeatures);
+ QHash<QFont::Tag, quint32> fontFeatures() const;
+ void setFontVariableAxes(const QHash<QFont::Tag, float> &fontVariableAxes);
+ QHash<QFont::Tag, float> fontVariableAxes() const;
+
inline void setFontKerning(bool enable)
{ setProperty(FontKerning, enable); }
inline bool fontKerning() const
diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
index 37cc4252247..1abd2939c43 100644
--- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
+++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
@@ -301,6 +301,7 @@ static constexpr int NColorRoles[] = {
QPalette::Accent + 1, // Qt_6_6
QPalette::Accent + 1, // Qt_6_7
QPalette::Accent + 1, // Qt_6_10
+ QPalette::Accent + 1, // Qt_6_11
};
// +1, because we start from "No Version"
diff --git a/tests/auto/gui/text/qtextformat/tst_qtextformat.cpp b/tests/auto/gui/text/qtextformat/tst_qtextformat.cpp
index 6c6145561d8..e71ea6a732c 100644
--- a/tests/auto/gui/text/qtextformat/tst_qtextformat.cpp
+++ b/tests/auto/gui/text/qtextformat/tst_qtextformat.cpp
@@ -45,6 +45,8 @@ private slots:
void setFont_collection_data();
void setFont_collection();
void clearCollection();
+ void setFontFeatures();
+ void setFontVariableAxes();
#ifndef QT_NO_DATASTREAM
void dataStreamCompatibility();
@@ -667,6 +669,89 @@ void tst_QTextFormat::clearCollection()
QCOMPARE(collection.defaultFont(), f); // kept, QTextDocument::clear or setPlainText should not reset the font set by setDefaultFont
}
+void tst_QTextFormat::setFontFeatures()
+{
+ {
+ QFont font;
+ font.setFeature("abcd", 1234);
+ font.setFeature("efgh", 5678);
+
+ QTextCharFormat format;
+ format.setFont(font);
+
+ QFont resolvedFont = format.font();
+ QCOMPARE(resolvedFont.featureTags().size(), 2);
+ QCOMPARE(resolvedFont.featureValue("abcd"), 1234);
+ QCOMPARE(resolvedFont.featureValue("efgh"), 5678);
+
+ QHash<QFont::Tag, quint32> features = format.fontFeatures();
+ QCOMPARE(features.size(), 2);
+ QCOMPARE(features.value("abcd"), 1234);
+ QCOMPARE(features.value("efgh"), 5678);
+ }
+
+ {
+ QTextCharFormat format;
+
+ QHash<QFont::Tag, quint32> features;
+ features.insert("abcd", 4321);
+ features.insert("efgh", 8765);
+ format.setFontFeatures(features);
+
+ QFont resolvedFont = format.font();
+ QCOMPARE(resolvedFont.featureTags().size(), 2);
+ QCOMPARE(resolvedFont.featureValue("abcd"), 4321);
+ QCOMPARE(resolvedFont.featureValue("efgh"), 8765);
+
+ features = format.fontFeatures();
+ QCOMPARE(features.size(), 2);
+ QCOMPARE(features.value("abcd"), 4321);
+ QCOMPARE(features.value("efgh"), 8765);
+ }
+}
+
+void tst_QTextFormat::setFontVariableAxes()
+{
+ {
+ QFont font;
+ font.setVariableAxis("abcd", 12.25);
+ font.setVariableAxis("efgh", 13.25);
+
+ QTextCharFormat format;
+ format.setFont(font);
+
+ QFont resolvedFont = format.font();
+ QCOMPARE(resolvedFont.variableAxisTags().size(), 2);
+ QCOMPARE(resolvedFont.variableAxisValue("abcd"), 12.25);
+ QCOMPARE(resolvedFont.variableAxisValue("efgh"), 13.25);
+
+ QHash<QFont::Tag, float> axes = format.fontVariableAxes();
+ QCOMPARE(axes.size(), 2);
+ QCOMPARE(axes.value("abcd"), 12.25);
+ QCOMPARE(axes.value("efgh"), 13.25);
+ }
+
+ {
+ QTextCharFormat format;
+
+ QHash<QFont::Tag, float> axes;
+ axes.insert("abcd", 12.25);
+ axes.insert("efgh", 13.25);
+ format.setFontVariableAxes(axes);
+
+ QFont resolvedFont = format.font();
+ QCOMPARE(resolvedFont.variableAxisTags().size(), 2);
+ QCOMPARE(resolvedFont.variableAxisValue("abcd"), 12.25);
+ QCOMPARE(resolvedFont.variableAxisValue("efgh"), 13.25);
+
+ axes = format.fontVariableAxes();
+ QCOMPARE(axes.size(), 2);
+ QCOMPARE(axes.value("abcd"), 12.25);
+ QCOMPARE(axes.value("efgh"), 13.25);
+ }
+
+}
+
#ifndef QT_NO_DATASTREAM
void tst_QTextFormat::dataStreamCompatibility()
{
@@ -795,6 +880,73 @@ void tst_QTextFormat::dataStreamCompatibility()
}
}
+ // Don't mix up FontFeatures and OldTextUnderlineColor
+ memory.clear();
+ {
+ {
+ QBuffer buffer(&memory);
+ buffer.open(QIODevice::WriteOnly);
+
+ QFont font;
+ font.setFeature("abcd", 1234);
+
+ QTextCharFormat format;
+ format.setFont(font);
+
+ QDataStream stream(&buffer);
+
+ stream << format;
+ }
+
+ {
+ QBuffer buffer(&memory);
+ buffer.open(QIODevice::ReadOnly);
+
+ QDataStream stream(&buffer);
+
+ QTextFormat other;
+ stream >> other;
+
+ QMap<int, QVariant> properties = other.properties();
+ QVERIFY(properties.contains(QTextFormat::FontFeatures));
+
+ auto features = other.property(QTextFormat::FontFeatures).value<QHash<QFont::Tag, quint32>>();
+ QCOMPARE(features.value("abcd"), 1234);
+ }
+ }
+
+ memory.clear();
+ {
+ {
+ QBuffer buffer(&memory);
+ buffer.open(QIODevice::WriteOnly);
+
+ QFont font;
+ font.setFeature("abcd", 1234);
+
+ QTextCharFormat format;
+ format.setFont(font);
+
+ QDataStream stream(&buffer);
+ stream.setVersion(QDataStream::Qt_5_15);
+
+ stream << format;
+ }
+
+ {
+ QBuffer buffer(&memory);
+ buffer.open(QIODevice::ReadOnly);
+
+ QDataStream stream(&buffer);
+ stream.setVersion(QDataStream::Qt_5_15);
+
+ QTextFormat other;
+ stream >> other;
+ QMap<int, QVariant> properties = other.properties();
+ QVERIFY(!properties.contains(QTextFormat::FontFeatures));
+ QVERIFY(!properties.contains(QTextFormat::OldTextUnderlineColor));
+ }
+ }
}
#endif // QT_NO_DATASTREAM