summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2018-09-15 00:12:42 +0200
committerAndy Shaw <andy.shaw@qt.io>2018-11-08 16:08:25 +0000
commit97f73e957756753b09a778daf2ee8f0ddb97f746 (patch)
treedb2528cfadd1f3556143ba9d319867c3ce465c0a
parentdb3777dd50210467aac44a152cb4dae8bb16c422 (diff)
Handle fonts that have commas/quotes in the family name
Since the comma character was originally used as a separator, we need to extend QFont to have setFamilies() so that we can avoid joining the family strings together. This enables us to see the family name as a single string and for multiple family names, we have families(). Subsequently, this has added functions to QTextCharFormat to account for multiple font families too. So it is now possible to set a single one directly with setFontFamily() and multiple ones with setFontFamilies(). This also bumps up the datastream version to 19 as QFont now streams the families list as well. [ChangeLog][QtGui][QFont] Add setFamilies()/families() to aid using of font families with commas and quotes in their name. [ChangeLog][Important Behavior Changes] QDataStream version bumped up to 19 to account for changes in the serialization of QFont. Fixes: QTBUG-46322 Change-Id: Iee9f715e47544a7a705c7f36401aba216a7d42b0 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--src/corelib/serialization/qdatastream.cpp2
-rw-r--r--src/corelib/serialization/qdatastream.h2
-rw-r--r--src/gui/text/qcssparser.cpp11
-rw-r--r--src/gui/text/qfont.cpp67
-rw-r--r--src/gui/text/qfont.h6
-rw-r--r--src/gui/text/qfont_p.h4
-rw-r--r--src/gui/text/qfontdatabase.cpp54
-rw-r--r--src/gui/text/qfontengine.cpp2
-rw-r--r--src/gui/text/qtextformat.cpp23
-rw-r--r--src/gui/text/qtextformat.h6
-rw-r--r--src/gui/text/qtexthtmlparser.cpp3
-rw-r--r--tests/auto/gui/text/qfont/qfont.pro1
-rw-r--r--tests/auto/gui/text/qfont/testfont.qrc5
-rw-r--r--tests/auto/gui/text/qfont/tst_qfont.cpp123
-rw-r--r--tests/auto/gui/text/qfont/weirdfont.otfbin0 -> 25008 bytes
-rw-r--r--tests/auto/gui/text/qfontcache/tst_qfontcache.cpp45
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp51
17 files changed, 356 insertions, 49 deletions
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 8566b4fd56..01808ebce6 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -559,7 +559,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_10 Same as Qt_5_6
\value Qt_5_11 Same as Qt_5_6
\value Qt_5_12 Version 18 (Qt 5.12)
- \value Qt_5_13 Same as Qt_5_12
+ \value Qt_5_13 Version 19 (Qt 5.13)
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index ad69621bbe..2c874700e4 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -99,7 +99,7 @@ public:
Qt_5_10 = Qt_5_9,
Qt_5_11 = Qt_5_10,
Qt_5_12 = 18,
- Qt_5_13 = Qt_5_12,
+ Qt_5_13 = 19,
#if QT_VERSION >= 0x050e00
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 8e317d5b97..91fa40eddf 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -1200,11 +1200,13 @@ static bool setFontWeightFromValue(const QCss::Value &value, QFont *font)
static bool setFontFamilyFromValues(const QVector<QCss::Value> &values, QFont *font, int start = 0)
{
QString family;
+ QStringList families;
bool shouldAddSpace = false;
for (int i = start; i < values.count(); ++i) {
const QCss::Value &v = values.at(i);
if (v.type == Value::TermOperatorComma) {
- family += QLatin1Char(',');
+ families << family;
+ family.clear();
shouldAddSpace = false;
continue;
}
@@ -1216,9 +1218,12 @@ static bool setFontFamilyFromValues(const QVector<QCss::Value> &values, QFont *f
family += str;
shouldAddSpace = true;
}
- if (family.isEmpty())
+ if (!family.isEmpty())
+ families << family;
+ if (families.isEmpty())
return false;
- font->setFamily(family);
+ font->setFamily(families.at(0));
+ font->setFamilies(families);
return true;
}
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index a23ef95fde..258a9ba675 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -116,7 +116,17 @@ bool QFontDef::exactMatch(const QFontDef &other) const
if (stretch != 0 && other.stretch != 0 && stretch != other.stretch)
return false;
+ if (families.size() != other.families.size())
+ return false;
+
QString this_family, this_foundry, other_family, other_foundry;
+ for (int i = 0; i < families.size(); ++i) {
+ QFontDatabase::parseFontName(families.at(i), this_foundry, this_family);
+ QFontDatabase::parseFontName(other.families.at(i), other_foundry, other_family);
+ if (this_family != other_family || this_foundry != other_foundry)
+ return false;
+ }
+
QFontDatabase::parseFontName(family, this_foundry, this_family);
QFontDatabase::parseFontName(other.family, other_foundry, other_family);
@@ -261,6 +271,9 @@ void QFontPrivate::resolve(uint mask, const QFontPrivate *other)
if (! (mask & QFont::FamilyResolved))
request.family = other->request.family;
+ if (!(mask & QFont::FamiliesResolved))
+ request.families = other->request.families;
+
if (! (mask & QFont::StyleNameResolved))
request.styleName = other->request.styleName;
@@ -424,7 +437,8 @@ QFontEngineData::~QFontEngineData()
\target fontmatching
The font matching algorithm works as follows:
\list 1
- \li If the specified font family exists and can be used to represent
+ \li The specified font families (set by setFamilies()) are searched for.
+ \li If not found, then if set the specified font family exists and can be used to represent
the writing system in use, it will be selected.
\li If not, a replacement font that supports the writing system is
selected. The font matching algorithm will try to find the
@@ -506,6 +520,7 @@ QFontEngineData::~QFontEngineData()
individually and then considered resolved.
\value FamilyResolved
+ \value FamiliesResolved
\value SizeResolved
\value StyleHintResolved
\value StyleStrategyResolved
@@ -1691,6 +1706,7 @@ bool QFont::operator<(const QFont &f) const
if (r1.stretch != r2.stretch) return r1.stretch < r2.stretch;
if (r1.styleHint != r2.styleHint) return r1.styleHint < r2.styleHint;
if (r1.styleStrategy != r2.styleStrategy) return r1.styleStrategy < r2.styleStrategy;
+ if (r1.families != r2.families) return r1.families < r2.families;
if (r1.family != r2.family) return r1.family < r2.family;
if (f.d->capital != d->capital) return f.d->capital < d->capital;
@@ -2192,6 +2208,48 @@ QString QFont::lastResortFont() const
}
#endif
+/*!
+ \since 5.13
+
+ Returns the requested font family names, i.e. the names set in the last
+ setFamilies() call or via the constructor. Otherwise it returns an
+ empty list.
+
+ \sa setFamily(), setFamilies(), family(), substitutes(), substitute()
+*/
+
+QStringList QFont::families() const
+{
+ return d->request.families;
+}
+
+/*!
+ \since 5.13
+
+ Sets the list of family names for the font. The names are case
+ insensitive and may include a foundry name. The first family in
+ \a families will be set as the main family for the font.
+
+ Each family name entry in \a families may optionally also include a
+ foundry name, e.g. "Helvetica [Cronyx]". If the family is
+ available from more than one foundry and the foundry isn't
+ specified, an arbitrary foundry is chosen. If the family isn't
+ available a family will be set using the \l{QFont}{font matching}
+ algorithm.
+
+ \sa family(), families(), setFamily(), setStyleHint(), QFontInfo
+*/
+
+void QFont::setFamilies(const QStringList &families)
+{
+ if ((resolve_mask & QFont::FamiliesResolved) && d->request.families == families)
+ return;
+ detach();
+ d->request.families = families;
+ resolve_mask |= QFont::FamiliesResolved;
+}
+
+
/*****************************************************************************
QFont stream functions
*****************************************************************************/
@@ -2256,6 +2314,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << (quint8)font.d->request.hintingPreference;
if (s.version() >= QDataStream::Qt_5_6)
s << (quint8)font.d->capital;
+ if (s.version() >= QDataStream::Qt_5_13)
+ s << font.d->request.families;
return s;
}
@@ -2351,6 +2411,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
s >> value;
font.d->capital = QFont::Capitalization(value);
}
+ if (s.version() >= QDataStream::Qt_5_13) {
+ QStringList value;
+ s >> value;
+ font.d->request.families = value;
+ }
return s;
}
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index a94586166e..1fe450e002 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -164,7 +164,8 @@ public:
WordSpacingResolved = 0x4000,
HintingPreferenceResolved = 0x8000,
StyleNameResolved = 0x10000,
- AllPropertiesResolved = 0x1ffff
+ FamiliesResolved = 0x20000,
+ AllPropertiesResolved = 0x3ffff
};
QFont();
@@ -179,6 +180,9 @@ public:
QString family() const;
void setFamily(const QString &);
+ QStringList families() const;
+ void setFamilies(const QStringList &);
+
QString styleName() const;
void setStyleName(const QString &);
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index 350ba7ce3c..09c18de5a6 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -78,6 +78,7 @@ struct QFontDef
}
QString family;
+ QStringList families;
QString styleName;
QStringList fallBackFamilies;
@@ -109,6 +110,7 @@ struct QFontDef
&& styleStrategy == other.styleStrategy
&& ignorePitch == other.ignorePitch && fixedPitch == other.fixedPitch
&& family == other.family
+ && families == other.families
&& styleName == other.styleName
&& hintingPreference == other.hintingPreference
;
@@ -122,6 +124,7 @@ struct QFontDef
if (styleHint != other.styleHint) return styleHint < other.styleHint;
if (styleStrategy != other.styleStrategy) return styleStrategy < other.styleStrategy;
if (family != other.family) return family < other.family;
+ if (families != other.families) return families < other.families;
if (styleName != other.styleName)
return styleName < other.styleName;
if (hintingPreference != other.hintingPreference) return hintingPreference < other.hintingPreference;
@@ -144,6 +147,7 @@ inline uint qHash(const QFontDef &fd, uint seed = 0) Q_DECL_NOTHROW
^ qHash(fd.ignorePitch)
^ qHash(fd.fixedPitch)
^ qHash(fd.family, seed)
+ ^ qHash(fd.families, seed)
^ qHash(fd.styleName)
^ qHash(fd.hintingPreference)
;
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 196eebb353..42e7871214 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -696,20 +696,20 @@ static QStringList familyList(const QFontDef &req)
{
// list of families to try
QStringList family_list;
- if (req.family.isEmpty())
- return family_list;
- const auto list = req.family.splitRef(QLatin1Char(','));
- const int numFamilies = list.size();
- family_list.reserve(numFamilies);
- for (int i = 0; i < numFamilies; ++i) {
- QStringRef str = list.at(i).trimmed();
- if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
- || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
- str = str.mid(1, str.length() - 2);
- family_list << str.toString();
+ family_list << req.families;
+ if (!req.family.isEmpty()) {
+ const auto list = req.family.splitRef(QLatin1Char(','));
+ const int numFamilies = list.size();
+ family_list.reserve(numFamilies);
+ for (int i = 0; i < numFamilies; ++i) {
+ QStringRef str = list.at(i).trimmed();
+ if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
+ || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
+ str = str.mid(1, str.length() - 2);
+ family_list << str.toString();
+ }
}
-
// append the substitute list for each family in family_list
for (int i = 0, size = family_list.size(); i < size; ++i)
family_list += QFont::substitutes(family_list.at(i));
@@ -2688,9 +2688,8 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
}
QString family_name, foundry_name;
-
- parseFontName(request.family, foundry_name, family_name);
-
+ const QString requestFamily = request.families.size() > 0 ? request.families.at(0) : request.family;
+ parseFontName(requestFamily, foundry_name, family_name);
QtFontDesc desc;
QList<int> blackListed;
int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
@@ -2703,8 +2702,8 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
// Don't pass empty family names to the platform font database, since it will then invoke its own matching
// and we will be out of sync with the matched font.
- if (fontDef.family.isEmpty())
- fontDef.family = desc.family->name;
+ if (fontDef.families.isEmpty() && fontDef.family.isEmpty())
+ fontDef.families = QStringList(desc.family->name);
engine = loadEngine(script, fontDef, desc.family, desc.foundry, desc.style, desc.size);
@@ -2717,13 +2716,13 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
}
if (!engine) {
- if (!request.family.isEmpty()) {
+ if (!requestFamily.isEmpty()) {
QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
if (styleHint == QFont::AnyStyle && request.fixedPitch)
styleHint = QFont::TypeWriter;
QStringList fallbacks = request.fallBackFamilies
- + fallbacksForFamily(request.family,
+ + fallbacksForFamily(requestFamily,
QFont::Style(request.style),
styleHint,
QChar::Script(script));
@@ -2741,7 +2740,7 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
index = match(multi ? QChar::Script_Common : script, def, def.family, QLatin1String(""), &desc, blackListed);
if (index >= 0) {
QFontDef loadDef = def;
- if (loadDef.family.isEmpty())
+ if (loadDef.families.isEmpty() && loadDef.family.isEmpty())
loadDef.family = desc.family->name;
engine = loadEngine(script, loadDef, desc.family, desc.foundry, desc.style, desc.size);
if (engine)
@@ -2782,7 +2781,10 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
// look for the requested font in the engine data cache
// note: fallBackFamilies are not respected in the EngineData cache key;
// join them with the primary selection family to avoid cache misses
- req.family = fallBackFamilies.join(QLatin1Char(','));
+ if (!d->request.family.isEmpty())
+ req.family = fallBackFamilies.join(QLatin1Char(','));
+ if (!d->request.families.isEmpty())
+ req.families = fallBackFamilies;
d->engineData = fontCache->findEngineData(req);
if (!d->engineData) {
@@ -2803,14 +2805,14 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
req.fallBackFamilies = fallBackFamilies;
if (!req.fallBackFamilies.isEmpty())
- req.family = req.fallBackFamilies.takeFirst();
+ req.families = QStringList(req.fallBackFamilies.takeFirst());
// list of families to try
QStringList family_list;
- if (!req.family.isEmpty()) {
+ if (!req.families.isEmpty()) {
// Add primary selection
- family_list << req.family;
+ family_list << req.families.at(0);
// add the default family
QString defaultFamily = QGuiApplication::font().family();
@@ -2824,11 +2826,11 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
for (; !fe && it != end; ++it) {
- req.family = *it;
+ req.families = QStringList(*it);
fe = QFontDatabase::findFont(req, script);
if (fe) {
- if (fe->type() == QFontEngine::Box && !req.family.isEmpty()) {
+ if (fe->type() == QFontEngine::Box && !req.families.isEmpty()) {
if (fe->ref.load() == 0)
delete fe;
fe = 0;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 9b0b0ec0d5..b06b64ca63 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1842,7 +1842,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
{
QFontDef request(fontDef);
request.styleStrategy |= QFont::NoFontMerging;
- request.family = fallbackFamilyAt(at - 1);
+ request.families = QStringList(fallbackFamilyAt(at - 1));
// At this point, the main script of the text has already been considered
// when fetching the list of fallback families from the database, and the
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 4957da1908..18de8408b5 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -361,6 +361,9 @@ void QTextFormatPrivate::recalcFont() const
case QTextFormat::FontFamily:
f.setFamily(props.at(i).value.toString());
break;
+ case QTextFormat::FontFamilies:
+ f.setFamilies(props.at(i).value.toStringList());
+ break;
case QTextFormat::FontPointSize:
f.setPointSizeF(props.at(i).value.toReal());
break;
@@ -562,6 +565,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
Character properties
\value FontFamily
+ \value FontFamilies
\value FontPointSize
\value FontPixelSize
\value FontSizeAdjustment Specifies the change in size given to the fontsize already set using
@@ -1390,7 +1394,23 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
\sa font()
*/
+/*!
+ \fn void QTextCharFormat::setFontFamilies(const QStringList &families)
+ \since 5.13
+
+ Sets the text format's font \a families.
+
+ \sa setFont()
+*/
+
+/*!
+ \fn QStringList QTextCharFormat::fontFamilies() const
+ \since 5.13
+
+ Returns the text format's font families.
+ \sa font()
+*/
/*!
\fn void QTextCharFormat::setFontPointSize(qreal size)
@@ -1919,6 +1939,9 @@ void QTextCharFormat::setFont(const QFont &font, FontPropertiesInheritanceBehavi
if (mask & QFont::FamilyResolved)
setFontFamily(font.family());
+ if (mask & QFont::FamiliesResolved)
+ setFontFamilies(font.families());
+
if (mask & QFont::SizeResolved) {
const qreal pointSize = font.pointSizeF();
if (pointSize > 0) {
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index a8e573d5a4..d27d2e7f17 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -188,6 +188,7 @@ public:
FontStyleStrategy = 0x1FE4,
FontKerning = 0x1FE5,
FontHintingPreference = 0x1FE6,
+ FontFamilies = 0x1FE7,
FontFamily = 0x2000,
FontPointSize = 0x2001,
FontSizeAdjustment = 0x2002,
@@ -428,6 +429,11 @@ public:
inline QString fontFamily() const
{ return stringProperty(FontFamily); }
+ inline void setFontFamilies(const QStringList &families)
+ { setProperty(FontFamilies, QVariant(families)); }
+ inline QVariant fontFamilies() const
+ { return property(FontFamilies); }
+
inline void setFontPointSize(qreal size)
{ setProperty(FontPointSize, size); }
inline qreal fontPointSize() const
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 4be800b251..9d2a5d553a 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -862,7 +862,8 @@ QString QTextHtmlParser::parseWord()
++pos;
while (pos < len) {
QChar c = txt.at(pos++);
- if (c == QLatin1Char('\''))
+ // Allow for escaped single quotes as they may be part of the string
+ if (c == QLatin1Char('\'') && (txt.length() > 1 && txt.at(pos - 2) != QLatin1Char('\\')))
break;
else
word += c;
diff --git a/tests/auto/gui/text/qfont/qfont.pro b/tests/auto/gui/text/qfont/qfont.pro
index 048d952faf..96cd4cfdab 100644
--- a/tests/auto/gui/text/qfont/qfont.pro
+++ b/tests/auto/gui/text/qfont/qfont.pro
@@ -4,3 +4,4 @@ QT += testlib
QT += core-private gui-private
qtHaveModule(widgets): QT += widgets
SOURCES += tst_qfont.cpp
+RESOURCES += testfont.qrc
diff --git a/tests/auto/gui/text/qfont/testfont.qrc b/tests/auto/gui/text/qfont/testfont.qrc
new file mode 100644
index 0000000000..cf51e4a2b4
--- /dev/null
+++ b/tests/auto/gui/text/qfont/testfont.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>weirdfont.otf</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp
index 8090f38a2c..9acf877790 100644
--- a/tests/auto/gui/text/qfont/tst_qfont.cpp
+++ b/tests/auto/gui/text/qfont/tst_qfont.cpp
@@ -66,6 +66,12 @@ private slots:
void fromStringWithoutStyleName();
void sharing();
+ void familyNameWithCommaQuote_data();
+ void familyNameWithCommaQuote();
+ void setFamilies_data();
+ void setFamilies();
+ void setFamiliesAndFamily_data();
+ void setFamiliesAndFamily();
};
// Testing get/set functions
@@ -116,6 +122,14 @@ void tst_QFont::exactMatch()
QVERIFY(!QFont("sans-serif").exactMatch());
QVERIFY(!QFont("serif").exactMatch());
QVERIFY(!QFont("monospace").exactMatch());
+
+ font.setFamilies(QStringList() << "BogusFont");
+ QVERIFY(!font.exactMatch());
+ QVERIFY(!QFont("sans").exactMatch());
+ QVERIFY(!QFont("sans-serif").exactMatch());
+ QVERIFY(!QFont("serif").exactMatch());
+ QVERIFY(!QFont("monospace").exactMatch());
+
}
void tst_QFont::italicOblique()
@@ -277,6 +291,12 @@ void tst_QFont::resolve()
QCOMPARE(f4.pointSize(), 45);
f4 = f4.resolve(f3);
QCOMPARE(f4.pointSize(), 55);
+
+ QFont font5, font6;
+ const QStringList fontFamilies = { QStringLiteral("Arial") };
+ font5.setFamilies(fontFamilies);
+ font6 = font6.resolve(font5);
+ QCOMPARE(font6.families(), fontFamilies);
}
#ifndef QT_NO_WIDGETS
@@ -624,5 +644,108 @@ void tst_QFont::sharing()
QVERIFY(QFontPrivate::get(f2)->engineData != QFontPrivate::get(f)->engineData);
}
+void tst_QFont::familyNameWithCommaQuote_data()
+{
+ QTest::addColumn<QString>("familyName");
+ QTest::addColumn<QString>("chosenFamilyName");
+
+ const QString standardFont(QFont().defaultFamily());
+ if (standardFont.isEmpty())
+ QSKIP("No default font available on the system");
+ const QString weirdFont(QLatin1String("'My, weird'' font name',"));
+ const QString commaSeparated(standardFont + QLatin1String(",Times New Roman"));
+ const QString commaSeparatedWeird(weirdFont + QLatin1String(",") + standardFont);
+ const QString commaSeparatedBogus(QLatin1String("BogusFont,") + standardFont);
+
+ QTest::newRow("standard") << standardFont << standardFont;
+ QTest::newRow("weird") << weirdFont << weirdFont;
+ QTest::newRow("commaSeparated") << commaSeparated << standardFont;
+ QTest::newRow("commaSeparatedWeird") << commaSeparatedWeird << weirdFont;
+ QTest::newRow("commaSeparatedBogus") << commaSeparatedBogus << standardFont;
+}
+
+void tst_QFont::familyNameWithCommaQuote()
+{
+ QFETCH(QString, familyName);
+ QFETCH(QString, chosenFamilyName);
+
+ const int weirdFontId = QFontDatabase::addApplicationFont(":/weirdfont.otf");
+
+ QVERIFY(weirdFontId != -1);
+ QFont f(familyName);
+ QCOMPARE(f.family(), familyName);
+ QCOMPARE(QFontInfo(f).family(), chosenFamilyName);
+
+ QFontDatabase::removeApplicationFont(weirdFontId);
+}
+
+void tst_QFont::setFamilies_data()
+{
+ QTest::addColumn<QStringList>("families");
+ QTest::addColumn<QString>("chosenFamilyName");
+
+ const QString weirdFont(QLatin1String("'My, weird'' font name',"));
+ const QString standardFont(QFont().defaultFamily());
+ if (standardFont.isEmpty())
+ QSKIP("No default font available on the system");
+
+ QTest::newRow("standard") << (QStringList() << standardFont) << standardFont;
+ QTest::newRow("weird") << (QStringList() << weirdFont) << weirdFont;
+ QTest::newRow("standard-weird") << (QStringList() << standardFont << weirdFont) << standardFont;
+ QTest::newRow("weird-standard") << (QStringList() << weirdFont << standardFont) << weirdFont;
+ QTest::newRow("nonexist-weird") << (QStringList() << "NonExistentFont" << weirdFont) << weirdFont;
+}
+
+void tst_QFont::setFamilies()
+{
+ QFETCH(QStringList, families);
+ QFETCH(QString, chosenFamilyName);
+
+ const int weirdFontId = QFontDatabase::addApplicationFont(":/weirdfont.otf");
+
+ QVERIFY(weirdFontId != -1);
+ QFont f;
+ f.setFamilies(families);
+ QCOMPARE(QFontInfo(f).family(), chosenFamilyName);
+
+ QFontDatabase::removeApplicationFont(weirdFontId);
+}
+
+void tst_QFont::setFamiliesAndFamily_data()
+{
+ QTest::addColumn<QStringList>("families");
+ QTest::addColumn<QString>("family");
+ QTest::addColumn<QString>("chosenFamilyName");
+
+ const QString weirdFont(QLatin1String("'My, weird'' font name',"));
+ const QString defaultFont(QFont().defaultFamily());
+ if (defaultFont.isEmpty())
+ QSKIP("No default font available on the system");
+
+ const QString timesFont(QLatin1String("Times"));
+ const QString nonExistFont(QLatin1String("NonExistentFont"));
+
+ QTest::newRow("firstInFamilies") << (QStringList() << defaultFont << timesFont) << weirdFont << defaultFont;
+ QTest::newRow("secondInFamilies") << (QStringList() << nonExistFont << weirdFont) << defaultFont << weirdFont;
+ QTest::newRow("family") << (QStringList() << nonExistFont) << defaultFont << defaultFont;
+}
+
+void tst_QFont::setFamiliesAndFamily()
+{
+ QFETCH(QStringList, families);
+ QFETCH(QString, family);
+ QFETCH(QString, chosenFamilyName);
+
+ const int weirdFontId = QFontDatabase::addApplicationFont(":/weirdfont.otf");
+
+ QVERIFY(weirdFontId != -1);
+ QFont f;
+ f.setFamilies(families);
+ f.setFamily(family);
+ QCOMPARE(QFontInfo(f).family(), chosenFamilyName);
+
+ QFontDatabase::removeApplicationFont(weirdFontId);
+}
+
QTEST_MAIN(tst_QFont)
#include "tst_qfont.moc"
diff --git a/tests/auto/gui/text/qfont/weirdfont.otf b/tests/auto/gui/text/qfont/weirdfont.otf
new file mode 100644
index 0000000000..b91c559f5b
--- /dev/null
+++ b/tests/auto/gui/text/qfont/weirdfont.otf
Binary files differ
diff --git a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
index fbca313ea3..785cc3fef2 100644
--- a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
+++ b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
@@ -45,6 +45,8 @@ public:
private slots:
void engineData_data();
void engineData();
+ void engineDataFamilies_data();
+ void engineDataFamilies();
void clear();
};
@@ -109,6 +111,49 @@ void tst_QFontCache::engineData()
QCOMPARE(engineData, QFontPrivate::get(f)->engineData);
}
+void tst_QFontCache::engineDataFamilies_data()
+{
+ QTest::addColumn<QStringList>("families");
+
+ const QStringList multiple = { QLatin1String("invalid"), QLatin1String("Times New Roman") };
+ const QStringList multipleQuotes = { QLatin1String("'invalid'"), QLatin1String("Times New Roman") };
+ const QStringList multiple2 = { QLatin1String("invalid"), QLatin1String("Times New Roman"),
+ QLatin1String("foobar"), QLatin1String("'baz'") };
+
+ QTest::newRow("unquoted-family-name") << QStringList(QLatin1String("Times New Roman"));
+ QTest::newRow("quoted-family-name") << QStringList(QLatin1String("Times New Roman"));
+ QTest::newRow("invalid") << QStringList(QLatin1String("invalid"));
+ QTest::newRow("multiple") << multiple;
+ QTest::newRow("multiple spaces quotes") << multipleQuotes;
+ QTest::newRow("multiple2") << multiple2;
+}
+
+void tst_QFontCache::engineDataFamilies()
+{
+ QFETCH(QStringList, families);
+
+ QFont f;
+ f.setFamily(QString()); // Unset the family as taken from the QGuiApplication default
+ f.setFamilies(families);
+ f.exactMatch(); // loads engine
+ QFontPrivate *d = QFontPrivate::get(f);
+
+ QFontDef req = d->request;
+ // copy-pasted from QFontDatabase::load(), to engineer the cache key
+ if (req.pixelSize == -1) {
+ req.pixelSize = std::floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
+ req.pixelSize = qRound(req.pixelSize);
+ }
+ if (req.pointSize < 0)
+ req.pointSize = req.pixelSize*72.0/d->dpi;
+
+ req.families = families;
+
+ QFontEngineData *engineData = QFontCache::instance()->findEngineData(req);
+
+ QCOMPARE(engineData, QFontPrivate::get(f)->engineData);
+}
+
void tst_QFontCache::clear()
{
#ifdef QT_BUILD_INTERNAL
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index 3e354b7523..08f7cf4fb2 100644
--- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -159,6 +159,7 @@ private slots:
void nonZeroMarginOnImport();
void html_charFormatPropertiesUnset();
void html_headings();
+ void html_quotedFontFamily_data();
void html_quotedFontFamily();
void html_spanBackgroundColor();
void defaultFont();
@@ -2184,23 +2185,45 @@ void tst_QTextDocumentFragment::html_headings()
QCOMPARE(doc->blockCount(), 2);
}
-void tst_QTextDocumentFragment::html_quotedFontFamily()
+void tst_QTextDocumentFragment::html_quotedFontFamily_data()
{
- setHtml("<div style=\"font-family: 'Foo Bar';\">Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
-
- setHtml("<div style='font-family: \"Foo Bar\";'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
-
- setHtml("<div style='font-family: \"Foo Bar\";'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
-
- setHtml("<div style='font-family: Foo\n Bar;'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<QString>("fontFamily");
+ QTest::addColumn<QStringList>("fontFamilies");
+
+ const QString fooFamily = QLatin1String("Foo Bar");
+ const QString weirdFamily = QLatin1String("'Weird, & font '' name',");
+
+ QTest::newRow("data1") << QString("<div style=\"font-family: 'Foo Bar';\">Test</div>")
+ << fooFamily << QStringList(fooFamily);
+ QTest::newRow("data2") << QString("<div style='font-family: \"Foo Bar\";'>Test</div>")
+ << QString("Foo Bar") << QStringList("Foo Bar");
+ QTest::newRow("data3") << QString("<div style='font-family: Foo\n Bar;'>Test</div>")
+ << fooFamily << QStringList(fooFamily);
+ QTest::newRow("data4") << QString("<div style='font-family: Foo\n Bar, serif, \"bar foo\";'>Test"
+ "</div>")
+ << fooFamily << (QStringList() << "Foo Bar" << "serif" << "bar foo");
+ QTest::newRow("data5") << QString("<div style='font-family: \"\\'Weird, & font \\'\\' name\\',"
+ "\";'>Test</div>")
+ << weirdFamily << QStringList(weirdFamily);
+ QTest::newRow("data6") << QString("<div style='font-family: \"\\'Weird, & font \\'\\' name\\',"
+ "\";'>Test</div>")
+ << weirdFamily << QStringList(weirdFamily);
+ QTest::newRow("data7") << QString("<div style='font-family: \"\\'Weird, & font \\'\\' name\\',\", "
+ "serif, \"bar foo\";'>Test</div>")
+ << weirdFamily
+ << (QStringList() << weirdFamily << "serif" << "bar foo");
+}
- setHtml("<div style='font-family: Foo\n Bar, serif, \"bar foo\";'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar,serif,bar foo"));
+void tst_QTextDocumentFragment::html_quotedFontFamily()
+{
+ QFETCH(QString, html);
+ QFETCH(QString, fontFamily);
+ QFETCH(QStringList, fontFamilies);
+ setHtml(html);
+ QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), fontFamily);
+ QCOMPARE(doc->begin().begin().fragment().charFormat().font().families(), fontFamilies);
}
void tst_QTextDocumentFragment::defaultFont()