WinRT: Use registerFontFamily to reduce font registration overhead

Adopt to the new lazy font loading strategy in order to reduce memory
and startup time associated with populating the entire font database.

Change-Id: I0134cc123f73cb8485fe85c4a6b8e3b3a3a2cab0
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
This commit is contained in:
Andrew Knight 2014-03-26 13:22:00 +02:00 committed by The Qt Project
parent 071098b08b
commit 244e2ef7b9
2 changed files with 192 additions and 162 deletions

View File

@ -63,7 +63,7 @@ QString QWinRTFontDatabase::fontDir() const
fontDirectory = applicationDirPath + QLatin1String("/fonts"); fontDirectory = applicationDirPath + QLatin1String("/fonts");
if (!QFile::exists(fontDirectory)) { if (!QFile::exists(fontDirectory)) {
#ifndef Q_OS_WINPHONE #ifndef Q_OS_WINPHONE
if (m_fonts.isEmpty()) if (m_fontFamilies.isEmpty())
#endif #endif
qWarning("No fonts directory found in application package."); qWarning("No fonts directory found in application package.");
fontDirectory = applicationDirPath; fontDirectory = applicationDirPath;
@ -78,6 +78,9 @@ QWinRTFontDatabase::~QWinRTFontDatabase()
{ {
foreach (IDWriteFontFile *fontFile, m_fonts.keys()) foreach (IDWriteFontFile *fontFile, m_fonts.keys())
fontFile->Release(); fontFile->Release();
foreach (IDWriteFontFamily *fontFamily, m_fontFamilies)
fontFamily->Release();
} }
QFont QWinRTFontDatabase::defaultFont() const QFont QWinRTFontDatabase::defaultFont() const
@ -132,15 +135,36 @@ void QWinRTFontDatabase::populateFontDatabase()
} }
QString familyName = QString::fromWCharArray(familyBuffer.data(), familyNameLength); QString familyName = QString::fromWCharArray(familyBuffer.data(), familyNameLength);
int fontCount = fontFamily->GetFontCount(); m_fontFamilies.insert(familyName, fontFamily.Detach());
registerFontFamily(familyName);
}
QBasicFontDatabase::populateFontDatabase();
}
void QWinRTFontDatabase::populateFamily(const QString &familyName)
{
IDWriteFontFamily *fontFamily = m_fontFamilies.value(familyName);
if (!fontFamily) {
qWarning("The font family %s was not found.", qPrintable(familyName));
return;
}
bool fontRegistered = false;
const int fontCount = fontFamily->GetFontCount();
for (int j = 0; j < fontCount; ++j) { for (int j = 0; j < fontCount; ++j) {
ComPtr<IDWriteFont> font; ComPtr<IDWriteFont> font;
hr = fontFamily->GetFont(j, &font); HRESULT hr = fontFamily->GetFont(j, &font);
if (FAILED(hr)) { if (FAILED(hr)) {
qWarning("Unable to get base font: %s", qPrintable(qt_error_string(hr))); qWarning("Unable to get font: %s", qPrintable(qt_error_string(hr)));
continue; continue;
} }
// Skip simulated faces
if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE)
continue;
ComPtr<IDWriteFontFace> baseFontFace; ComPtr<IDWriteFontFace> baseFontFace;
hr = font->CreateFontFace(&baseFontFace); hr = font->CreateFontFace(&baseFontFace);
if (FAILED(hr)) { if (FAILED(hr)) {
@ -154,13 +178,6 @@ void QWinRTFontDatabase::populateFontDatabase()
continue; continue;
} }
// Only try to load true-type fonts
DWRITE_FONT_FACE_TYPE type = fontFace->GetType();
if (!(type == DWRITE_FONT_FACE_TYPE_TRUETYPE
|| type == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)) {
continue;
}
// We can't deal with multi-file fonts // We can't deal with multi-file fonts
quint32 fileCount; quint32 fileCount;
hr = fontFace->GetFiles(&fileCount, NULL); hr = fontFace->GetFiles(&fileCount, NULL);
@ -168,7 +185,7 @@ void QWinRTFontDatabase::populateFontDatabase()
qWarning("Unable to get font file count: %s", qPrintable(qt_error_string(hr))); qWarning("Unable to get font file count: %s", qPrintable(qt_error_string(hr)));
continue; continue;
} }
if (fileCount != 1) // Should not happen as we only look at TT fonts if (fileCount != 1)
continue; continue;
ComPtr<IDWriteLocalizedStrings> informationalStrings; ComPtr<IDWriteLocalizedStrings> informationalStrings;
@ -293,14 +310,21 @@ void QWinRTFontDatabase::populateFontDatabase()
m_fonts.insert(fontFile, description); m_fonts.insert(fontFile, description);
registerFont(familyName, QString(), foundryName, weight, style, stretch, registerFont(familyName, QString(), foundryName, weight, style, stretch,
true, true, 0, fixedPitch, writingSystems, fontFile); true, true, 0, fixedPitch, writingSystems, fontFile);
} fontRegistered = true;
} }
QBasicFontDatabase::populateFontDatabase(); // Always populate something to avoid an assert
if (!fontRegistered) {
registerFont(familyName, QString(), QString(), QFont::Normal, QFont::StyleNormal,
QFont::Unstretched, false, false, 0, false, QSupportedWritingSystems(), 0);
}
} }
QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{ {
if (!handle) // Happens if a font family population failed
return 0;
IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle); IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle);
if (!m_fonts.contains(fontFile)) if (!m_fonts.contains(fontFile))
return QBasicFontDatabase::fontEngine(fontDef, handle); return QBasicFontDatabase::fontEngine(fontDef, handle);
@ -361,6 +385,9 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl
void QWinRTFontDatabase::releaseHandle(void *handle) void QWinRTFontDatabase::releaseHandle(void *handle)
{ {
if (!handle)
return;
IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle); IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle);
if (m_fonts.contains(fontFile)) { if (m_fonts.contains(fontFile)) {
m_fonts.remove(fontFile); m_fonts.remove(fontFile);

View File

@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE
#ifndef Q_OS_WINPHONE #ifndef Q_OS_WINPHONE
struct IDWriteFontFile; struct IDWriteFontFile;
struct IDWriteFontFamily;
struct FontDescription struct FontDescription
{ {
@ -64,10 +65,12 @@ public:
~QWinRTFontDatabase(); ~QWinRTFontDatabase();
QFont defaultFont() const Q_DECL_OVERRIDE; QFont defaultFont() const Q_DECL_OVERRIDE;
void populateFontDatabase() Q_DECL_OVERRIDE; void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
void releaseHandle(void *handle) Q_DECL_OVERRIDE; void releaseHandle(void *handle) Q_DECL_OVERRIDE;
private: private:
QHash<IDWriteFontFile *, FontDescription> m_fonts; QHash<IDWriteFontFile *, FontDescription> m_fonts;
QHash<QString, IDWriteFontFamily *> m_fontFamilies;
#endif // !Q_OS_WINPHONE #endif // !Q_OS_WINPHONE
}; };