diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp | 579 |
1 files changed, 405 insertions, 174 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 0fc5e0dc0c..ad75a0bd54 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -41,31 +41,19 @@ #include <QtCore/QDir> #include <QtCore/QDirIterator> #include <QtCore/QSettings> +#include <QtCore/QRegularExpression> #include <QtGui/private/qfontengine_ft_p.h> #include <QtGui/QGuiApplication> #include <QtGui/QFontDatabase> #include <wchar.h> #ifdef Q_OS_WINCE +#include <QtCore/QFile> #include <QtEndian> #endif QT_BEGIN_NAMESPACE -// convert 0 ~ 1000 integer to QFont::Weight -static inline QFont::Weight weightFromInteger(long weight) -{ - if (weight < 400) - return QFont::Light; - if (weight < 600) - return QFont::Normal; - if (weight < 700) - return QFont::DemiBold; - if (weight < 800) - return QFont::Bold; - return QFont::Black; -} - static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet) { switch (charSet) { @@ -114,22 +102,247 @@ static FontFile * createFontFile(const QString &fileName, int index) extern bool localizedName(const QString &name); extern QString getEnglishName(const QString &familyName); -static bool addFontToDatabase(const QString &familyName, uchar charSet, +#ifndef Q_OS_WINCE + +namespace { +struct FontKey +{ + QString fileName; + QStringList fontNames; +}; +} // namespace + +typedef QVector<FontKey> FontKeys; + +static FontKeys &fontKeys() +{ + static FontKeys result; + if (result.isEmpty()) { + const QSettings fontRegistry(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), + QSettings::NativeFormat); + const QStringList allKeys = fontRegistry.allKeys(); + const QString trueType = QStringLiteral("(TrueType)"); + const QRegularExpression sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); + Q_ASSERT(sizeListMatch.isValid()); + const int size = allKeys.size(); + result.reserve(size); + for (int i = 0; i < size; ++i) { + FontKey fontKey; + const QString ®istryFontKey = allKeys.at(i); + fontKey.fileName = fontRegistry.value(registryFontKey).toString(); + QString realKey = registryFontKey; + realKey.remove(trueType); + realKey.remove(sizeListMatch); + const QStringList fontNames = realKey.trimmed().split(QLatin1Char('&')); + fontKey.fontNames.reserve(fontNames.size()); + foreach (const QString &fontName, fontNames) + fontKey.fontNames.append(fontName.trimmed()); + result.append(fontKey); + } + } + return result; +} + +static const FontKey *findFontKey(const QString &name, int *indexIn = Q_NULLPTR) +{ + typedef FontKeys::ConstIterator ConstIt; + + const FontKeys &keys = fontKeys(); + for (ConstIt it = keys.constBegin(), cend = keys.constEnd(); it != cend; ++it) { + const int index = it->fontNames.indexOf(name); + if (index >= 0) { + if (indexIn) + *indexIn = index; + return &(*it); + } + } + if (indexIn) + *indexIn = -1; + return Q_NULLPTR; +} + +#else // Q_OS_WINCE + +typedef struct { + quint16 majorVersion; + quint16 minorVersion; + quint16 numTables; + quint16 searchRange; + quint16 entrySelector; + quint16 rangeShift; +} OFFSET_TABLE; + +typedef struct { + quint32 tag; + quint32 checkSum; + quint32 offset; + quint32 length; +} TABLE_DIRECTORY; + +typedef struct { + quint16 fontSelector; + quint16 nrCount; + quint16 storageOffset; +} NAME_TABLE_HEADER; + +typedef struct { + quint16 platformID; + quint16 encodingID; + quint16 languageID; + quint16 nameID; + quint16 stringLength; + quint16 stringOffset; +} NAME_RECORD; + +static QString fontNameFromTTFile(const QString &filename) +{ + QFile f(filename); + QString retVal; + qint64 bytesRead; + qint64 bytesToRead; + + if (f.open(QIODevice::ReadOnly)) { + OFFSET_TABLE ttOffsetTable; + bytesToRead = sizeof(OFFSET_TABLE); + bytesRead = f.read((char*)&ttOffsetTable, bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + ttOffsetTable.numTables = qFromBigEndian(ttOffsetTable.numTables); + ttOffsetTable.majorVersion = qFromBigEndian(ttOffsetTable.majorVersion); + ttOffsetTable.minorVersion = qFromBigEndian(ttOffsetTable.minorVersion); + + if (ttOffsetTable.majorVersion != 1 || ttOffsetTable.minorVersion != 0) + return retVal; + + TABLE_DIRECTORY tblDir; + bool found = false; + + for (int i = 0; i < ttOffsetTable.numTables; i++) { + bytesToRead = sizeof(TABLE_DIRECTORY); + bytesRead = f.read((char*)&tblDir, bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + if (qFromBigEndian(tblDir.tag) == MAKE_TAG('n', 'a', 'm', 'e')) { + found = true; + tblDir.length = qFromBigEndian(tblDir.length); + tblDir.offset = qFromBigEndian(tblDir.offset); + break; + } + } + + if (found) { + f.seek(tblDir.offset); + NAME_TABLE_HEADER ttNTHeader; + bytesToRead = sizeof(NAME_TABLE_HEADER); + bytesRead = f.read((char*)&ttNTHeader, bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + ttNTHeader.nrCount = qFromBigEndian(ttNTHeader.nrCount); + ttNTHeader.storageOffset = qFromBigEndian(ttNTHeader.storageOffset); + NAME_RECORD ttRecord; + found = false; + + for (int i = 0; i < ttNTHeader.nrCount; i++) { + bytesToRead = sizeof(NAME_RECORD); + bytesRead = f.read((char*)&ttRecord, bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + ttRecord.nameID = qFromBigEndian(ttRecord.nameID); + if (ttRecord.nameID == 1) { + ttRecord.stringLength = qFromBigEndian(ttRecord.stringLength); + ttRecord.stringOffset = qFromBigEndian(ttRecord.stringOffset); + int nPos = f.pos(); + f.seek(tblDir.offset + ttRecord.stringOffset + ttNTHeader.storageOffset); + + QByteArray nameByteArray = f.read(ttRecord.stringLength); + if (!nameByteArray.isEmpty()) { + if (ttRecord.encodingID == 256 || ttRecord.encodingID == 768) { + //This is UTF-16 in big endian + int stringLength = ttRecord.stringLength / 2; + retVal.resize(stringLength); + QChar *data = retVal.data(); + const ushort *srcData = (const ushort *)nameByteArray.data(); + for (int i = 0; i < stringLength; ++i) + data[i] = qFromBigEndian(srcData[i]); + return retVal; + } else if (ttRecord.encodingID == 0) { + //This is Latin1 + retVal = QString::fromLatin1(nameByteArray); + } else { + qWarning("Could not retrieve Font name from file: %s", qPrintable(QDir::toNativeSeparators(filename))); + } + break; + } + f.seek(nPos); + } + } + } + f.close(); + } + return retVal; +} + +static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); } +static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); } +static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); } + +static QString findFontFile(const QString &faceName) +{ + static QHash<QString, QString> fontCache; + + if (fontCache.isEmpty()) { + QSettings settings(QSettings::SystemScope, fontSettingsOrganization(), fontSettingsApplication()); + settings.beginGroup(fontSettingsGroup()); + foreach (const QString &fontName, settings.allKeys()) + fontCache.insert(fontName, settings.value(fontName).toString()); + settings.endGroup(); + } + + QString value = fontCache.value(faceName); + + //Fallback if we haven't cached the font yet or the font got removed/renamed iterate again over all fonts + if (value.isEmpty() || !QFile::exists(value)) { + QSettings settings(QSettings::SystemScope, fontSettingsOrganization(), fontSettingsApplication()); + settings.beginGroup(fontSettingsGroup()); + + //empty the cache first, as it seems that it is dirty + settings.remove(QString()); + + QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System); + + while (it.hasNext()) { + const QString fontFile = it.next(); + const QString fontName = fontNameFromTTFile(fontFile); + if (fontName.isEmpty()) + continue; + fontCache.insert(fontName, fontFile); + settings.setValue(fontName, fontFile); + + if (localizedName(fontName)) { + QString englishFontName = getEnglishName(fontName); + fontCache.insert(englishFontName, fontFile); + settings.setValue(englishFontName, fontFile); + } + } + settings.endGroup(); + value = fontCache.value(faceName); + } + return value; +} +#endif // Q_OS_WINCE + +static bool addFontToDatabase(const QString &faceName, + const QString &fullName, + uchar charSet, const TEXTMETRIC *textmetric, const FONTSIGNATURE *signature, - int type) + int type, + bool registerAlias) { - typedef QPair<QString, QStringList> FontKey; - // the "@family" fonts are just the same as "family". Ignore them. - if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_"))) + if (faceName.isEmpty() || faceName.at(0) == QLatin1Char('@') || faceName.startsWith(QLatin1String("WST_"))) return false; - const int separatorPos = familyName.indexOf(QStringLiteral("::")); - const QString faceName = - separatorPos != -1 ? familyName.left(separatorPos) : familyName; - const QString fullName = - separatorPos != -1 ? familyName.mid(separatorPos + 2) : QString(); static const int SMOOTH_SCALABLE = 0xffff; const QString foundryName; // No such concept. const NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; @@ -139,14 +352,14 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; const bool antialias = false; - const QFont::Weight weight = weightFromInteger(tm->tmWeight); + const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; #ifndef QT_NO_DEBUG_OUTPUT if (QWindowsContext::verbose > 2) { QString message; QTextStream str(&message); - str << __FUNCTION__ << ' ' << familyName << ' ' << charSet << " TTF=" << ttf; + str << __FUNCTION__ << ' ' << faceName << "::" << fullName << ' ' << charSet << " TTF=" << ttf; if (type & DEVICE_FONTTYPE) str << " DEVICE"; if (type & RASTER_FONTTYPE) @@ -161,7 +374,7 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, #endif QString englishName; - if (ttf && localizedName(faceName)) + if (registerAlias & ttf && localizedName(faceName)) englishName = getEnglishName(faceName); QSupportedWritingSystems writingSystems; @@ -189,93 +402,19 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, writingSystems.setSupported(ws); } -#ifndef Q_OS_WINCE - const QSettings fontRegistry(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), - QSettings::NativeFormat); - - static QVector<FontKey> allFonts; - if (allFonts.isEmpty()) { - const QStringList allKeys = fontRegistry.allKeys(); - allFonts.reserve(allKeys.size()); - const QString trueType = QStringLiteral("(TrueType)"); - const QRegExp sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); - foreach (const QString &key, allKeys) { - QString realKey = key; - realKey.remove(trueType); - realKey.remove(sizeListMatch); - QStringList fonts; - const QStringList fontNames = realKey.trimmed().split(QLatin1Char('&')); - foreach (const QString &fontName, fontNames) - fonts.push_back(fontName.trimmed()); - allFonts.push_back(FontKey(key, fonts)); - } - } - - QString value; int index = 0; - for (int k = 0; k < allFonts.size(); ++k) { - const FontKey &fontKey = allFonts.at(k); - for (int i = 0; i < fontKey.second.length(); ++i) { - const QString &font = fontKey.second.at(i); - if (font == faceName || fullName == font || englishName == font) { - value = fontRegistry.value(fontKey.first).toString(); - index = i; - break; - } - } - if (!value.isEmpty()) - break; +#ifndef Q_OS_WINCE + const FontKey *key = findFontKey(faceName, &index); + if (!key) { + key = findFontKey(fullName, &index); + if (!key && !englishName.isEmpty()) + key = findFontKey(englishName, &index); + if (!key) + return false; } + QString value = key->fileName; #else - QString value; - int index = 0; - - static QHash<QString, QString> fontCache; - - if (fontCache.isEmpty()) { - QSettings settings(QSettings::SystemScope, QStringLiteral("Qt-Project"), QStringLiteral("Qtbase")); - settings.beginGroup(QStringLiteral("CEFontCache")); - - foreach (const QString &fontName, settings.allKeys()) { - const QString fontFileName = settings.value(fontName).toString(); - fontCache.insert(fontName, fontFileName); - } - - settings.endGroup(); // CEFontCache - } - - value = fontCache.value(faceName); - - //Fallback if we haven't cached the font yet or the font got removed/renamed iterate again over all fonts - if (value.isEmpty() || !QFile::exists(value)) { - QSettings settings(QSettings::SystemScope, QStringLiteral("Qt-Project"), QStringLiteral("Qtbase")); - settings.beginGroup(QStringLiteral("CEFontCache")); - - //empty the cache first, as it seems that it is dirty - foreach (const QString &fontName, settings.allKeys()) - settings.remove(fontName); - - QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System); - - while (it.hasNext()) { - const QString fontFile = it.next(); - const QString fontName = QBasicFontDatabase::fontNameFromTTFile(fontFile); - if (fontName.isEmpty()) - continue; - fontCache.insert(fontName, fontFile); - settings.setValue(fontName, fontFile); - - if (localizedName(fontName)) { - QString englishFontName = getEnglishName(fontName); - fontCache.insert(englishFontName, fontFile); - settings.setValue(englishFontName, fontFile); - } - } - - value = fontCache.value(faceName); - - settings.endGroup(); // CEFontCache - } + QString value = findFontFile(faceName); #endif if (value.isEmpty()) @@ -329,62 +468,23 @@ static QByteArray getFntTable(HFONT hfont, uint tag) #endif static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, - int type, LPARAM namesSetIn) + int type, LPARAM) { - typedef QSet<QString> StringSet; - const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName) - + QStringLiteral("::") - + QString::fromWCharArray(f->elfFullName); + + const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName); + const QString fullName = QString::fromWCharArray(f->elfFullName); const uchar charSet = f->elfLogFont.lfCharSet; -#ifndef Q_OS_WINCE const FONTSIGNATURE signature = textmetric->ntmFontSig; -#else - FONTSIGNATURE signature; - QByteArray table; - - if (type & TRUETYPE_FONTTYPE) { - HFONT hfont = CreateFontIndirect(&f->elfLogFont); - table = getFntTable(hfont, MAKE_TAG('O', 'S', '/', '2')); - DeleteObject((HGDIOBJ)hfont); - } - - if (table.length() >= 86) { - // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec - uchar *tableData = reinterpret_cast<uchar *>(table.data()); - - signature.fsUsb[0] = qFromBigEndian<quint32>(tableData + 42); - signature.fsUsb[1] = qFromBigEndian<quint32>(tableData + 46); - signature.fsUsb[2] = qFromBigEndian<quint32>(tableData + 50); - signature.fsUsb[3] = qFromBigEndian<quint32>(tableData + 54); - - signature.fsCsb[0] = qFromBigEndian<quint32>(tableData + 78); - signature.fsCsb[1] = qFromBigEndian<quint32>(tableData + 82); - } else { - memset(&signature, 0, sizeof(signature)); - } -#endif - // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is // identical to a TEXTMETRIC except for the last four members, which we don't use // anyway - if (addFontToDatabase(familyName, charSet, (TEXTMETRIC *)textmetric, &signature, type)) - reinterpret_cast<StringSet *>(namesSetIn)->insert(familyName); + addFontToDatabase(faceName, fullName, charSet, (TEXTMETRIC *)textmetric, &signature, type, false); // keep on enumerating return 1; } -void QWindowsFontDatabaseFT::populateFontDatabase() -{ - m_families.clear(); - populate(); // Called multiple times. - // Work around EnumFontFamiliesEx() not listing the system font, see below. - const QString sysFontFamily = QGuiApplication::font().family(); - if (!m_families.contains(sysFontFamily)) - populate(sysFontFamily); -} - /*! \brief Populate font database using EnumFontFamiliesEx(). @@ -393,26 +493,157 @@ void QWindowsFontDatabaseFT::populateFontDatabase() are only found when specifying the name explicitly. */ -void QWindowsFontDatabaseFT::populate(const QString &family) - { +void QWindowsFontDatabaseFT::populateFamily(const QString &familyName) +{ + qCDebug(lcQpaFonts) << familyName; + if (familyName.size() >= LF_FACESIZE) { + qCWarning(lcQpaFonts) << "Unable to enumerate family '" << familyName << '\''; + return; + } + HDC dummy = GetDC(0); + LOGFONT lf; + lf.lfCharSet = DEFAULT_CHARSET; + familyName.toWCharArray(lf.lfFaceName); + lf.lfFaceName[familyName.size()] = 0; + lf.lfPitchAndFamily = 0; + EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)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 - qCDebug(lcQpaFonts) << __FUNCTION__ << m_families.size() << family; +#ifndef Q_OS_WINCE + +// Delayed population of font families + +static int QT_WIN_CALLBACK populateFontFamilies(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *tm, int, LPARAM lparam) +{ + // the "@family" fonts are just the same as "family". Ignore them. + const wchar_t *faceNameW = f->elfLogFont.lfFaceName; + if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) { + // Register only font families for which a font file exists for delayed population + const QString faceName = QString::fromWCharArray(faceNameW); + const FontKey *key = findFontKey(faceName); + if (!key) { + key = findFontKey(QString::fromWCharArray(f->elfFullName)); + if (!key && (tm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE) && localizedName(faceName)) + key = findFontKey(getEnglishName(faceName)); + } + 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 + const bool ttf = (tm->ntmTm.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 +} +void QWindowsFontDatabaseFT::populateFontDatabase() +{ HDC dummy = GetDC(0); LOGFONT lf; lf.lfCharSet = DEFAULT_CHARSET; - if (family.size() >= LF_FACESIZE) { - qWarning("%s: Unable to enumerate family '%s'.", - __FUNCTION__, qPrintable(family)); - return; + lf.lfFaceName[0] = 0; + lf.lfPitchAndFamily = 0; + PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family()); + EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)populateFontFamilies, reinterpret_cast<LPARAM>(&context), 0); + ReleaseDC(0, dummy); + // Work around EnumFontFamiliesEx() not listing the system font + if (!context.seenSystemDefaultFont) + QPlatformFontDatabase::registerFontFamily(context.systemDefaultFont); +} + +#else // !Q_OS_WINCE + +// Non-delayed population of fonts (Windows CE). + +static int QT_WIN_CALLBACK populateFontCe(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, + int type, LPARAM lparam) +{ + // the "@family" fonts are just the same as "family". Ignore them. + const wchar_t *faceNameW = f->elfLogFont.lfFaceName; + if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) { + const uchar charSet = f->elfLogFont.lfCharSet; + + FONTSIGNATURE signature; + QByteArray table; + + if (type & TRUETYPE_FONTTYPE) { + HFONT hfont = CreateFontIndirect(&f->elfLogFont); + table = getFntTable(hfont, MAKE_TAG('O', 'S', '/', '2')); + DeleteObject((HGDIOBJ)hfont); + } + + if (table.length() >= 86) { + // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec + uchar *tableData = reinterpret_cast<uchar *>(table.data()); + + signature.fsUsb[0] = qFromBigEndian<quint32>(tableData + 42); + signature.fsUsb[1] = qFromBigEndian<quint32>(tableData + 46); + signature.fsUsb[2] = qFromBigEndian<quint32>(tableData + 50); + signature.fsUsb[3] = qFromBigEndian<quint32>(tableData + 54); + + signature.fsCsb[0] = qFromBigEndian<quint32>(tableData + 78); + signature.fsCsb[1] = qFromBigEndian<quint32>(tableData + 82); + } else { + memset(&signature, 0, sizeof(signature)); + } + + // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is + // identical to a TEXTMETRIC except for the last four members, which we don't use + // anyway + const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName); + if (addFontToDatabase(faceName, QString::fromWCharArray(f->elfFullName), + charSet, (TEXTMETRIC *)textmetric, &signature, type, true)) { + PopulateFamiliesContext *context = reinterpret_cast<PopulateFamiliesContext *>(lparam); + if (!context->seenSystemDefaultFont && faceName == context->systemDefaultFont) + context->seenSystemDefaultFont = true; + } } - wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()), - family.size() + 1); + + // keep on enumerating + return 1; +} + +void QWindowsFontDatabaseFT::populateFontDatabase() +{ + LOGFONT lf; + lf.lfCharSet = DEFAULT_CHARSET; + HDC dummy = GetDC(0); + lf.lfFaceName[0] = 0; lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, - (LPARAM)&m_families, 0); + PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family()); + EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)populateFontCe, reinterpret_cast<LPARAM>(&context), 0); ReleaseDC(0, dummy); + // Work around EnumFontFamiliesEx() not listing the system font, see below. + if (!context.seenSystemDefaultFont) + populateFamily(context.systemDefaultFont); } +#endif // Q_OS_WINCE QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle) { @@ -449,7 +680,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint - << script << result << m_families; + << script << result; return result; } |