summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2012-03-23 14:17:23 +0200
committerQt by Nokia <qt-info@nokia.com>2012-03-27 17:06:59 +0200
commit4f1820e3a77b3fdda32a1b935502b187e73059cf (patch)
treeb4547ee03c9ba6257ad51134f689ad466eebae30 /src/plugins/platforms
parentd41e0564f5f6a002ca2cdb0d745de8e75247ea99 (diff)
Implement application font loading for Windows
For FreeType Windows font database, use the application font loading implementation of the parent class. For native Windows font database, the implementation was adapted from Qt 4.8. Also fixed a bug in font database population, where old data was not destroyed before population, resulting in fonts not getting properly repopulated when a new font was added. Task-number: QTBUG-24193 Task-number: QTBUG-24195 Task-number: QTBUG-24196 Change-Id: Ie224a87baf7500b9867aaafa807f62dd4503dee8 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp173
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp23
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h1
4 files changed, 177 insertions, 28 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 7d0bd53e8b..c1c25dd686 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -51,6 +51,7 @@
#include <QtCore/qmath.h>
#include <QtCore/QDebug>
+#include <QtCore/QtEndian>
#include <wchar.h>
@@ -618,14 +619,14 @@ static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric,
void QWindowsFontDatabase::populateFontDatabase()
{
- if (m_families.isEmpty()) {
- QPlatformFontDatabase::populateFontDatabase();
- 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);
- }
+ m_families.clear();
+ removeApplicationFonts();
+ QPlatformFontDatabase::populateFontDatabase();
+ 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);
}
/*!
@@ -669,6 +670,7 @@ QWindowsFontDatabase::QWindowsFontDatabase() :
QWindowsFontDatabase::~QWindowsFontDatabase()
{
+ removeApplicationFonts();
}
QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef,
@@ -702,11 +704,160 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString family, const
return result;
}
+static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData)
+{
+ QList<quint32> offsets;
+ const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData);
+ if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) {
+ if (headerTag != MAKE_TAG(0, 1, 0, 0)
+ && headerTag != MAKE_TAG('O', 'T', 'T', 'O')
+ && headerTag != MAKE_TAG('t', 'r', 'u', 'e')
+ && headerTag != MAKE_TAG('t', 'y', 'p', '1'))
+ return offsets;
+ offsets << 0;
+ return offsets;
+ }
+ const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8);
+ for (uint i = 0; i < numFonts; ++i) {
+ offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4);
+ }
+ return offsets;
+}
+
+static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
+{
+ const quint16 numTables = qFromBigEndian<quint16>(data + 4);
+ for (uint i = 0; i < numTables; ++i) {
+ const quint32 offset = 12 + 16 * i;
+ if (*reinterpret_cast<const quint32 *>(data + offset) == tag) {
+ *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8);
+ *length = qFromBigEndian<quint32>(data + offset + 12);
+ return;
+ }
+ }
+ *table = 0;
+ *length = 0;
+ return;
+}
+
+static void getFamiliesAndSignatures(const QByteArray &fontData,
+ QStringList *families,
+ QVector<FONTSIGNATURE> *signatures)
+{
+ const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
+
+ QList<quint32> offsets = getTrueTypeFontOffsets(data);
+ if (offsets.isEmpty())
+ return;
+
+ for (int i = 0; i < offsets.count(); ++i) {
+ const uchar *font = data + offsets.at(i);
+ const uchar *table;
+ quint32 length;
+ getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
+ if (!table)
+ continue;
+ QString name = getEnglishName(table, length);
+ if (name.isEmpty())
+ continue;
+
+ families->append(name);
+
+ if (signatures) {
+ FONTSIGNATURE signature;
+ getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
+ if (table && length >= 86) {
+ // Offsets taken from OS/2 table in the TrueType spec
+ signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42);
+ signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46);
+ signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50);
+ signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54);
+
+ signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78);
+ signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82);
+ } else {
+ memset(&signature, 0, sizeof(signature));
+ }
+ signatures->append(signature);
+ }
+ }
+}
+
QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
{
- const QStringList result = QPlatformFontDatabase::addApplicationFont(fontData, fileName);
- Q_UNIMPLEMENTED();
- return result;
+ WinApplicationFont font;
+ font.fileName = fileName;
+ QVector<FONTSIGNATURE> signatures;
+ QStringList families;
+
+ if (!fontData.isEmpty()) {
+ getFamiliesAndSignatures(fontData, &families, &signatures);
+ if (families.isEmpty())
+ return families;
+
+ DWORD dummy = 0;
+ font.handle = AddFontMemResourceEx((void *)fontData.constData(), fontData.size(), 0,
+ &dummy);
+ if (font.handle == 0)
+ return QStringList();
+
+ // Memory fonts won't show up in enumeration, so do add them the hard way.
+ for (int j = 0; j < families.count(); ++j) {
+ const QString familyName = families.at(j);
+ HDC hdc = GetDC(0);
+ LOGFONT lf;
+ memset(&lf, 0, sizeof(LOGFONT));
+ memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size()));
+ lf.lfCharSet = DEFAULT_CHARSET;
+ HFONT hfont = CreateFontIndirect(&lf);
+ HGDIOBJ oldobj = SelectObject(hdc, hfont);
+
+ TEXTMETRIC textMetrics;
+ GetTextMetrics(hdc, &textMetrics);
+
+ addFontToDatabase(familyName, QString(), &textMetrics, &signatures.at(j),
+ TRUETYPE_FONTTYPE);
+
+ SelectObject(hdc, oldobj);
+ DeleteObject(hfont);
+ ReleaseDC(0, hdc);
+ }
+ } else {
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly))
+ return families;
+ QByteArray data = f.readAll();
+ f.close();
+
+ getFamiliesAndSignatures(data, &families, 0);
+ if (families.isEmpty())
+ return families;
+
+ if (AddFontResourceExW((wchar_t*)fileName.utf16(), FR_PRIVATE, 0) == 0)
+ return QStringList();
+
+ font.handle = 0;
+
+ // Fonts based on files are added via populate, as they will show up in font enumeration.
+ for (int j = 0; j < families.count(); ++j)
+ populate(families.at(j));
+ }
+
+ m_applicationFonts << font;
+
+ return families;
+}
+
+void QWindowsFontDatabase::removeApplicationFonts()
+{
+ foreach (const WinApplicationFont &font, m_applicationFonts) {
+ if (font.handle) {
+ RemoveFontMemResourceEx(font.handle);
+ } else {
+ RemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0);
+ }
+ }
+ m_applicationFonts.clear();
}
void QWindowsFontDatabase::releaseHandle(void *handle)
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index 774a203a55..2fa615253e 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -100,8 +100,16 @@ public:
private:
void populate(const QString &family = QString());
+ void removeApplicationFonts();
QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
QSet<QString> m_families;
+
+ struct WinApplicationFont {
+ HANDLE handle;
+ QString fileName;
+ };
+
+ QList<WinApplicationFont> m_applicationFonts;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index f90a880cd3..500a1eeccb 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -273,14 +273,13 @@ static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric,
void QWindowsFontDatabaseFT::populateFontDatabase()
{
- if (m_families.isEmpty()) {
- QPlatformFontDatabase::populateFontDatabase();
- 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);
- }
+ m_families.clear();
+ QPlatformFontDatabase::populateFontDatabase();
+ 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);
}
/*!
@@ -426,14 +425,6 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString family, con
<< script << result << m_families;
return result;
}
-
-QStringList QWindowsFontDatabaseFT::addApplicationFont(const QByteArray &fontData, const QString &fileName)
-{
- const QStringList result = QPlatformFontDatabase::addApplicationFont(fontData, fileName);
- Q_UNIMPLEMENTED();
- return result;
-}
-
QString QWindowsFontDatabaseFT::fontDir() const
{
const QString result = QLatin1String(qgetenv("windir")) + QLatin1String("/Fonts");//QPlatformFontDatabase::fontDir();
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index 24810c9202..bb55b68251 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -56,7 +56,6 @@ public:
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const;
- QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
virtual QString fontDir() const;
virtual QFont defaultFont() const;