summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-10-09 20:55:47 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-10-20 21:36:52 +0200
commitbde443801fe9dfda6c84ead939be7a1fa1ff72f3 (patch)
tree9d908662950e724a6d9a006bad6c83d2025cd863
parentfa8943640c02adbe100cdbca2b44a102b45de53f (diff)
QFont: add a tag type for features and other advanced properties
Instead of overloads and generic string literals with runtime checks, use a dedicated Tag type for specifying the font feature. The Tag type can only be instantiated with a string literal of exactly 4 characters (plus the terminating null)l; longer or shorter literals result in a compile time error. Constructing a Tag from any other string type is possible through the named fromString constructor, in which case we can only check the length and warn at runtime. The type's API is almost completely constexpr so that we can use it to calculate e.g. enum values. Task-number: QTBUG-117046 Change-Id: I31038c7c6fd2b843a105b032f021e506b0b60822 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r--src/gui/text/qfont.cpp261
-rw-r--r--src/gui/text/qfont.h70
-rw-r--r--src/gui/text/qfont_p.h6
-rw-r--r--src/gui/text/qtextengine.cpp18
-rw-r--r--src/gui/text/qtextengine_p.h2
-rw-r--r--tests/auto/gui/text/qfont/tst_qfont.cpp41
6 files changed, 296 insertions, 102 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 73944dfdcb..d144a8d79a 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -348,12 +348,12 @@ void QFontPrivate::resolve(uint mask, const QFontPrivate *other)
features = other->features;
}
-void QFontPrivate::setFeature(quint32 tag, quint32 value)
+void QFontPrivate::setFeature(QFont::Tag tag, quint32 value)
{
features.insert(tag, value);
}
-void QFontPrivate::unsetFeature(quint32 tag)
+void QFontPrivate::unsetFeature(QFont::Tag tag)
{
features.remove(tag);
}
@@ -2231,20 +2231,153 @@ void QFont::cacheStatistics()
}
/*!
+ \class QFont::Tag
+ \brief The QFont::Tag type provides access to advanced font features.
+ \since 6.7
+ \inmodule QtGui
+
+ QFont provides access to advanced features when shaping text. A feature is defined
+ by a tag, which can be represented as a four-character string, or as a 32bit integer
+ value. This type represents such a tag in a type-safe way. It can be constructed from
+ a four-character, 8bit string literal, or from a corresponding 32bit integer value.
+ Using a shorter or longer string literal will result in a compile-time error.
+
+ \code
+ QFont font;
+ // Correct
+ font.setFeature("frac");
+
+ // Wrong - won't compile
+ font.setFeature("fraction");
+
+ // Wrong - will produce runtime warning and fail
+ font.setFeature(u"fraction"_s);
+ \endcode
+
+ The named constructors allow to create a tag from an 32bit integer or string value,
+ and will return a \c std::nullopt when the input is invalid.
+
+ \sa QFont::setFeature(), QFont::featureTags()
+*/
+
+/*!
+ \fn QFont::Tag::Tag()
+
+ Default constructor, producing an invalid tag.
+*/
+
+/*!
+ \fn template <size_t N> QFont::Tag::Tag(const char (&str)[N]) noexcept
+
+ Constructs a tag from a string literal, \a str. The literal must be exactly four
+ characters long.
+
+ \code
+ font.setFeature("frac", 1);
+ \endcode
+
+ \sa fromString(), fromValue()
+*/
+
+/*!
+ \fn bool QFont::Tag::operator==(QFont::Tag::Tag lhs, QFont::Tag::Tag rhs) noexcept
+ \fn bool QFont::Tag::operator!=(QFont::Tag::Tag lhs, QFont::Tag::Tag rhs) noexcept
+ \fn bool QFont::Tag::operator<(QFont::Tag::Tag lhs, QFont::Tag::Tag rhs) noexcept
+
+ Compare \a lhs with \a rhs for equality and ordering.
+*/
+
+/*!
+ \fn size_t QFont::Tag::qHash(QFont::Tag key, size_t seed) noexcept
+
+ Returns the hash value for \a key, using \a seed to seed the calculation.
+*/
+
+/*!
+ \fn quint32 QFont::Tag::value() const noexcept
+
+ Returns the numerical value of this tag.
+
+ \sa isValid(), fromValue()
+*/
+
+/*!
+ \fn bool QFont::Tag::isValid() const noexcept
+
+ Returns whether the tag is valid. A tag is valid if its value is not zero.
+
+ \sa value(), fromValue(), fromString()
+*/
+
+/*!
+ \fn QByteArray QFont::Tag::toString() const noexcept
+
+ Returns the string representation of this tag as a byte array.
+
+ \sa fromString()
+*/
+
+/*!
+ \fn std::optional<QFont::Tag> QFont::Tag::fromValue(quint32 value) noexcept
+
+ Returns a tag constructed from \a value, or \c std::nullopt if the tag produced
+ would be invalid.
+
+ \sa isValid()
+*/
+
+/*!
+ Returns a tag constructed from the string in \a view. The string must be exactly
+ four characters long.
+
+ Returns \c std::nullopt if the input is not four characters long, or if the tag
+ produced would be invalid.
+
+ \sa isValid(), fromValue()
+*/
+std::optional<QFont::Tag> QFont::Tag::fromString(QAnyStringView view) noexcept
+{
+ if (view.size() != 4) {
+ qWarning("The tag name must be exactly 4 characters long!");
+ return std::nullopt;
+ }
+ const QFont::Tag maybeTag = view.visit([](auto view) {
+ using CharType = decltype(view.at(0));
+ if constexpr (std::is_same_v<CharType, char>) {
+ const char bytes[5] = { view.at(0), view.at(1), view.at(2), view.at(3), 0 };
+ return Tag(bytes);
+ } else {
+ const char bytes[5] = { view.at(0).toLatin1(), view.at(1).toLatin1(),
+ view.at(2).toLatin1(), view.at(3).toLatin1(), 0 };
+ return Tag(bytes);
+ }
+ });
+ return maybeTag.isValid() ? std::optional<Tag>(maybeTag) : std::nullopt;
+}
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &, QFont::Tag)
+ \fn QDataStream &operator>>(QDataStream &, QFont::Tag &)
+ \relates QFont::Tag
+
+ Data stream operators for QFont::Tag.
+*/
+
+/*!
\since 6.6
\overload
\preliminary
- Applies an integer value to a specific typographical feature when shaping the text. This
- provides advanced access to the font shaping process, and can be used to support font features
- that are otherwise not covered in the API.
+ Applies an integer value to the typographical feature specified by \a tag when shaping the
+ text. This provides advanced access to the font shaping process, and can be used to support
+ font features that are otherwise not covered in the API.
- A feature is defined by a 32-bit \a tag (encoded from the four-character name of the table by
- using the stringToTag() function), as well as an integer value.
+ The feature is specified by a \l{QFont::Tag}{tag}, which is typically encoded from the
+ four-character feature name in the font feature map.
This integer \a value passed along with the tag in most cases represents a boolean value: A zero
value means the feature is disabled, and a non-zero value means it is enabled. For certain
- font features, however, it may have other intepretations. For example, when applied to the
+ font features, however, it may have other interpretations. For example, when applied to the
\c salt feature, the value is an index that specifies the stylistic alternative to use.
For example, the \c frac font feature will convert diagonal fractions separated with a slash
@@ -2252,7 +2385,7 @@ void QFont::cacheStatistics()
fraction into a single character width (such as \c ½).
If a font supports the \c frac feature, then it can be enabled in the shaper by setting
- \c{features[stringToTag("frac")] = 1} in the font feature map.
+ \c{features["frac"] = 1} in the font feature map.
\note By default, Qt will enable and disable certain font features based on other font
properties. In particular, the \c kern feature will be enabled/disabled depending on the
@@ -2265,11 +2398,11 @@ void QFont::cacheStatistics()
kerning property is set to false. Similarly, if it is set to 0, then it will always be disabled.
To reset a font feature to its default behavior, you can unset it using unsetFeature().
- \sa clearFeatures(), setFeature(), unsetFeature(), featureTags(), stringToTag()
+ \sa QFont::Tag, clearFeatures(), setFeature(), unsetFeature(), featureTags()
*/
-void QFont::setFeature(quint32 tag, quint32 value)
+void QFont::setFeature(Tag tag, quint32 value)
{
- if (tag != 0) {
+ if (tag.isValid()) {
d->detachButKeepEngineData(this);
d->setFeature(tag, value);
resolve_mask |= QFont::FeaturesResolved;
@@ -2281,25 +2414,6 @@ void QFont::setFeature(quint32 tag, quint32 value)
\overload
\preliminary
- Sets the \a value of a specific \a feature. This is an advanced feature which can be used to
- enable or disable specific OpenType features if they are available in the font.
-
- See \l setFeature(quint32, quint32) for more details on font features.
-
- \note This is equivalent to calling setFeature(stringToTag(feature), value).
-
- \sa clearFeatures(), unsetFeature(), featureTags(), featureValue(), stringToTag()
-*/
-void QFont::setFeature(const char *feature, quint32 value)
-{
- setFeature(stringToTag(feature), value);
-}
-
-/*!
- \since 6.6
- \overload
- \preliminary
-
Unsets the \a tag from the map of explicitly enabled/disabled features.
\note Even if the feature has not previously been added, this will mark the font features map
@@ -2307,13 +2421,13 @@ void QFont::setFeature(const char *feature, quint32 value)
Unsetting an existing feature on the QFont reverts behavior to the default.
- See \l setFeature(quint32, quint32) for more details on font features.
+ See \l setFeature() for more details on font features.
- \sa clearFeatures(), setFeature(), featureTags(), featureValue(), stringToTag()
+ \sa QFont::Tag, clearFeatures(), setFeature(), featureTags(), featureValue()
*/
-void QFont::unsetFeature(quint32 tag)
+void QFont::unsetFeature(Tag tag)
{
- if (tag != 0) {
+ if (tag.isValid()) {
d->detachButKeepEngineData(this);
d->unsetFeature(tag);
resolve_mask |= QFont::FeaturesResolved;
@@ -2321,39 +2435,16 @@ void QFont::unsetFeature(quint32 tag)
}
/*!
- \since 6.6
- \overload
- \preliminary
-
- Unsets the \a feature from the map of explicitly enabled/disabled features.
-
- \note Even if the feature has not previously been added, this will mark the font features map
- as modified in this QFont, so that it will take precedence when resolving against other fonts.
-
- Unsetting an existing feature on the QFont reverts behavior to the default.
-
- See \l setFeature(quint32, quint32) for more details on font features.
-
- \note This is equivalent to calling unsetFeature(stringToTag(feature)).
-
- \sa clearFeatures(), setFeature(), featureTags(), featureValue(), stringToTag()
-*/
-void QFont::unsetFeature(const char *feature)
-{
- unsetFeature(stringToTag(feature));
-}
-
-/*!
\since 6.6
\preliminary
Returns a list of tags for all font features currently set on this QFont.
- See \l setFeature(quint32, quint32) for more details on font features.
+ See \l{QFont::}{setFeature()} for more details on font features.
- \sa setFeature(), unsetFeature(), isFeatureSet(), clearFeatures(), tagToString()
+ \sa QFont::Tag, setFeature(), unsetFeature(), isFeatureSet(), clearFeatures()
*/
-QList<quint32> QFont::featureTags() const
+QList<QFont::Tag> QFont::featureTags() const
{
return d->features.keys();
}
@@ -2365,11 +2456,11 @@ QList<quint32> QFont::featureTags() const
Returns the value set for a specific feature \a tag. If the tag has not been set, 0 will be
returned instead.
- See \l setFeature(quint32, quint32) for more details on font features.
+ See \l{QFont::}{setFeature()} for more details on font features.
- \sa setFeature(), unsetFeature(), featureTags(), isFeatureSet(), stringToTag()
+ \sa QFont::Tag, setFeature(), unsetFeature(), featureTags(), isFeatureSet()
*/
-quint32 QFont::featureValue(quint32 tag) const
+quint32 QFont::featureValue(Tag tag) const
{
return d->features.value(tag);
}
@@ -2381,11 +2472,11 @@ quint32 QFont::featureValue(quint32 tag) const
Returns true if a value for the feature given by \a tag has been set on the QFont, otherwise
returns false.
- See \l setFeature(quint32, quint32) for more details on font features.
+ See \l{QFont::}{setFeature()} for more details on font features.
- \sa setFeature(), unsetFeature(), featureTags(), featureValue(), stringToTag()
+ \sa QFont::Tag, setFeature(), unsetFeature(), featureTags(), featureValue()
*/
-bool QFont::isFeatureSet(quint32 tag) const
+bool QFont::isFeatureSet(Tag tag) const
{
return d->features.contains(tag);
}
@@ -2396,9 +2487,9 @@ bool QFont::isFeatureSet(quint32 tag) const
Clears any previously set features on the QFont.
- See \l setFeature(quint32, quint32) for more details on font features.
+ See \l{QFont::}{setFeature()} for more details on font features.
- \sa setFeature(), unsetFeature(), featureTags(), featureValue()
+ \sa QFont::Tag, setFeature(), unsetFeature(), featureTags(), featureValue()
*/
void QFont::clearFeatures()
{
@@ -2407,13 +2498,13 @@ void QFont::clearFeatures()
/*!
\since 6.6
- \preliminary
+ \internal
Returns the decoded name for \a tag as defined in the OpenType font specification. The tag
is decoded into four 8 bit characters. For valid tags, each will be in the basic Latin range of
0x20 to 0x7E.
- \sa setFeature(), unsetFeature(), featureTags(), featureValue(), stringToTag()
+ \sa setFeature(), unsetFeature(), featureTags(), featureValue()
*/
QByteArray QFont::tagToString(quint32 tag)
{
@@ -2427,7 +2518,7 @@ QByteArray QFont::tagToString(quint32 tag)
/*!
\since 6.6
- \preliminary
+ \internal
Returns the encoded tag for \a name as defined in the OpenType font specification. The name
must be a null-terminated string of four characters exactly, and in order to be a valid tag,
@@ -2436,7 +2527,7 @@ QByteArray QFont::tagToString(quint32 tag)
The function returns 0 for strings of the wrong length, but does not otherwise check the input
for validity.
- \sa setFeature(), unsetFeature(), featureTags(), featureValue(), tagToString()
+ \sa setFeature(), unsetFeature(), featureTags(), featureValue()
*/
quint32 QFont::stringToTag(const char *name)
{
@@ -2706,6 +2797,23 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
return s;
}
+QDataStream &operator<<(QDataStream &stream, QFont::Tag tag)
+{
+ stream << tag.value();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QFont::Tag &tag)
+{
+ quint32 value;
+ stream >> value;
+ if (const auto maybeTag = QFont::Tag::fromValue(value))
+ tag = *maybeTag;
+ else
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+
#endif // QT_NO_DATASTREAM
@@ -3551,6 +3659,13 @@ QDebug operator<<(QDebug stream, const QFont &font)
return stream;
}
+
+QDebug operator<<(QDebug debug, QFont::Tag tag)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote() << tag.toString();
+ return debug;
+}
#endif
QT_END_NAMESPACE
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index e84fbe20df..bb6e07ba51 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -4,6 +4,7 @@
#ifndef QFONT_H
#define QFONT_H
+#include <QtCore/qendian.h>
#include <QtCore/qshareddata.h>
#include <QtGui/qtguiglobal.h>
#include <QtGui/qwindowdefs.h>
@@ -208,13 +209,68 @@ public:
HintingPreference hintingPreference() const;
// Note: The following set of APIs are preliminary and may change in future releases
- void setFeature(const char *feature, quint32 value);
- void setFeature(quint32 tag, quint32 value);
- void unsetFeature(quint32 tag);
- void unsetFeature(const char *feature);
- quint32 featureValue(quint32 tag) const;
- bool isFeatureSet(quint32 tag) const;
- QList<quint32> featureTags() const;
+
+ struct Tag
+ {
+ constexpr Tag() = default;
+
+ template <size_t N>
+ constexpr Q_IMPLICIT Tag(const char (&str)[N]) noexcept
+ : m_value((quint32(str[0]) << 24) | (quint32(str[1]) << 16)
+ | (quint32(str[2]) << 8) | quint32(str[3]))
+ {
+ static_assert(N == 5, "The tag name must be exactly 4 characters long!");
+ }
+
+ friend inline bool operator==(Tag lhs, Tag rhs) noexcept
+ { return lhs.m_value == rhs.m_value; }
+ friend inline bool operator!=(Tag lhs, Tag rhs) noexcept
+ { return lhs.m_value != rhs.m_value; }
+ friend inline bool operator<(Tag lhs, Tag rhs) noexcept
+ { return lhs.m_value < rhs.m_value; }
+ constexpr bool isValid() const noexcept { return m_value != 0; }
+ constexpr quint32 value() const noexcept { return m_value; }
+
+ QByteArray toString() const
+ {
+ const char data[] = {
+ char((m_value & 0xff000000) >> 24),
+ char((m_value & 0x00ff0000) >> 16),
+ char((m_value & 0x0000ff00) >> 8),
+ char((m_value & 0x000000ff)),
+ 0 };
+ return QByteArray(data);
+ }
+
+ static constexpr std::optional<Tag> fromValue(quint32 value) noexcept
+ {
+ Tag maybeTag;
+ maybeTag.m_value = value;
+ return maybeTag.isValid() ? std::optional<Tag>(maybeTag) : std::nullopt;
+ }
+ Q_GUI_EXPORT static std::optional<Tag> fromString(QAnyStringView view) noexcept;
+
+#ifndef QT_NO_DATASTREAM
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, Tag);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, Tag &);
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug debug, Tag tag);
+#endif
+
+ friend constexpr size_t qHash(Tag key, size_t seed = 0) noexcept
+ { return qHash(key.value(), seed); }
+
+ private:
+ quint32 m_value = 0;
+ };
+
+ void setFeature(Tag tag, quint32 value);
+ void unsetFeature(Tag tag);
+ quint32 featureValue(Tag tag) const;
+ bool isFeatureSet(Tag tag) const;
+ QList<Tag> featureTags() const;
void clearFeatures();
static QByteArray tagToString(quint32 tag);
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index 3596322fae..18093de49c 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -164,7 +164,7 @@ public:
QFixed letterSpacing;
QFixed wordSpacing;
- QHash<quint32, quint32> features;
+ QHash<QFont::Tag, quint32> features;
mutable QFontPrivate *scFont;
QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); }
@@ -179,8 +179,8 @@ public:
static void detachButKeepEngineData(QFont *font);
- void setFeature(quint32 tag, quint32 value);
- void unsetFeature(quint32 tag);
+ void setFeature(QFont::Tag tag, quint32 value);
+ void unsetFeature(QFont::Tag tag);
private:
QFontPrivate &operator=(const QFontPrivate &) { return *this; }
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index a1c6bd2754..3ca932d34f 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1399,7 +1399,7 @@ void QTextEngine::shapeText(int item) const
bool kerningEnabled;
bool letterSpacingIsAbsolute;
bool shapingEnabled = false;
- QHash<quint32, quint32> features;
+ QHash<QFont::Tag, quint32> features;
QFixed letterSpacing, wordSpacing;
#ifndef QT_NO_RAWFONT
if (useRawFont) {
@@ -1600,7 +1600,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
const QList<uint> &itemBoundaries,
bool kerningEnabled,
bool hasLetterSpacing,
- const QHash<quint32, quint32> &fontFeatures) const
+ const QHash<QFont::Tag, quint32> &fontFeatures) const
{
uint glyphs_shaped = 0;
@@ -1655,19 +1655,19 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
bool dontLigate = hasLetterSpacing && !scriptRequiresOpenType;
- QHash<quint32, quint32> features;
- features.insert(HB_TAG('k','e','r','n'), !!kerningEnabled);
+ QHash<QFont::Tag, quint32> features;
+ features.insert(QFont::Tag("kern"), !!kerningEnabled);
if (dontLigate) {
- features.insert(HB_TAG('l','i','g','a'), false);
- features.insert(HB_TAG('c','l','i','g'), false);
- features.insert(HB_TAG('d','l','i','g'), false);
- features.insert(HB_TAG('h','l','i','g'), false);
+ features.insert(QFont::Tag("liga"), false);
+ features.insert(QFont::Tag("clig"), false);
+ features.insert(QFont::Tag("dlig"), false);
+ features.insert(QFont::Tag("hlig"), false);
}
features.insert(fontFeatures);
QVarLengthArray<hb_feature_t, 16> featureArray;
for (auto it = features.constBegin(); it != features.constEnd(); ++it) {
- featureArray.append({ it.key(),
+ featureArray.append({ it.key().value(),
it.value(),
HB_FEATURE_GLOBAL_START,
HB_FEATURE_GLOBAL_END });
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 6cacd6b556..f2bfaee5a9 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -628,7 +628,7 @@ private:
const QList<uint> &itemBoundaries,
bool kerningEnabled,
bool hasLetterSpacing,
- const QHash<quint32, quint32> &features) const;
+ const QHash<QFont::Tag, quint32> &features) const;
#endif
int endOfLine(int lineNum);
diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp
index 2438756bf0..bbcbf11d09 100644
--- a/tests/auto/gui/text/qfont/tst_qfont.cpp
+++ b/tests/auto/gui/text/qfont/tst_qfont.cpp
@@ -22,6 +22,8 @@
#include <qlist.h>
#include <QtTest/private/qemulationdetector_p.h>
+using namespace Qt::StringLiterals;
+
class tst_QFont : public QObject
{
Q_OBJECT
@@ -846,34 +848,55 @@ void tst_QFont::setFamiliesAndFamily()
void tst_QFont::featureAccessors()
{
+ const QFont::Tag abcdTag("abcd");
+ QCOMPARE(abcdTag.toString(), "abcd");
+ QVERIFY(abcdTag.isValid());
+
QFont font;
QVERIFY(font.featureTags().isEmpty());
font.setFeature("abcd", 0xc0ffee);
- quint32 abcdTag = QFont::stringToTag("abcd");
- quint32 bcdeTag = QFont::stringToTag("bcde");
QVERIFY(font.isFeatureSet(abcdTag));
- QVERIFY(!font.isFeatureSet(bcdeTag));
+ QVERIFY(!font.isFeatureSet("bcde"));
QCOMPARE(font.featureTags().size(), 1);
QCOMPARE(font.featureTags().first(), abcdTag);
- QCOMPARE(QFont::tagToString(font.featureTags().first()), QByteArray("abcd"));
+ QCOMPARE(font.featureTags().first(), "abcd");
QCOMPARE(font.featureValue(abcdTag), 0xc0ffeeU);
- QCOMPARE(font.featureValue(bcdeTag), 0U);
+ QCOMPARE(font.featureValue("bcde"), 0U);
font.setFeature(abcdTag, 0xf00d);
QCOMPARE(font.featureTags().size(), 1);
QCOMPARE(font.featureValue(abcdTag), 0xf00dU);
- font.setFeature("abcde", 0xcaca0);
- QVERIFY(!font.isFeatureSet(QFont::stringToTag("abcde")));
+
+ QFont::Tag invalidTag;
+ QVERIFY(!invalidTag.isValid());
+ font.setFeature(invalidTag, 0xcaca0);
+ QVERIFY(!font.isFeatureSet(invalidTag));
QCOMPARE(font.featureTags().size(), 1);
QFont font2 = font;
font.unsetFeature("abcd");
- QVERIFY(!font.isFeatureSet(QFont::stringToTag("abcd")));
+ QVERIFY(!font.isFeatureSet("abcd"));
QVERIFY(font.featureTags().isEmpty());
- QVERIFY(font2.isFeatureSet(QFont::stringToTag("abcd")));
+ QVERIFY(font2.isFeatureSet("abcd"));
font2.clearFeatures();
QVERIFY(font.featureTags().isEmpty());
+
+ // various constructor compile tests
+ QFont::Tag tag;
+ tag = QFont::Tag("1234");
+ QVERIFY(QFont::Tag::fromString(QByteArray("abcd")));
+ QVERIFY(QFont::Tag::fromString(u"frac"_s));
+
+ // named constructors with invalid input
+ QTest::ignoreMessage(QtWarningMsg, "The tag name must be exactly 4 characters long!");
+ QVERIFY(!QFont::Tag::fromString(u"fraction"_s));
+ QVERIFY(!QFont::Tag::fromValue(0));
+ QVERIFY(QFont::Tag::fromValue(abcdTag.value()));
+
+ enum Features {
+ Frac = QFont::Tag("frac").value()
+ };
}
QTEST_MAIN(tst_QFont)