DirectWrite font db: Fix fallback fonts
The implementation of this was based on a misunderstanding of the API. The GetMatchingFonts() function does not give a sorted list of fonts that can be used in place of the given family, but just requests the fonts in the family itself. Instead, we use the same implementation as in the other two font databases we have on Windows (moving the implementation to be shared). Change-Id: I6a7b73e3d8376f7d97f598db0d7b63122ad1940c Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
3c0cd7566c
commit
ba50d27e76
@ -39,6 +39,7 @@
|
||||
|
||||
#include "qwindowsdirectwritefontdatabase_p.h"
|
||||
#include "qwindowsfontenginedirectwrite_p.h"
|
||||
#include "qwindowsfontdatabase_p.h"
|
||||
|
||||
#include <QtCore/qendian.h>
|
||||
#include <QtCore/qstringbuilder.h>
|
||||
@ -269,54 +270,14 @@ QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QFontDef &fontDef
|
||||
|
||||
QStringList QWindowsDirectWriteFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
||||
{
|
||||
Q_UNUSED(styleHint);
|
||||
Q_UNUSED(script);
|
||||
QStringList result;
|
||||
result.append(familyForStyleHint(styleHint));
|
||||
result.append(extraTryFontsForFamily(family));
|
||||
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
|
||||
wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH];
|
||||
bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0;
|
||||
wchar_t englishLocale[] = L"en-us";
|
||||
|
||||
QStringList ret;
|
||||
|
||||
auto it = m_populatedFonts.find(family);
|
||||
IDWriteFontFamily *fontFamily = it != m_populatedFonts.end() ? it.value() : nullptr;
|
||||
if (fontFamily != nullptr) {
|
||||
IDWriteFontList *matchingFonts = nullptr;
|
||||
if (SUCCEEDED(fontFamily->GetMatchingFonts(DWRITE_FONT_WEIGHT_REGULAR,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
toDirectWriteStyle(style),
|
||||
&matchingFonts))) {
|
||||
for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) {
|
||||
IDWriteFont *font = nullptr;
|
||||
if (SUCCEEDED(matchingFonts->GetFont(j, &font))) {
|
||||
IDWriteFontFamily *fontFamily2;
|
||||
if (SUCCEEDED(font->GetFontFamily(&fontFamily2))) {
|
||||
IDWriteLocalizedStrings *names;
|
||||
if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) {
|
||||
QString name = localeString(names, englishLocale);
|
||||
if (name.isEmpty() && hasDefaultLocale)
|
||||
name = localeString(names, defaultLocale);
|
||||
|
||||
if (!name.isEmpty() && m_populatedFonts.contains(name))
|
||||
ret.append(name);
|
||||
|
||||
names->Release();
|
||||
}
|
||||
|
||||
fontFamily2->Release();
|
||||
}
|
||||
|
||||
font->Release();
|
||||
}
|
||||
}
|
||||
|
||||
matchingFonts->Release();
|
||||
}
|
||||
}
|
||||
|
||||
qDebug(lcQpaFonts) << "fallbacks for" << family << "is" << ret;
|
||||
|
||||
return ret;
|
||||
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
|
||||
<< script << result;
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
|
||||
|
@ -1080,131 +1080,12 @@ void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont)
|
||||
m_uniqueFontData[uniqueFont].refCount.ref();
|
||||
}
|
||||
|
||||
// Creation functions
|
||||
|
||||
static const char *other_tryFonts[] = {
|
||||
"Arial",
|
||||
"MS UI Gothic",
|
||||
"Gulim",
|
||||
"SimSun",
|
||||
"PMingLiU",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *jp_tryFonts [] = {
|
||||
"MS UI Gothic",
|
||||
"Arial",
|
||||
"Gulim",
|
||||
"SimSun",
|
||||
"PMingLiU",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *ch_CN_tryFonts [] = {
|
||||
"SimSun",
|
||||
"Arial",
|
||||
"PMingLiU",
|
||||
"Gulim",
|
||||
"MS UI Gothic",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *ch_TW_tryFonts [] = {
|
||||
"PMingLiU",
|
||||
"Arial",
|
||||
"SimSun",
|
||||
"Gulim",
|
||||
"MS UI Gothic",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *kr_tryFonts[] = {
|
||||
"Gulim",
|
||||
"Arial",
|
||||
"PMingLiU",
|
||||
"SimSun",
|
||||
"MS UI Gothic",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char **tryFonts = 0;
|
||||
|
||||
QStringList QWindowsFontDatabase::extraTryFontsForFamily(const QString &family)
|
||||
{
|
||||
QStringList result;
|
||||
QFontDatabase db;
|
||||
if (!db.writingSystems(family).contains(QFontDatabase::Symbol)) {
|
||||
if (!tryFonts) {
|
||||
LANGID lid = GetUserDefaultLangID();
|
||||
switch (lid&0xff) {
|
||||
case LANG_CHINESE: // Chinese
|
||||
if ( lid == 0x0804 || lid == 0x1004) // China mainland and Singapore
|
||||
tryFonts = ch_CN_tryFonts;
|
||||
else
|
||||
tryFonts = ch_TW_tryFonts; // Taiwan, Hong Kong and Macau
|
||||
break;
|
||||
case LANG_JAPANESE:
|
||||
tryFonts = jp_tryFonts;
|
||||
break;
|
||||
case LANG_KOREAN:
|
||||
tryFonts = kr_tryFonts;
|
||||
break;
|
||||
default:
|
||||
tryFonts = other_tryFonts;
|
||||
break;
|
||||
}
|
||||
}
|
||||
QFontDatabase db;
|
||||
const QStringList families = db.families();
|
||||
const char **tf = tryFonts;
|
||||
while (tf && *tf) {
|
||||
// QTBUG-31689, family might be an English alias for a localized font name.
|
||||
const QString family = QString::fromLatin1(*tf);
|
||||
if (families.contains(family) || db.hasFamily(family))
|
||||
result << family;
|
||||
++tf;
|
||||
}
|
||||
}
|
||||
result.append(QStringLiteral("Segoe UI Emoji"));
|
||||
result.append(QStringLiteral("Segoe UI Symbol"));
|
||||
return result;
|
||||
}
|
||||
|
||||
QString QWindowsFontDatabase::familyForStyleHint(QFont::StyleHint styleHint)
|
||||
{
|
||||
switch (styleHint) {
|
||||
case QFont::Times:
|
||||
return QStringLiteral("Times New Roman");
|
||||
case QFont::Courier:
|
||||
return QStringLiteral("Courier New");
|
||||
case QFont::Monospace:
|
||||
return QStringLiteral("Courier New");
|
||||
case QFont::Cursive:
|
||||
return QStringLiteral("Comic Sans MS");
|
||||
case QFont::Fantasy:
|
||||
return QStringLiteral("Impact");
|
||||
case QFont::Decorative:
|
||||
return QStringLiteral("Old English");
|
||||
case QFont::Helvetica:
|
||||
return QStringLiteral("Arial");
|
||||
case QFont::System:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QStringLiteral("MS Shell Dlg 2");
|
||||
}
|
||||
|
||||
QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
||||
{
|
||||
QStringList result;
|
||||
result.append(QWindowsFontDatabase::familyForStyleHint(styleHint));
|
||||
result.append(familyForStyleHint(styleHint));
|
||||
result.append(m_eudcFonts);
|
||||
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
|
||||
result.append(extraTryFontsForFamily(family));
|
||||
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
|
||||
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
|
||||
|
@ -422,8 +422,8 @@ QFontEngine *QWindowsFontDatabaseFT::fontEngine(const QByteArray &fontData, qrea
|
||||
QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
|
||||
{
|
||||
QStringList result;
|
||||
result.append(QWindowsFontDatabase::familyForStyleHint(styleHint));
|
||||
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
|
||||
result.append(QWindowsFontDatabaseBase::familyForStyleHint(styleHint));
|
||||
result.append(QWindowsFontDatabaseBase::extraTryFontsForFamily(family));
|
||||
result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
|
||||
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
|
||||
|
@ -96,9 +96,6 @@ public:
|
||||
|
||||
static qreal fontSmoothingGamma();
|
||||
|
||||
static QStringList extraTryFontsForFamily(const QString &family);
|
||||
static QString familyForStyleHint(QFont::StyleHint styleHint);
|
||||
|
||||
static void setFontOptions(unsigned options);
|
||||
static unsigned fontOptions();
|
||||
|
||||
|
@ -866,4 +866,123 @@ QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qr
|
||||
return fontEngine;
|
||||
}
|
||||
|
||||
QString QWindowsFontDatabaseBase::familyForStyleHint(QFont::StyleHint styleHint)
|
||||
{
|
||||
switch (styleHint) {
|
||||
case QFont::Times:
|
||||
return QStringLiteral("Times New Roman");
|
||||
case QFont::Courier:
|
||||
return QStringLiteral("Courier New");
|
||||
case QFont::Monospace:
|
||||
return QStringLiteral("Courier New");
|
||||
case QFont::Cursive:
|
||||
return QStringLiteral("Comic Sans MS");
|
||||
case QFont::Fantasy:
|
||||
return QStringLiteral("Impact");
|
||||
case QFont::Decorative:
|
||||
return QStringLiteral("Old English");
|
||||
case QFont::Helvetica:
|
||||
return QStringLiteral("Arial");
|
||||
case QFont::System:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QStringLiteral("MS Shell Dlg 2");
|
||||
}
|
||||
|
||||
// Creation functions
|
||||
|
||||
static const char *other_tryFonts[] = {
|
||||
"Arial",
|
||||
"MS UI Gothic",
|
||||
"Gulim",
|
||||
"SimSun",
|
||||
"PMingLiU",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *jp_tryFonts [] = {
|
||||
"MS UI Gothic",
|
||||
"Arial",
|
||||
"Gulim",
|
||||
"SimSun",
|
||||
"PMingLiU",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *ch_CN_tryFonts [] = {
|
||||
"SimSun",
|
||||
"Arial",
|
||||
"PMingLiU",
|
||||
"Gulim",
|
||||
"MS UI Gothic",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *ch_TW_tryFonts [] = {
|
||||
"PMingLiU",
|
||||
"Arial",
|
||||
"SimSun",
|
||||
"Gulim",
|
||||
"MS UI Gothic",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *kr_tryFonts[] = {
|
||||
"Gulim",
|
||||
"Arial",
|
||||
"PMingLiU",
|
||||
"SimSun",
|
||||
"MS UI Gothic",
|
||||
"Arial Unicode MS",
|
||||
0
|
||||
};
|
||||
|
||||
static const char **tryFonts = nullptr;
|
||||
|
||||
QStringList QWindowsFontDatabaseBase::extraTryFontsForFamily(const QString &family)
|
||||
{
|
||||
QStringList result;
|
||||
QFontDatabase db;
|
||||
if (!db.writingSystems(family).contains(QFontDatabase::Symbol)) {
|
||||
if (!tryFonts) {
|
||||
LANGID lid = GetUserDefaultLangID();
|
||||
switch (lid&0xff) {
|
||||
case LANG_CHINESE: // Chinese
|
||||
if ( lid == 0x0804 || lid == 0x1004) // China mainland and Singapore
|
||||
tryFonts = ch_CN_tryFonts;
|
||||
else
|
||||
tryFonts = ch_TW_tryFonts; // Taiwan, Hong Kong and Macau
|
||||
break;
|
||||
case LANG_JAPANESE:
|
||||
tryFonts = jp_tryFonts;
|
||||
break;
|
||||
case LANG_KOREAN:
|
||||
tryFonts = kr_tryFonts;
|
||||
break;
|
||||
default:
|
||||
tryFonts = other_tryFonts;
|
||||
break;
|
||||
}
|
||||
}
|
||||
QFontDatabase db;
|
||||
const QStringList families = db.families();
|
||||
const char **tf = tryFonts;
|
||||
while (tf && *tf) {
|
||||
// QTBUG-31689, family might be an English alias for a localized font name.
|
||||
const QString family = QString::fromLatin1(*tf);
|
||||
if (families.contains(family) || db.hasFamily(family))
|
||||
result << family;
|
||||
++tf;
|
||||
}
|
||||
}
|
||||
result.append(QStringLiteral("Segoe UI Emoji"));
|
||||
result.append(QStringLiteral("Segoe UI Symbol"));
|
||||
return result;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -102,6 +102,9 @@ public:
|
||||
static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef, const QString &faceName);
|
||||
static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0);
|
||||
|
||||
static QString familyForStyleHint(QFont::StyleHint styleHint);
|
||||
static QStringList extraTryFontsForFamily(const QString &family);
|
||||
|
||||
class FontTable{};
|
||||
class EmbeddedFont
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user