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>
bb10
Andy Shaw 2018-09-15 00:12:42 +02:00
parent db3777dd50
commit 97f73e9577
17 changed files with 356 additions and 49 deletions

View File

@ -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()

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 &);

View File

@ -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)
;

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -4,3 +4,4 @@ QT += testlib
QT += core-private gui-private
qtHaveModule(widgets): QT += widgets
SOURCES += tst_qfont.cpp
RESOURCES += testfont.qrc

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>weirdfont.otf</file>
</qresource>
</RCC>

View File

@ -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"

Binary file not shown.

View File

@ -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

View File

@ -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_data()
{
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");
}
void tst_QTextDocumentFragment::html_quotedFontFamily()
{
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"));
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"));
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()