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:
parent
87b20009cc
commit
3ccdeb4b58
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user