diff options
-rw-r--r-- | src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp | 369 | ||||
-rw-r--r-- | src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h | 6 |
2 files changed, 164 insertions, 211 deletions
diff --git a/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp b/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp index 25bb1863298..594fc18f9c6 100644 --- a/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp +++ b/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp @@ -357,6 +357,79 @@ QStringList QWindowsDirectWriteFontDatabase::fallbacksForFamily(const QString &f return result; } +template<typename T> +void QWindowsDirectWriteFontDatabase::collectAdditionalNames(T *font, + wchar_t *defaultLocale, + wchar_t *englishLocale, + std::function<void(const std::pair<QString, QString> &)> registerFamily) +{ + BOOL ok; + QString defaultLocaleGdiCompatibleFamilyName; + QString englishLocaleGdiCompatibleFamilyName; + + const bool hasDefaultLocale = defaultLocale != nullptr; + Q_ASSERT(englishLocale != nullptr); + + IDWriteLocalizedStrings *names = nullptr; + if (SUCCEEDED(font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &names, &ok)) && ok) { + defaultLocaleGdiCompatibleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleGdiCompatibleFamilyName = localeString(names, englishLocale); + + names->Release(); + } + + QString defaultLocaleGdiCompatibleStyleName; + QString englishLocaleGdiCompatibleStyleName; + if (SUCCEEDED(font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, &names, &ok)) && ok) { + defaultLocaleGdiCompatibleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleGdiCompatibleStyleName = localeString(names, englishLocale); + + names->Release(); + } + + QString defaultLocaleTypographicFamilyName; + QString englishLocaleTypographicFamilyName; + if (SUCCEEDED(font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES, &names, &ok)) && ok) { + defaultLocaleTypographicFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleTypographicFamilyName = localeString(names, englishLocale); + + names->Release(); + } + + QString defaultLocaleTypographicStyleName; + QString englishLocaleTypographicStyleName; + if (SUCCEEDED(font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES, &names, &ok)) && ok) { + defaultLocaleTypographicStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleTypographicStyleName = localeString(names, englishLocale); + + names->Release(); + } + + { + const auto key = std::make_pair(englishLocaleGdiCompatibleFamilyName, englishLocaleGdiCompatibleStyleName); + if (!englishLocaleGdiCompatibleFamilyName.isEmpty()) + registerFamily(key); + } + + { + const auto key = std::make_pair(defaultLocaleGdiCompatibleFamilyName, defaultLocaleGdiCompatibleStyleName); + if (!defaultLocaleGdiCompatibleFamilyName.isEmpty()) + registerFamily(key); + } + + { + const auto key = std::make_pair(englishLocaleTypographicFamilyName, englishLocaleTypographicStyleName); + if (!englishLocaleTypographicFamilyName.isEmpty()) + registerFamily(key); + } + + { + const auto key = std::make_pair(defaultLocaleTypographicFamilyName, defaultLocaleTypographicStyleName); + if (!defaultLocaleTypographicFamilyName.isEmpty()) + registerFamily(key); + } +} + QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont) { qCDebug(lcQpaFonts) << "Adding application font" << fileName; @@ -377,6 +450,7 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray return QStringList(); } + QSet<std::pair<QString, QString> > registeredFonts; QSet<QString> ret; for (int i = 0; i < faces.size(); ++i) { IDWriteFontFace *face = faces.at(i); @@ -393,62 +467,6 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray DirectWriteScope<IDWriteFontFace3> face3; if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3), reinterpret_cast<void **>(&face3)))) { - QString defaultLocaleFamilyName; - QString englishLocaleFamilyName; - - IDWriteLocalizedStrings *names = nullptr; - if (SUCCEEDED(face3->GetFamilyNames(&names))) { - defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleFamilyName = localeString(names, englishLocale); - - names->Release(); - } - - QString defaultLocaleStyleName; - QString englishLocaleStyleName; - if (SUCCEEDED(face3->GetFaceNames(&names))) { - defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleStyleName = localeString(names, englishLocale); - - names->Release(); - } - - BOOL ok; - QString defaultLocaleGdiCompatibleFamilyName; - QString englishLocaleGdiCompatibleFamilyName; - if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &names, &ok)) && ok) { - defaultLocaleGdiCompatibleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleGdiCompatibleFamilyName = localeString(names, englishLocale); - - names->Release(); - } - - QString defaultLocaleGdiCompatibleStyleName; - QString englishLocaleGdiCompatibleStyleName; - if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, &names, &ok)) && ok) { - defaultLocaleGdiCompatibleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleGdiCompatibleStyleName = localeString(names, englishLocale); - - names->Release(); - } - - QString defaultLocaleTypographicFamilyName; - QString englishLocaleTypographicFamilyName; - if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES, &names, &ok)) && ok) { - defaultLocaleTypographicFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleTypographicFamilyName = localeString(names, englishLocale); - - names->Release(); - } - - QString defaultLocaleTypographicStyleName; - QString englishLocaleTypographicStyleName; - if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES, &names, &ok)) && ok) { - defaultLocaleTypographicStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleTypographicStyleName = localeString(names, englishLocale); - - names->Release(); - } QFont::Stretch stretch = fromDirectWriteStretch(face3->GetStretch()); QFont::Style style = fromDirectWriteStyle(face3->GetStyle()); @@ -456,26 +474,26 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray bool fixed = face3->IsMonospacedFont(); bool color = face3->IsColorFont(); - qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName - << ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName - << ", stretch:" << stretch - << ", style:" << style - << ", weight:" << weight - << ", fixed:" << fixed; + auto registerFamilyAndStyle = [&](const std::pair<QString, QString> &familyAndStyle) + { + if (registeredFonts.contains(familyAndStyle)) + return; + registeredFonts.insert(familyAndStyle); + ret.insert(familyAndStyle.first); - if (!englishLocaleFamilyName.isEmpty()) { + qCDebug(lcQpaFonts) << "\tRegistering alternative:" << familyAndStyle.first + << ":" << familyAndStyle.second; if (applicationFont != nullptr) { QFontDatabasePrivate::ApplicationFont::Properties properties; properties.style = style; properties.weight = weight; - properties.familyName = englishLocaleFamilyName; - properties.styleName = englishLocaleStyleName; + properties.familyName = familyAndStyle.first; + properties.styleName = familyAndStyle.second; applicationFont->properties.append(properties); } - ret.insert(englishLocaleFamilyName); - QPlatformFontDatabase::registerFont(englishLocaleFamilyName, - englishLocaleStyleName, + QPlatformFontDatabase::registerFont(familyAndStyle.first, + familyAndStyle.second, QString(), weight, style, @@ -486,139 +504,53 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray fixed, color, writingSystems, - new FontHandle(face, englishLocaleFamilyName)); - } + new FontHandle(face, familyAndStyle.first)); + }; - if (!defaultLocaleFamilyName.isEmpty() && !ret.contains(defaultLocaleFamilyName)) { - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = style; - properties.weight = weight; - properties.familyName = englishLocaleFamilyName; - properties.styleName = englishLocaleStyleName; - applicationFont->properties.append(properties); - } - - ret.insert(defaultLocaleFamilyName); - QPlatformFontDatabase::registerFont(defaultLocaleFamilyName, - defaultLocaleStyleName, - QString(), - weight, - style, - stretch, - antialias, - scalable, - size, - fixed, - color, - writingSystems, - new FontHandle(face, defaultLocaleFamilyName)); - } + QString defaultLocaleFamilyName; + QString englishLocaleFamilyName; - if (!englishLocaleGdiCompatibleFamilyName.isEmpty() && - !ret.contains(englishLocaleGdiCompatibleFamilyName)) { - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = style; - properties.weight = weight; - properties.familyName = englishLocaleGdiCompatibleFamilyName; - applicationFont->properties.append(properties); - } + IDWriteLocalizedStrings *names = nullptr; + if (SUCCEEDED(face3->GetFamilyNames(&names))) { + defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleFamilyName = localeString(names, englishLocale); - ret.insert(englishLocaleGdiCompatibleFamilyName); - QPlatformFontDatabase::registerFont(englishLocaleGdiCompatibleFamilyName, - englishLocaleGdiCompatibleStyleName, - QString(), - weight, - style, - stretch, - antialias, - scalable, - size, - fixed, - color, - writingSystems, - new FontHandle(face, englishLocaleGdiCompatibleFamilyName)); + names->Release(); } - if (!defaultLocaleGdiCompatibleFamilyName.isEmpty() - && !ret.contains(defaultLocaleGdiCompatibleFamilyName)) { - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = style; - properties.weight = weight; - properties.familyName = defaultLocaleGdiCompatibleFamilyName; - applicationFont->properties.append(properties); - } + QString defaultLocaleStyleName; + QString englishLocaleStyleName; + if (SUCCEEDED(face3->GetFaceNames(&names))) { + defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleStyleName = localeString(names, englishLocale); - ret.insert(defaultLocaleGdiCompatibleFamilyName); - QPlatformFontDatabase::registerFont(defaultLocaleGdiCompatibleFamilyName, - defaultLocaleGdiCompatibleStyleName, - QString(), - weight, - style, - stretch, - antialias, - scalable, - size, - fixed, - color, - writingSystems, - new FontHandle(face, defaultLocaleGdiCompatibleFamilyName)); + names->Release(); } - if (!englishLocaleTypographicFamilyName.isEmpty() - && !ret.contains(englishLocaleTypographicFamilyName)) { - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = style; - properties.weight = weight; - properties.familyName = englishLocaleTypographicFamilyName; - applicationFont->properties.append(properties); - } + qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName + << ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName + << ", stretch:" << stretch + << ", style:" << style + << ", weight:" << weight + << ", fixed:" << fixed; - ret.insert(englishLocaleTypographicFamilyName); - QPlatformFontDatabase::registerFont(englishLocaleTypographicFamilyName, - englishLocaleTypographicStyleName, - QString(), - weight, - style, - stretch, - antialias, - scalable, - size, - fixed, - color, - writingSystems, - new FontHandle(face, englishLocaleTypographicFamilyName)); + { + const auto key = std::make_pair(englishLocaleFamilyName, englishLocaleStyleName); + if (!englishLocaleFamilyName.isEmpty()) + registerFamilyAndStyle(key); } - if (!defaultLocaleTypographicFamilyName.isEmpty() - && !ret.contains(defaultLocaleTypographicFamilyName)) { - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = style; - properties.weight = weight; - properties.familyName = defaultLocaleTypographicFamilyName; - applicationFont->properties.append(properties); - } - - ret.insert(defaultLocaleTypographicFamilyName); - QPlatformFontDatabase::registerFont(defaultLocaleTypographicFamilyName, - defaultLocaleTypographicStyleName, - QString(), - weight, - style, - stretch, - antialias, - scalable, - size, - fixed, - color, - writingSystems, - new FontHandle(face, defaultLocaleTypographicFamilyName)); + { + const auto key = std::make_pair(defaultLocaleFamilyName, defaultLocaleStyleName); + if (!defaultLocaleFamilyName.isEmpty()) + registerFamilyAndStyle(key); } + collectAdditionalNames(*face3, + hasDefaultLocale ? defaultLocale : nullptr, + englishLocale, + registerFamilyAndStyle); + } else { qCWarning(lcQpaFonts) << "Unable to query IDWriteFontFace3 interface from font face."; } @@ -678,44 +610,59 @@ void QWindowsDirectWriteFontDatabase::populateFontDatabase() if (SUCCEEDED(factory6->GetSystemFontCollection(false, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC, &fontCollection))) { + QSet<QString> registeredFamilies; for (uint i = 0; i < fontCollection->GetFontFamilyCount(); ++i) { DirectWriteScope<IDWriteFontFamily2> fontFamily; if (SUCCEEDED(fontCollection->GetFontFamily(i, &fontFamily))) { + auto registerFamily = [&](const std::pair<QString, QString> &familyAndStyle) { + const QString registeredFamily = familyAndStyle.first; + if (registeredFamilies.contains(registeredFamily)) + return; + registeredFamilies.insert(registeredFamily); + + qCDebug(lcQpaFonts) << "Registering font family" << registeredFamily; + registerFontFamily(registeredFamily); + m_populatedFonts.insert(registeredFamily, *fontFamily); + fontFamily->AddRef(); + + if (registeredFamily == defaultFontName + && defaultFontName != systemDefaultFontName) { + qCDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName + << "as alternative to" << registeredFamily; + + m_populatedFonts.insert(systemDefaultFontName, *fontFamily); + fontFamily->AddRef(); + } + }; + QString defaultLocaleName; QString englishLocaleName; - DirectWriteScope<IDWriteLocalizedStrings> names; if (SUCCEEDED(fontFamily->GetFamilyNames(&names))) { if (hasDefaultLocale) defaultLocaleName = localeString(*names, defaultLocale); - englishLocaleName = localeString(*names, englishLocale); } - qCDebug(lcQpaFonts) << "Registering font, english name = " << englishLocaleName << ", name in current locale = " << defaultLocaleName; - if (!defaultLocaleName.isEmpty()) { - registerFontFamily(defaultLocaleName); - m_populatedFonts.insert(defaultLocaleName, *fontFamily); - fontFamily->AddRef(); - - if (defaultLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) { - qCDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << defaultLocaleName; - - m_populatedFonts.insert(systemDefaultFontName, *fontFamily); - fontFamily->AddRef(); - } + { + const auto key = std::make_pair(defaultLocaleName, QString{}); + if (!defaultLocaleName.isEmpty()) + registerFamily(key); } - if (!englishLocaleName.isEmpty() && englishLocaleName != defaultLocaleName) { - registerFontFamily(englishLocaleName); - m_populatedFonts.insert(englishLocaleName, *fontFamily); - fontFamily->AddRef(); - - if (englishLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) { - qCDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << englishLocaleName; + { + const auto key = std::make_pair(englishLocaleName, QString{}); + if (!englishLocaleName.isEmpty()) + registerFamily(key); + } - m_populatedFonts.insert(systemDefaultFontName, *fontFamily); - fontFamily->AddRef(); + for (uint j = 0; j < fontFamily->GetFontCount(); ++j) { + DirectWriteScope<IDWriteFont3> font; + if (SUCCEEDED(fontFamily->GetFont(j, &font))) { + collectAdditionalNames(*font, + hasDefaultLocale ? defaultLocale : nullptr, + englishLocale, + registerFamily); } } } diff --git a/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h b/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h index 1ea01cbd88e..c8ebdef3561 100644 --- a/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h +++ b/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h @@ -69,6 +69,12 @@ private: friend class QWindowsFontEngineDirectWrite; static QString localeString(IDWriteLocalizedStrings *names, wchar_t localeName[]); + template<typename T> + static void collectAdditionalNames(T *fontFace, + wchar_t *defaultLocale, + wchar_t *englishLocale, + std::function<void(const std::pair<QString, QString> &)> registerFamily); + QSupportedWritingSystems supportedWritingSystems(IDWriteFontFace *face) const; QHash<QString, IDWriteFontFamily *> m_populatedFonts; |