Remove specialized multi font engine on Windows

This was added as a platform-specific implementation of the multi engine
in 2005, before this code was generalized, and it currently only has the purpose
of special handling loadEngine().

The way this was special handled was by creating a new QFontEngine for every
fallback family *every* time, never checking if the font engine already exists
in the cache (like the superclass implementation does). The result of this was
that if you had 500 fonts and each of them had 500 fallback fonts, and made
a loop that would load all of them, then you would get 250000 font engines.
At some point before this, we would run out of available handles and crash.

There shouldn't be any need to have special handling of fallback font loading
on Windows (i.e. all the platform specific parts should go through the normal
mechanisms in QPA), so lets just go through the superclass implementation instead.

[ChangeLog][Windows][Text] Reduced the number of font engines that are
created when loading new fonts, fixing crashes in some special cases where
a large number of fonts are created during a short period of time.

Fixes: QTBUG-70032
Change-Id: I05040dd458e820510685e8c6df8f31876d9bdb89
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2018-12-12 11:54:54 +01:00
parent 87b20009cc
commit 3ccdeb4b58
4 changed files with 0 additions and 130 deletions

View File

@ -1264,11 +1264,6 @@ QWindowsFontDatabase::~QWindowsFontDatabase()
removeApplicationFonts();
}
QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
{
return new QWindowsMultiFontEngine(fontEngine, script);
}
QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
const QString faceName(static_cast<const QChar*>(handle));

View File

@ -98,7 +98,6 @@ public:
void populateFontDatabase() override;
void populateFamily(const QString &familyName) override;
QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) override;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override;

View File

@ -1199,120 +1199,6 @@ void QWindowsFontEngine::initFontInfo(const QFontDef &request,
}
}
/*!
\class QWindowsMultiFontEngine
\brief Standard Windows Multi font engine.
\internal
\ingroup qt-lighthouse-win
"Merges" several font engines that have gaps in the
supported writing systems.
Will probably be superseded by a common Free Type font engine in Qt 5.X.
*/
QWindowsMultiFontEngine::QWindowsMultiFontEngine(QFontEngine *fe, int script)
: QFontEngineMulti(fe, script)
{
}
#ifndef QT_NO_DIRECTWRITE
static QString msgDirectWriteFunctionFailed(HRESULT hr, const char *function,
const QString &fam, const QString &substitute)
{
_com_error error(hr);
QString result;
QTextStream str(&result);
str << function << " failed for \"" << fam << '"';
if (substitute != fam)
str << " (substitute: \"" << substitute << "\")";
str << ": error " << hex << showbase << ulong(hr) << ' ' << noshowbase << dec
<< ": " << QString::fromWCharArray(error.ErrorMessage());
return result;
}
#endif // !QT_NO_DIRECTWRITE
QFontEngine *QWindowsMultiFontEngine::loadEngine(int at)
{
QFontEngine *fontEngine = engine(0);
QSharedPointer<QWindowsFontEngineData> data;
LOGFONT lf;
#ifndef QT_NO_DIRECTWRITE
if (fontEngine->type() == QFontEngine::DirectWrite) {
QWindowsFontEngineDirectWrite *fe = static_cast<QWindowsFontEngineDirectWrite *>(fontEngine);
lf = QWindowsFontDatabase::fontDefToLOGFONT(fe->fontDef, QString());
data = fe->fontEngineData();
} else
#endif
{
QWindowsFontEngine *fe = static_cast<QWindowsFontEngine*>(fontEngine);
lf = fe->m_logfont;
data = fe->fontEngineData();
}
const QString fam = fallbackFamilyAt(at - 1);
const int faceNameLength = qMin(fam.length(), LF_FACESIZE - 1);
memcpy(lf.lfFaceName, fam.utf16(), faceNameLength * sizeof(wchar_t));
lf.lfFaceName[faceNameLength] = 0;
#ifndef QT_NO_DIRECTWRITE
if (fontEngine->type() == QFontEngine::DirectWrite) {
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam);
if (nameSubstitute != fam) {
const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1);
memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t));
lf.lfFaceName[nameSubstituteLength] = 0;
}
HFONT hfont = CreateFontIndirect(&lf);
if (hfont == nullptr) {
qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__);
} else {
HGDIOBJ oldFont = SelectObject(data->hdc, hfont);
IDWriteFontFace *directWriteFontFace = nullptr;
QWindowsFontEngineDirectWrite *fedw = nullptr;
HRESULT hr = data->directWriteGdiInterop->CreateFontFaceFromHdc(data->hdc, &directWriteFontFace);
if (SUCCEEDED(hr)) {
Q_ASSERT(directWriteFontFace);
fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
fontEngine->fontDef.pixelSize,
data);
fedw->fontDef.weight = fontEngine->fontDef.weight;
if (fontEngine->fontDef.style > QFont::StyleNormal)
fedw->fontDef.style = fontEngine->fontDef.style;
fedw->fontDef.family = fam;
fedw->fontDef.hintingPreference = fontEngine->fontDef.hintingPreference;
fedw->fontDef.stretch = fontEngine->fontDef.stretch;
} else {
qWarning("%s: %s", __FUNCTION__,
qPrintable(msgDirectWriteFunctionFailed(hr, "CreateFontFace", fam, nameSubstitute)));
}
SelectObject(data->hdc, oldFont);
DeleteObject(hfont);
if (fedw != nullptr)
return fedw;
}
}
#endif
// Get here if original font is not DirectWrite or DirectWrite creation failed for some
// reason
QFontEngine *fe = new QWindowsFontEngine(fam, lf, data);
fe->fontDef.weight = fontEngine->fontDef.weight;
if (fontEngine->fontDef.style > QFont::StyleNormal)
fe->fontDef.style = fontEngine->fontDef.style;
fe->fontDef.family = fam;
fe->fontDef.hintingPreference = fontEngine->fontDef.hintingPreference;
fe->fontDef.stretch = fontEngine->fontDef.stretch;
return fe;
}
bool QWindowsFontEngine::supportsTransformation(const QTransform &transform) const
{
// Support all transformations for ttf files, and translations for raster fonts

View File

@ -67,8 +67,6 @@ class QWindowsFontEngineData;
class QWindowsFontEngine : public QFontEngine
{
Q_DISABLE_COPY(QWindowsFontEngine)
friend class QWindowsMultiFontEngine;
public:
QWindowsFontEngine(const QString &name, LOGFONT lf,
const QSharedPointer<QWindowsFontEngineData> &fontEngineData);
@ -169,14 +167,6 @@ private:
mutable int designAdvancesSize = 0;
};
class QWindowsMultiFontEngine : public QFontEngineMulti
{
public:
explicit QWindowsMultiFontEngine(QFontEngine *fe, int script);
QFontEngine *loadEngine(int at) override;
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(HFONT)