From bcd2fa484a4fe93e77743195d7f72cce9e580d43 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 2 Apr 2019 15:33:16 +0200 Subject: [PATCH] Fix font matching of typographic families on Windows 9204b8c31ea1b5f0c05870c5b5d74c33b1a4f622 broke font matching on Windows. After this change, if you request a specific face of a family, such as "Arial Black", and Qt detects that its typographic/preferred name is "Arial", then it will be added as the single style of the Arial family, which will in turn be set as populated=true. So if you later request a regular font of "Arial" family, then it will see that the family has already been populated, skip this step, and then see that there is only one style available, i.e. "Arial Black". To work around this, we need to make sure the typographic family is properly populated the first time it is registered. [ChangeLog][Windows][Fonts] Fixed a bug where it would be impossible to request different faces of a font family after a specific type face has been in use. Task-number: QTBUG-74748 Change-Id: Ia0caace2b88a32e6114ff23ad10ee1ea8f5a3e03 Reviewed-by: Allan Sandfeld Jensen --- src/gui/text/qfontdatabase.cpp | 7 +++++++ src/gui/text/qplatformfontdatabase.cpp | 11 +++++++++++ src/gui/text/qplatformfontdatabase.h | 2 ++ .../windows/qwindowsfontdatabase.cpp | 17 ++++++++++++----- .../windows/qwindowsfontdatabase_p.h | 2 ++ 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index fa9573441a..a307539800 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -804,6 +804,13 @@ QString qt_resolveFontFamilyAlias(const QString &alias) return alias; } +bool qt_isFontFamilyPopulated(const QString &familyName) +{ + QFontDatabasePrivate *d = privateDb(); + QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily); + return f != nullptr && f->populated; +} + /*! Returns a list of alternative fonts for the specified \a family and \a style and \a script using the \a styleHint given. diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index a911014a19..715b00d838 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -60,6 +60,7 @@ void qt_registerFont(const QString &familyname, const QString &stylename, void qt_registerFontFamily(const QString &familyName); void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias); +bool qt_isFontFamilyPopulated(const QString &familyName); /*! Registers the pre-rendered QPF2 font contained in the given \a dataArray. @@ -665,6 +666,16 @@ void QPlatformFontDatabase::registerAliasToFontFamily(const QString &familyName, qt_registerAliasToFontFamily(familyName, alias); } +/*! + Helper function that returns true if the font family has already been registered and populated. + + \since 5.14 +*/ +bool QPlatformFontDatabase::isFamilyPopulated(const QString &familyName) +{ + return qt_isFontFamilyPopulated(familyName); +} + /*! \class QPlatformFontDatabase \since 5.0 diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index f4558129a7..38ba7f10b2 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -139,6 +139,8 @@ public: static void registerFontFamily(const QString &familyName); static void registerAliasToFontFamily(const QString &familyName, const QString &alias); + + static bool isFamilyPopulated(const QString &familyName); }; QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index 10df85f68e..ff0efaac1a 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -1012,7 +1012,8 @@ static bool addFontToDatabase(QString familyName, const LOGFONT &logFont, const TEXTMETRIC *textmetric, const FONTSIGNATURE *signature, - int type) + int type, + QWindowsFontDatabase *db) { // the "@family" fonts are just the same as "family". Ignore them. if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_"))) @@ -1092,6 +1093,12 @@ static bool addFontToDatabase(QString familyName, writingSystems.setSupported(ws); } + // We came here from populating a different font family, so we have + // to ensure the entire typographic family is populated before we + // mark it as such inside registerFont() + if (!subFamilyName.isEmpty() && familyName != subFamilyName && !QPlatformFontDatabase::isFamilyPopulated(familyName)) + db->populateFamily(familyName); + QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName)); @@ -1118,7 +1125,7 @@ static bool addFontToDatabase(QString familyName, } static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric, - DWORD type, LPARAM) + DWORD type, LPARAM lParam) { const ENUMLOGFONTEX *f = reinterpret_cast(logFont); const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName); @@ -1130,7 +1137,7 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t const FONTSIGNATURE *signature = nullptr; if (type & TRUETYPE_FONTTYPE) signature = &reinterpret_cast(textmetric)->ntmFontSig; - addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type); + addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type, reinterpret_cast(lParam)); // keep on enumerating return 1; @@ -1149,7 +1156,7 @@ void QWindowsFontDatabase::populateFamily(const QString &familyName) familyName.toWCharArray(lf.lfFaceName); lf.lfFaceName[familyName.size()] = 0; lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, storeFont, 0, 0); + EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast(this), 0); ReleaseDC(0, dummy); } @@ -1590,7 +1597,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, GetTextMetrics(hdc, &textMetrics); addFontToDatabase(familyName, styleName, lf, &textMetrics, &signatures.at(j), - TRUETYPE_FONTTYPE); + TRUETYPE_FONTTYPE, this); SelectObject(hdc, oldobj); DeleteObject(hfont); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h index b85a2dceee..a1cab17a87 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h @@ -96,6 +96,8 @@ public: QWindowsFontDatabase(); ~QWindowsFontDatabase() override; + void ensureFamilyPopulated(const QString &familyName); + void populateFontDatabase() override; void populateFamily(const QString &familyName) override; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;