Fix application fonts with DirectWrite font engine

There is no way to add fonts to the system font collection with
DirectWrite. Instead you have to write custom collections. But
that would mean keeping two instances of the same font data in
memory since we are already registering them for the GDI engine,
and we have no way of knowing which engine will be used. When
we at some point replace the GDI engine completely, we could
implement this in the proper way, but for now, instead of looking
up the equivalent to the LOGFONT in DirectWrite's system font
collection, we look it up using GDI and then convert the HFONT
to DirectWrite.

[ChangeLog][Windows][Text] Fixed disabling hinting for application
fonts, e.g. when automatic scaling by device pixel ratio is in
effect.

Task-number: QTBUG-18711
Change-Id: I5c1365ab956dfa23d4d687877d7440473ee03bb0
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
bb10
Eskil Abrahamsen Blomfeldt 2016-03-04 11:44:05 +01:00
parent 273ddd5b23
commit 21c7421d4e
3 changed files with 19 additions and 72 deletions

View File

@ -1762,28 +1762,35 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request,
lf.lfFaceName[nameSubstituteLength] = 0;
}
IDWriteFont *directWriteFont = 0;
HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont);
if (FAILED(hr)) {
const QString errorString = qt_error_string(int(hr));
qWarning().noquote().nospace() << "DirectWrite: CreateFontFromLOGFONT() failed ("
<< errorString << ") for " << request << ' ' << lf << " dpi=" << dpi;
HFONT hfont = CreateFontIndirect(&lf);
if (!hfont) {
qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__);
} else {
HGDIOBJ oldFont = SelectObject(data->hdc, hfont);
IDWriteFontFace *directWriteFontFace = NULL;
hr = directWriteFont->CreateFontFace(&directWriteFontFace);
HRESULT hr = data->directWriteGdiInterop->CreateFontFaceFromHdc(data->hdc, &directWriteFontFace);
if (FAILED(hr)) {
const QString errorString = qt_error_string(int(hr));
qWarning().noquote() << "DirectWrite: CreateFontFace() failed ("
qWarning().noquote().nospace() << "DirectWrite: CreateFontFaceFromHDC() failed ("
<< errorString << ") for " << request << ' ' << lf << " dpi=" << dpi;
} else {
QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
request.pixelSize,
data);
fedw->initFontInfo(request, dpi, directWriteFont);
wchar_t n[64];
GetTextFace(data->hdc, 64, n);
QFontDef fontDef = request;
fontDef.family = QString::fromWCharArray(n);
fedw->initFontInfo(fontDef, dpi);
fe = fedw;
}
directWriteFont->Release();
SelectObject(data->hdc, oldFont);
DeleteObject(hfont);
}
}
#endif // QT_NO_DIRECTWRITE

View File

@ -648,71 +648,11 @@ QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const
return fontEngine;
}
// Dynamically resolve GetUserDefaultLocaleName, which is available from Windows
// Vista onwards. ### fixme 5.7: Consider reverting to direct linking.
typedef int (WINAPI *GetUserDefaultLocaleNamePtr)(LPWSTR, int);
static inline GetUserDefaultLocaleNamePtr resolveGetUserDefaultLocaleName()
{
QSystemLibrary library(QStringLiteral("kernel32"));
return (GetUserDefaultLocaleNamePtr)library.resolve("GetUserDefaultLocaleName");
}
void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request,
int dpi, IDWriteFont *font)
int dpi)
{
fontDef = request;
IDWriteFontFamily *fontFamily = NULL;
HRESULT hr = font->GetFontFamily(&fontFamily);
IDWriteLocalizedStrings *familyNames = NULL;
if (SUCCEEDED(hr))
hr = fontFamily->GetFamilyNames(&familyNames);
UINT32 index = 0;
if (SUCCEEDED(hr)) {
BOOL exists = false;
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
static const GetUserDefaultLocaleNamePtr getUserDefaultLocaleName = resolveGetUserDefaultLocaleName();
const int defaultLocaleSuccess = getUserDefaultLocaleName
? getUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) : 0;
if (defaultLocaleSuccess)
hr = familyNames->FindLocaleName(localeName, &index, &exists);
if (SUCCEEDED(hr) && !exists)
hr = familyNames->FindLocaleName(L"en-us", &index, &exists);
if (!exists)
index = 0;
}
// Get the family name.
if (SUCCEEDED(hr)) {
UINT32 length = 0;
hr = familyNames->GetStringLength(index, &length);
if (SUCCEEDED(hr)) {
QVarLengthArray<wchar_t, 128> name(length+1);
hr = familyNames->GetString(index, name.data(), name.size());
if (SUCCEEDED(hr))
fontDef.family = QString::fromWCharArray(name.constData());
}
}
if (familyNames != NULL)
familyNames->Release();
if (fontFamily)
fontFamily->Release();
if (FAILED(hr))
qErrnoWarning(hr, "initFontInfo: Failed to get family name");
if (fontDef.pointSize < 0)
fontDef.pointSize = fontDef.pixelSize * 72. / dpi;
else if (fontDef.pixelSize == -1)

View File

@ -59,7 +59,7 @@ public:
const QSharedPointer<QWindowsFontEngineData> &d);
~QWindowsFontEngineDirectWrite();
void initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font);
void initFontInfo(const QFontDef &request, int dpi);
QFixed lineThickness() const Q_DECL_OVERRIDE;
QFixed underlinePosition() const Q_DECL_OVERRIDE;