Windows: Fix crash when loading color fonts from data

When color fonts are loaded from data, the font returned will
be a DirectWrite engine even the hinting preference does not
require it. This would cause a crash as we unconditionally cast
the pointer to QWindowsFontEngine*.

Using GDI and the unique family name hack to load the font from
data works fine, but we need to make sure we reference count
the font resource in this case, so we have to implement the
setUniqueFamilyName() logic in the DirectWrite engine as well
for this specific case.

[ChangeLog][Windows] Fixed crash when loading color fonts from
data.

Task-number: QTBUG-55595
Change-Id: I05443e8a396105da68ac4872b48339130b86c7f6
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
bb10
Eskil Abrahamsen Blomfeldt 2016-09-20 13:58:18 +02:00
parent 8cd28ea885
commit 6af82fe9fd
3 changed files with 35 additions and 5 deletions

View File

@ -1231,8 +1231,23 @@ QT_WARNING_POP
Q_ASSERT(fontEngine->ref.load() == 0);
// Override the generated font name
static_cast<QWindowsFontEngine *>(fontEngine)->setUniqueFamilyName(uniqueFamilyName);
fontEngine->fontDef.family = actualFontName;
switch (fontEngine->type()) {
case QFontEngine::Win:
static_cast<QWindowsFontEngine *>(fontEngine)->setUniqueFamilyName(uniqueFamilyName);
fontEngine->fontDef.family = actualFontName;
break;
#if !defined(QT_NO_DIRECTWRITE)
case QFontEngine::DirectWrite:
static_cast<QWindowsFontEngineDirectWrite *>(fontEngine)->setUniqueFamilyName(uniqueFamilyName);
fontEngine->fontDef.family = actualFontName;
break;
#endif // !QT_NO_DIRECTWRITE
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled font engine.");
}
UniqueFontData uniqueData;
uniqueData.handle = fontHandle;
uniqueData.refCount.ref();

View File

@ -48,6 +48,8 @@
#include <QtCore/QVarLengthArray>
#include <private/qstringiterator_p.h>
#include <QtCore/private/qsystemlibrary_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#if defined(QT_USE_DIRECTWRITE2)
# include <dwrite_2.h>
@ -233,6 +235,11 @@ QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite()
if (m_directWriteBitmapRenderTarget != 0)
m_directWriteBitmapRenderTarget->Release();
if (!m_uniqueFamilyName.isEmpty()) {
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
static_cast<QWindowsFontDatabase *>(pfdb)->derefUniqueFont(m_uniqueFamilyName);
}
}
void QWindowsFontEngineDirectWrite::collectMetrics()
@ -765,12 +772,17 @@ QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t,
QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const
{
QFontEngine *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace,
pixelSize,
m_fontEngineData);
QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace,
pixelSize,
m_fontEngineData);
fontEngine->fontDef = fontDef;
fontEngine->fontDef.pixelSize = pixelSize;
if (!m_uniqueFamilyName.isEmpty()) {
fontEngine->setUniqueFamilyName(m_uniqueFamilyName);
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
static_cast<QWindowsFontDatabase *>(pfdb)->refUniqueFont(m_uniqueFamilyName);
}
return fontEngine;
}

View File

@ -108,6 +108,8 @@ public:
IDWriteFontFace *directWriteFontFace() const { return m_directWriteFontFace; }
void setUniqueFamilyName(const QString &newName) { m_uniqueFamilyName = newName; }
private:
QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform);
void collectMetrics();
@ -126,6 +128,7 @@ private:
QFixed m_xHeight;
QFixed m_lineGap;
FaceId m_faceId;
QString m_uniqueFamilyName;
};
QT_END_NAMESPACE