summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2016-11-07 14:37:58 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-11-23 10:04:47 +0000
commit9204b8c31ea1b5f0c05870c5b5d74c33b1a4f622 (patch)
treee86eaa69aa39a94ec7d243c831c18f6122e3de03 /src/platformsupport
parent53686bf86db1c2695ee16b903e4b86cc3ee74006 (diff)
Register fonts with preferred names on Windows
Looks up the canonical names of enumerated fonts and register them under their preferred names if present. Also changes the logic handling registration of english aliases, so it is always done, even if it might in rare cases cause a double registration since that is safe. Task-number: QTBUG-53458 Change-Id: Ia010774b26072192b55697b717cc37442c852881 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp217
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp105
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h25
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp16
4 files changed, 189 insertions, 174 deletions
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index b8d997bc35..1c615e06ed 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -759,7 +759,7 @@ static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSe
((quint32)(ch1)) \
)
-bool localizedName(const QString &name)
+bool qt_localizedName(const QString &name)
{
const QChar *c = name.unicode();
for (int i = 0; i < name.length(); ++i) {
@@ -769,24 +769,8 @@ bool localizedName(const QString &name)
return false;
}
-static inline quint16 getUShort(const unsigned char *p)
-{
- quint16 val;
- val = *p++ << 8;
- val |= *p;
-
- return val;
-}
-
namespace {
-struct FontNames {
- QString name; // e.g. "DejaVu Sans Condensed"
- QString style; // e.g. "Italic"
- QString preferredName; // e.g. "DejaVu Sans"
- QString preferredStyle; // e.g. "Condensed Italic"
-};
-
static QString readName(bool unicode, const uchar *string, int length)
{
QString out;
@@ -797,7 +781,7 @@ static QString readName(bool unicode, const uchar *string, int length)
out.resize(length);
QChar *uc = out.data();
for (int i = 0; i < length; ++i)
- uc[i] = getUShort(string + 2*i);
+ uc[i] = qt_getUShort(string + 2*i);
} else {
// Apple Roman
@@ -822,7 +806,7 @@ enum PlatformFieldValue {
PlatformId_Microsoft = 3
};
-static FontNames getCanonicalFontNames(const uchar *table, quint32 bytes)
+FontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes)
{
FontNames out;
const int NameRecordSize = 12;
@@ -836,11 +820,11 @@ static FontNames getCanonicalFontNames(const uchar *table, quint32 bytes)
if (bytes < 8)
return out;
- if (getUShort(table) != 0)
+ if (qt_getUShort(table) != 0)
return out;
- count = getUShort(table+2);
- string_offset = getUShort(table+4);
+ count = qt_getUShort(table + 2);
+ string_offset = qt_getUShort(table + 4);
names = table + 6;
if (string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
@@ -859,10 +843,10 @@ static FontNames getCanonicalFontNames(const uchar *table, quint32 bytes)
for (int i = 0; i < count; ++i) {
// search for the correct name entries
- quint16 platform_id = getUShort(names + i*NameRecordSize);
- quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize);
- quint16 language_id = getUShort(names + 4 + i*NameRecordSize);
- quint16 name_id = getUShort(names + 6 + i*NameRecordSize);
+ quint16 platform_id = qt_getUShort(names + i*NameRecordSize);
+ quint16 encoding_id = qt_getUShort(names + 2 + i*NameRecordSize);
+ quint16 language_id = qt_getUShort(names + 4 + i*NameRecordSize);
+ quint16 name_id = qt_getUShort(names + 6 + i*NameRecordSize);
PlatformIdType *idType = nullptr;
int *id = nullptr;
@@ -888,8 +872,8 @@ static FontNames getCanonicalFontNames(const uchar *table, quint32 bytes)
continue;
}
- quint16 length = getUShort(names + 8 + i*NameRecordSize);
- quint16 offset = getUShort(names + 10 + i*NameRecordSize);
+ quint16 length = qt_getUShort(names + 8 + i*NameRecordSize);
+ quint16 offset = qt_getUShort(names + 10 + i*NameRecordSize);
if (DWORD(string_offset + offset + length) > bytes)
continue;
@@ -916,8 +900,8 @@ static FontNames getCanonicalFontNames(const uchar *table, quint32 bytes)
if (idStatus[i] == NotFound)
continue;
int id = ids[i];
- quint16 length = getUShort(names + 8 + id * NameRecordSize);
- quint16 offset = getUShort(names + 10 + id * NameRecordSize);
+ quint16 length = qt_getUShort(names + 8 + id * NameRecordSize);
+ quint16 offset = qt_getUShort(names + 10 + id * NameRecordSize);
const unsigned char *string = table + string_offset + offset;
strings[i] = readName(idStatus[i] != Apple, string, length);
}
@@ -931,7 +915,7 @@ static FontNames getCanonicalFontNames(const uchar *table, quint32 bytes)
} // namespace
-QString getEnglishName(const QString &familyName, bool includeStyle = false)
+QString qt_getEnglishName(const QString &familyName, bool includeStyle)
{
QString i18n_name;
QString faceName = familyName;
@@ -970,7 +954,7 @@ QString getEnglishName(const QString &familyName, bool includeStyle = false)
goto error;
{
- const FontNames names = getCanonicalFontNames(table, bytes);
+ const FontNames names = qt_getCanonicalFontNames(table, bytes);
i18n_name = names.name;
if (includeStyle)
i18n_name += QLatin1Char(' ') + names.style;
@@ -985,16 +969,63 @@ error:
return i18n_name;
}
-static bool addFontToDatabase(const QString &familyName, const QString &styleName, uchar charSet,
+// Note this duplicates parts of qt_getEnglishName, we should try to unify the two functions.
+FontNames qt_getCanonicalFontNames(const LOGFONT &lf)
+{
+ FontNames fontNames;
+ HDC hdc = GetDC(0);
+ HFONT hfont = CreateFontIndirect(&lf);
+
+ if (!hfont) {
+ ReleaseDC(0, hdc);
+ return fontNames;
+ }
+
+ HGDIOBJ oldobj = SelectObject(hdc, hfont);
+
+ // get the name table
+ QByteArray table;
+ const DWORD name_tag = MAKE_TAG('n', 'a', 'm', 'e');
+ DWORD bytes = GetFontData(hdc, name_tag, 0, 0, 0);
+ if (bytes != GDI_ERROR) {
+ table.resize(bytes);
+
+ if (GetFontData(hdc, name_tag, 0, table.data(), bytes) != GDI_ERROR)
+ fontNames = qt_getCanonicalFontNames(reinterpret_cast<const uchar*>(table.constData()), bytes);
+ }
+
+ SelectObject(hdc, oldobj);
+ DeleteObject(hfont);
+ ReleaseDC(0, hdc);
+
+ return fontNames;
+}
+
+static QChar *createFontFile(const QString &faceName)
+{
+ QChar *faceNamePtr = nullptr;
+ if (!faceName.isEmpty()) {
+ const int nameLength = qMin(faceName.length(), LF_FACESIZE - 1);
+ faceNamePtr = new QChar[nameLength + 1];
+ memcpy(faceNamePtr, faceName.utf16(), sizeof(wchar_t) * nameLength);
+ faceNamePtr[nameLength] = 0;
+ }
+ return faceNamePtr;
+}
+
+static bool addFontToDatabase(QString familyName,
+ QString styleName,
+ const LOGFONT &logFont,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
- int type,
- bool registerAlias)
+ int type)
{
// the "@family" fonts are just the same as "family". Ignore them.
if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_")))
return false;
+ uchar charSet = logFont.lfCharSet;
+
static const int SMOOTH_SCALABLE = 0xffff;
const QString foundryName; // No such concept.
const bool fixed = !(textmetric->tmPitchAndFamily & TMPF_FIXED_PITCH);
@@ -1023,10 +1054,24 @@ static bool addFontToDatabase(const QString &familyName, const QString &styleNam
qCDebug(lcQpaFonts) << message;
}
#endif
-
QString englishName;
- if (registerAlias && ttf && localizedName(familyName))
- englishName = getEnglishName(familyName);
+ QString faceName;
+
+ QString subFamilyName;
+ QString subFamilyStyle;
+ if (ttf) {
+ // Look-up names registered in the font
+ FontNames canonicalNames = qt_getCanonicalFontNames(logFont);
+ if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty())
+ englishName = canonicalNames.name;
+ if (!canonicalNames.preferredName.isEmpty()) {
+ subFamilyName = familyName;
+ subFamilyStyle = styleName;
+ faceName = familyName; // Remember the original name for later lookups
+ familyName = canonicalNames.preferredName;
+ styleName = canonicalNames.preferredStyle;
+ }
+ }
QSupportedWritingSystems writingSystems;
if (type & TRUETYPE_FONTTYPE) {
@@ -1054,32 +1099,36 @@ static bool addFontToDatabase(const QString &familyName, const QString &styleNam
}
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
- style, stretch, antialias, scalable, size, fixed, writingSystems, 0);
+ style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
+
// add fonts windows can generate for us:
if (weight <= QFont::DemiBold && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
- style, stretch, antialias, scalable, size, fixed, writingSystems, 0);
+ style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
if (style != QFont::StyleItalic && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight,
- QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
+ QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
- QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
+ QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
- if (!englishName.isEmpty())
+ if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
+ QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
+ style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
+ }
+
+ if (!englishName.isEmpty() && englishName != familyName)
QPlatformFontDatabase::registerAliasToFontFamily(familyName, englishName);
return true;
}
static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric,
- DWORD type, LPARAM lParam)
+ DWORD type, LPARAM)
{
const ENUMLOGFONTEX *f = reinterpret_cast<const ENUMLOGFONTEX *>(logFont);
const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
const QString styleName = QString::fromWCharArray(f->elfStyle);
- const uchar charSet = f->elfLogFont.lfCharSet;
- const bool registerAlias = bool(lParam);
// NEWTEXTMETRICEX (passed for TT fonts) is a NEWTEXTMETRIC, which according
// to the documentation is identical to a TEXTMETRIC except for the last four
@@ -1087,13 +1136,13 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
const FONTSIGNATURE *signature = Q_NULLPTR;
if (type & TRUETYPE_FONTTYPE)
signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
- addFontToDatabase(familyName, styleName, charSet, textmetric, signature, type, registerAlias);
+ addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type);
// keep on enumerating
return 1;
}
-void QWindowsFontDatabase::populateFamily(const QString &familyName, bool registerAlias)
+void QWindowsFontDatabase::populateFamily(const QString &familyName)
{
qCDebug(lcQpaFonts) << familyName;
if (familyName.size() >= LF_FACESIZE) {
@@ -1106,29 +1155,12 @@ void QWindowsFontDatabase::populateFamily(const QString &familyName, bool regist
familyName.toWCharArray(lf.lfFaceName);
lf.lfFaceName[familyName.size()] = 0;
lf.lfPitchAndFamily = 0;
- EnumFontFamiliesEx(dummy, &lf, storeFont, LPARAM(registerAlias), 0);
+ EnumFontFamiliesEx(dummy, &lf, storeFont, 0, 0);
ReleaseDC(0, dummy);
}
-void QWindowsFontDatabase::populateFamily(const QString &familyName)
-{
- populateFamily(familyName, false);
-}
-
-namespace {
-// Context for enumerating system fonts, records whether the default font has been encountered,
-// which is normally not enumerated by EnumFontFamiliesEx().
-struct PopulateFamiliesContext
-{
- PopulateFamiliesContext(const QString &f) : systemDefaultFont(f), seenSystemDefaultFont(false) {}
-
- QString systemDefaultFont;
- bool seenSystemDefaultFont;
-};
-} // namespace
-
-static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric,
- DWORD, LPARAM lparam)
+static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *,
+ DWORD, LPARAM)
{
// the "@family" fonts are just the same as "family". Ignore them.
const ENUMLOGFONTEX *f = reinterpret_cast<const ENUMLOGFONTEX *>(logFont);
@@ -1136,22 +1168,6 @@ static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TE
if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) {
const QString faceName = QString::fromWCharArray(faceNameW);
QPlatformFontDatabase::registerFontFamily(faceName);
- PopulateFamiliesContext *context = reinterpret_cast<PopulateFamiliesContext *>(lparam);
- if (!context->seenSystemDefaultFont && faceName == context->systemDefaultFont)
- context->seenSystemDefaultFont = true;
-
- // Register current font's english name as alias
- const bool ttf = textmetric->tmPitchAndFamily & TMPF_TRUETYPE;
- if (ttf && localizedName(faceName)) {
- const QString englishName = getEnglishName(faceName);
- if (!englishName.isEmpty()) {
- QPlatformFontDatabase::registerAliasToFontFamily(faceName, englishName);
- // Check whether the system default font name is an alias of the current font family name,
- // as on Chinese Windows, where the system font "SimSun" is an alias to a font registered under a local name
- if (!context->seenSystemDefaultFont && englishName == context->systemDefaultFont)
- context->seenSystemDefaultFont = true;
- }
- }
}
return 1; // continue
}
@@ -1164,12 +1180,10 @@ void QWindowsFontDatabase::populateFontDatabase()
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfFaceName[0] = 0;
lf.lfPitchAndFamily = 0;
- PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family());
- EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, reinterpret_cast<LPARAM>(&context), 0);
+ EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, 0, 0);
ReleaseDC(0, dummy);
// Work around EnumFontFamiliesEx() not listing the system font.
- if (!context.seenSystemDefaultFont)
- QPlatformFontDatabase::registerFontFamily(context.systemDefaultFont);
+ QPlatformFontDatabase::registerFontFamily(QWindowsFontDatabase::systemDefaultFont().family());
}
typedef QSharedPointer<QWindowsFontEngineData> QWindowsFontEngineDataPtr;
@@ -1228,7 +1242,8 @@ QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine,
QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
- QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef,
+ const QString faceName(static_cast<const QChar*>(handle));
+ QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef, faceName,
defaultVerticalDPI(),
sharedFontData());
qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << fe << handle;
@@ -1282,7 +1297,7 @@ QT_WARNING_POP
request.hintingPreference = hintingPreference;
request.stretch = QFont::Unstretched;
- fontEngine = QWindowsFontDatabase::createEngine(request,
+ fontEngine = QWindowsFontDatabase::createEngine(request, QString(),
defaultVerticalDPI(),
sharedFontData());
@@ -1461,7 +1476,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
if (!table)
continue;
- FontNames names = getCanonicalFontNames(table, length);
+ FontNames names = qt_getCanonicalFontNames(table, length);
if (names.name.isEmpty())
continue;
@@ -1523,8 +1538,8 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
TEXTMETRIC textMetrics;
GetTextMetrics(hdc, &textMetrics);
- addFontToDatabase(familyName, styleName, lf.lfCharSet, &textMetrics, &signatures.at(j),
- TRUETYPE_FONTTYPE, true);
+ addFontToDatabase(familyName, styleName, lf, &textMetrics, &signatures.at(j),
+ TRUETYPE_FONTTYPE);
SelectObject(hdc, oldobj);
DeleteObject(hfont);
@@ -1550,7 +1565,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
for (int j = 0; j < families.count(); ++j) {
const QString familyName = families.at(j).name;
familyNames << familyName;
- populateFamily(familyName, true);
+ populateFamily(familyName);
}
}
@@ -1571,8 +1586,10 @@ void QWindowsFontDatabase::removeApplicationFonts()
m_applicationFonts.clear();
}
-void QWindowsFontDatabase::releaseHandle(void * /* handle */)
+void QWindowsFontDatabase::releaseHandle(void *handle)
{
+ const QChar *faceName = reinterpret_cast<const QChar *>(handle);
+ delete[] faceName;
}
QString QWindowsFontDatabase::fontDir() const
@@ -1663,7 +1680,7 @@ static const char *kr_tryFonts[] = {
static const char **tryFonts = 0;
-LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request)
+LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request, const QString &faceName)
{
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
@@ -1738,7 +1755,9 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request)
lf.lfPitchAndFamily = DEFAULT_PITCH | hint;
- QString fam = request.family;
+ QString fam = faceName;
+ if (fam.isEmpty())
+ fam = request.family;
if (Q_UNLIKELY(fam.size() >= LF_FACESIZE)) {
qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam));
fam.truncate(LF_FACESIZE - 1);
@@ -1837,13 +1856,13 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFon
}
-QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request,
+QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const QString &faceName,
int dpi,
const QSharedPointer<QWindowsFontEngineData> &data)
{
QFontEngine *fe = 0;
- LOGFONT lf = fontDefToLOGFONT(request);
+ LOGFONT lf = fontDefToLOGFONT(request, faceName);
const bool preferClearTypeAA = lf.lfQuality == CLEARTYPE_QUALITY;
if (request.stretch != 100) {
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
index 4d973bbf17..df84198862 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
@@ -100,9 +100,6 @@ static FontFile * createFontFile(const QString &fileName, int index)
return fontFile;
}
-extern bool localizedName(const QString &name);
-extern QString getEnglishName(const QString &familyName, bool includeStyle = false);
-
namespace {
struct FontKey
{
@@ -162,19 +159,20 @@ static const FontKey *findFontKey(const QString &name, int *indexIn = Q_NULLPTR)
return Q_NULLPTR;
}
-static bool addFontToDatabase(const QString &faceName,
- const QString &styleName,
+static bool addFontToDatabase(QString familyName,
+ QString styleName,
const QString &fullName,
- uchar charSet,
+ const LOGFONT &logFont,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
- int type,
- bool registerAlias)
+ int type)
{
// the "@family" fonts are just the same as "family". Ignore them.
- if (faceName.isEmpty() || faceName.at(0) == QLatin1Char('@') || faceName.startsWith(QLatin1String("WST_")))
+ if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_")))
return false;
+ uchar charSet = logFont.lfCharSet;
+
static const int SMOOTH_SCALABLE = 0xffff;
const QString foundryName; // No such concept.
const bool fixed = !(textmetric->tmPitchAndFamily & TMPF_FIXED_PITCH);
@@ -190,7 +188,7 @@ static bool addFontToDatabase(const QString &faceName,
if (lcQpaFonts().isDebugEnabled()) {
QString message;
QTextStream str(&message);
- str << __FUNCTION__ << ' ' << faceName << "::" << fullName << ' ' << charSet << " TTF=" << ttf;
+ str << __FUNCTION__ << ' ' << familyName << "::" << fullName << ' ' << charSet << " TTF=" << ttf;
if (type & DEVICE_FONTTYPE)
str << " DEVICE";
if (type & RASTER_FONTTYPE)
@@ -205,8 +203,22 @@ static bool addFontToDatabase(const QString &faceName,
#endif
QString englishName;
- if (registerAlias & ttf && localizedName(faceName))
- englishName = getEnglishName(faceName);
+ QString faceName = familyName;
+
+ QString subFamilyName;
+ QString subFamilyStyle;
+ if (ttf) {
+ // Look-up names registered in the font
+ FontNames canonicalNames = qt_getCanonicalFontNames(logFont);
+ if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty())
+ englishName = canonicalNames.name;
+ if (!canonicalNames.preferredName.isEmpty()) {
+ subFamilyName = familyName;
+ subFamilyStyle = styleName;
+ familyName = canonicalNames.preferredName;
+ styleName = canonicalNames.preferredStyle;
+ }
+ }
QSupportedWritingSystems writingSystems;
if (type & TRUETYPE_FONTTYPE) {
@@ -243,12 +255,10 @@ static bool addFontToDatabase(const QString &faceName,
&& systemLocale.language() != QLocale::English
&& styleName != QLatin1String("Italic")
&& styleName != QLatin1String("Bold")) {
- key = findFontKey(getEnglishName(fullName, true), &index);
+ key = findFontKey(qt_getEnglishName(fullName, true), &index);
}
if (!key)
key = findFontKey(faceName, &index);
- if (!key && !registerAlias && englishName.isEmpty() && localizedName(faceName))
- englishName = getEnglishName(faceName);
if (!key && !englishName.isEmpty())
key = findFontKey(englishName, &index);
if (!key)
@@ -261,24 +271,29 @@ static bool addFontToDatabase(const QString &faceName,
if (!QDir::isAbsolutePath(value))
value.prepend(QFile::decodeName(qgetenv("windir") + "\\Fonts\\"));
- QPlatformFontDatabase::registerFont(faceName, styleName, foundryName, weight, style, stretch,
+ QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch,
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
// add fonts windows can generate for us:
if (weight <= QFont::DemiBold && styleName.isEmpty())
- QPlatformFontDatabase::registerFont(faceName, QString(), foundryName, QFont::Bold, style, stretch,
+ QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, style, stretch,
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
if (style != QFont::StyleItalic && styleName.isEmpty())
- QPlatformFontDatabase::registerFont(faceName, QString(), foundryName, weight, QFont::StyleItalic, stretch,
+ QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight, QFont::StyleItalic, stretch,
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
- QPlatformFontDatabase::registerFont(faceName, QString(), foundryName, QFont::Bold, QFont::StyleItalic, stretch,
+ QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, QFont::StyleItalic, stretch,
antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
- if (!englishName.isEmpty())
- QPlatformFontDatabase::registerAliasToFontFamily(faceName, englishName);
+ if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
+ QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
+ style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(value, index));
+ }
+
+ if (!englishName.isEmpty() && englishName != familyName)
+ QPlatformFontDatabase::registerAliasToFontFamily(familyName, englishName);
return true;
}
@@ -290,7 +305,6 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
const QString styleName = QString::fromWCharArray(f->elfStyle);
const QString fullName = QString::fromWCharArray(f->elfFullName);
- const uchar charSet = f->elfLogFont.lfCharSet;
// NEWTEXTMETRICEX (passed for TT fonts) is a NEWTEXTMETRIC, which according
// to the documentation is identical to a TEXTMETRIC except for the last four
@@ -298,7 +312,7 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
const FONTSIGNATURE *signature = Q_NULLPTR;
if (type & TRUETYPE_FONTTYPE)
signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
- addFontToDatabase(faceName, styleName, fullName, charSet, textmetric, signature, type, false);
+ addFontToDatabase(faceName, styleName, fullName, *logFont, textmetric, signature, type);
// keep on enumerating
return 1;
@@ -321,30 +335,19 @@ void QWindowsFontDatabaseFT::populateFamily(const QString &familyName)
}
HDC dummy = GetDC(0);
LOGFONT lf;
- lf.lfCharSet = DEFAULT_CHARSET;
+ memset(&lf, 0, sizeof(LOGFONT));
familyName.toWCharArray(lf.lfFaceName);
lf.lfFaceName[familyName.size()] = 0;
+ lf.lfCharSet = DEFAULT_CHARSET;
lf.lfPitchAndFamily = 0;
EnumFontFamiliesEx(dummy, &lf, storeFont, 0, 0);
ReleaseDC(0, dummy);
}
-namespace {
-// Context for enumerating system fonts, records whether the default font has been
-// encountered, which is normally not enumerated.
-struct PopulateFamiliesContext
-{
- PopulateFamiliesContext(const QString &f) : systemDefaultFont(f), seenSystemDefaultFont(false) {}
-
- QString systemDefaultFont;
- bool seenSystemDefaultFont;
-};
-} // namespace
-
// Delayed population of font families
static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric,
- DWORD, LPARAM lparam)
+ DWORD, LPARAM)
{
const ENUMLOGFONTEX *f = reinterpret_cast<const ENUMLOGFONTEX *>(logFont);
// the "@family" fonts are just the same as "family". Ignore them.
@@ -356,27 +359,11 @@ static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TE
const FontKey *key = findFontKey(faceName);
if (!key) {
key = findFontKey(QString::fromWCharArray(f->elfFullName));
- if (!key && ttf && localizedName(faceName))
- key = findFontKey(getEnglishName(faceName));
+ if (!key && ttf && qt_localizedName(faceName))
+ key = findFontKey(qt_getEnglishName(faceName));
}
- if (key) {
+ if (key)
QPlatformFontDatabase::registerFontFamily(faceName);
- PopulateFamiliesContext *context = reinterpret_cast<PopulateFamiliesContext *>(lparam);
- if (!context->seenSystemDefaultFont && faceName == context->systemDefaultFont)
- context->seenSystemDefaultFont = true;
-
- // Register current font's english name as alias
- if (ttf && localizedName(faceName)) {
- const QString englishName = getEnglishName(faceName);
- if (!englishName.isEmpty()) {
- QPlatformFontDatabase::registerAliasToFontFamily(faceName, englishName);
- // Check whether the system default font name is an alias of the current font family name,
- // as on Chinese Windows, where the system font "SimSun" is an alias to a font registered under a local name
- if (!context->seenSystemDefaultFont && englishName == context->systemDefaultFont)
- context->seenSystemDefaultFont = true;
- }
- }
- }
}
return 1; // continue
}
@@ -388,12 +375,10 @@ void QWindowsFontDatabaseFT::populateFontDatabase()
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfFaceName[0] = 0;
lf.lfPitchAndFamily = 0;
- PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family());
- EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, reinterpret_cast<LPARAM>(&context), 0);
+ EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, 0, 0);
ReleaseDC(0, dummy);
// Work around EnumFontFamiliesEx() not listing the system font
- if (!context.seenSystemDefaultFont)
- QPlatformFontDatabase::registerFontFamily(context.systemDefaultFont);
+ QPlatformFontDatabase::registerFontFamily(QWindowsFontDatabase::systemDefaultFont().family());
}
QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle)
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
index b7ebfc033f..325f522335 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
@@ -112,7 +112,7 @@ public:
static QFont systemDefaultFont();
- static QFontEngine *createEngine(const QFontDef &request,
+ static QFontEngine *createEngine(const QFontDef &request, const QString &faceName,
int dpi,
const QSharedPointer<QWindowsFontEngineData> &data);
@@ -120,7 +120,7 @@ public:
static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0);
static qreal fontSmoothingGamma();
- static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef);
+ static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef, const QString &faceName);
static QStringList extraTryFontsForFamily(const QString &family);
static QString familyForStyleHint(QFont::StyleHint styleHint);
@@ -133,7 +133,6 @@ public:
static QString readRegistryString(HKEY parentHandle, const wchar_t *keyPath, const wchar_t *keyName);
private:
- void populateFamily(const QString &familyName, bool registerAlias);
void removeApplicationFonts();
struct WinApplicationFont {
@@ -157,6 +156,26 @@ private:
QDebug operator<<(QDebug, const QFontDef &def);
#endif
+inline quint16 qt_getUShort(const unsigned char *p)
+{
+ quint16 val;
+ val = *p++ << 8;
+ val |= *p;
+
+ return val;
+}
+
+struct FontNames {
+ QString name; // e.g. "DejaVu Sans Condensed"
+ QString style; // e.g. "Italic"
+ QString preferredName; // e.g. "DejaVu Sans"
+ QString preferredStyle; // e.g. "Condensed Italic"
+};
+
+bool qt_localizedName(const QString &name);
+QString qt_getEnglishName(const QString &familyName, bool includeStyle = false);
+FontNames qt_getCanonicalFontNames(const LOGFONT &lf);
+
QT_END_NAMESPACE
#endif // QWINDOWSFONTDATABASE_H
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
index 9fc6fec915..0cd473e020 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
@@ -97,15 +97,6 @@ static void resolveGetCharWidthI()
ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QStringLiteral("gdi32"), "GetCharWidthI");
}
-static inline quint16 getUShort(unsigned char *p)
-{
- quint16 val;
- val = *p++ << 8;
- val |= *p;
-
- return val;
-}
-
// general font engine
QFixed QWindowsFontEngine::lineThickness() const
@@ -912,7 +903,7 @@ int QWindowsFontEngine::synthesized() const
SelectObject(hdc, hfont);
uchar data[4];
GetFontData(hdc, HEAD, 44, &data, 4);
- USHORT macStyle = getUShort(data);
+ USHORT macStyle = qt_getUShort(data);
if (tm.tmItalic && !(macStyle & 2))
synthesized_flags = SynthesizedItalic;
if (fontDef.stretch != 100 && ttf)
@@ -1192,9 +1183,10 @@ QFontEngine *QWindowsFontEngine::cloneWithSize(qreal pixelSize) const
if (!uniqueFamilyName.isEmpty())
request.family = uniqueFamilyName;
request.pixelSize = pixelSize;
+ const QString faceName = QString::fromWCharArray(m_logfont.lfFaceName);
QFontEngine *fontEngine =
- QWindowsFontDatabase::createEngine(request,
+ QWindowsFontDatabase::createEngine(request, faceName,
QWindowsFontDatabase::defaultVerticalDPI(),
m_fontEngineData);
if (fontEngine) {
@@ -1257,7 +1249,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at)
#ifndef QT_NO_DIRECTWRITE
if (fontEngine->type() == QFontEngine::DirectWrite) {
QWindowsFontEngineDirectWrite *fe = static_cast<QWindowsFontEngineDirectWrite *>(fontEngine);
- lf = QWindowsFontDatabase::fontDefToLOGFONT(fe->fontDef);
+ lf = QWindowsFontDatabase::fontDefToLOGFONT(fe->fontDef, QString());
data = fe->fontEngineData();
} else