Fix printing with unhinted fonts

On high-dpi displays or when you explicitly select an unhinted font,
we pick a DirectWrite font engine. This hit an uncovered code path
on Windows, because we relied on being able to get the HFONT from
the font engine.

To fix this, we introduce an alternative code path which gets the
HFONT based on the DirectWrite font when this font engine is active.

[ChangeLog][Windows] Fixed an issue where the characters in printed
text would look too small.

Fixes: QTBUG-95720
Change-Id: Ifd609e92512e1f25f0ee2aace35cb5ccedf09030
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
(cherry picked from commit 2f5695bed5660e32a41786d8b9ab6b4b0775caf1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2021-08-16 14:41:47 +02:00 committed by Qt Cherry-pick Bot
parent 8b50bc28f4
commit b4a1265b15
3 changed files with 55 additions and 3 deletions

View File

@ -337,6 +337,22 @@ QString QWindowsFontEngineDirectWrite::filenameFromFontFile(IDWriteFontFile *fon
return ret;
}
HFONT QWindowsFontEngineDirectWrite::createHFONT() const
{
if (m_fontEngineData == nullptr || m_directWriteFontFace == nullptr)
return NULL;
LOGFONT lf;
HRESULT hr = m_fontEngineData->directWriteGdiInterop->ConvertFontFaceToLOGFONT(m_directWriteFontFace,
&lf);
if (SUCCEEDED(hr)) {
lf.lfHeight = -qRound(fontDef.pixelSize);
return CreateFontIndirect(&lf);
} else {
return NULL;
}
}
void QWindowsFontEngineDirectWrite::initializeHeightMetrics() const
{
DWRITE_FONT_METRICS metrics;

View File

@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE
class QWindowsFontEngineData;
class QWindowsFontEngineDirectWrite : public QFontEngine
class Q_GUI_EXPORT QWindowsFontEngineDirectWrite : public QFontEngine
{
Q_DISABLE_COPY_MOVE(QWindowsFontEngineDirectWrite)
public:
@ -107,6 +107,8 @@ public:
bool supportsHorizontalSubPixelPositions() const override;
HFONT createHFONT() const;
QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition) override;
QImage alphaMapForGlyph(glyph_t glyph,
const QFixedPoint &subPixelPosition,

View File

@ -49,6 +49,9 @@
#include <private/qfont_p.h>
#include <private/qfontengine_p.h>
#include <private/qpainter_p.h>
#if QT_CONFIG(directwrite)
# include <private/qwindowsfontenginedirectwrite_p.h>
#endif
#include <qpa/qplatformprintplugin.h>
#include <qpa/qplatformprintersupport.h>
@ -290,8 +293,22 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
|| d->txop >= QTransform::TxProject
|| !d->embed_fonts;
if (!fallBack && ti.fontEngine->type() == QFontEngine::Win) {
if (HFONT hfont = static_cast<HFONT>(ti.fontEngine->handle())) {
if (!fallBack) {
bool deleteFont = false;
HFONT hfont = NULL;
if (ti.fontEngine->type() == QFontEngine::Win) {
hfont = static_cast<HFONT>(ti.fontEngine->handle());
}
#if QT_CONFIG(directwrite)
else if (ti.fontEngine->type() == QFontEngine::DirectWrite) {
QWindowsFontEngineDirectWrite *fedw = static_cast<QWindowsFontEngineDirectWrite *>(ti.fontEngine);
hfont = fedw->createHFONT();
if (hfont)
deleteFont = true;
}
#endif
if (hfont) {
// Try selecting the font to see if we get a substitution font
SelectObject(d->hdc, hfont);
if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) {
@ -302,7 +319,12 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
GetTextFace(d->hdc, 64, n);
fallBack = QString::fromWCharArray(n)
!= QString::fromWCharArray(logFont.lfFaceName);
if (deleteFont)
DeleteObject(hfont);
}
} else {
fallBack = true;
}
}
@ -1720,11 +1742,20 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
const bool has_kerning = ti.f && ti.f->kerning();
HFONT hfont = 0;
bool deleteFont = false;
if (ti.fontEngine->type() == QFontEngine::Win) {
if (ti.fontEngine->supportsTransformation(QTransform::fromScale(0.5, 0.5))) // is TrueType font?
hfont = static_cast<HFONT>(ti.fontEngine->handle());
}
#if QT_CONFIG(directwrite)
else if (ti.fontEngine->type() == QFontEngine::DirectWrite) {
QWindowsFontEngineDirectWrite *fedw = static_cast<QWindowsFontEngineDirectWrite *>(ti.fontEngine);
hfont = fedw->createHFONT();
if (hfont)
deleteFont = true;
}
#endif
if (!hfont)
hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
@ -1797,6 +1828,9 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
SetWorldTransform(hdc, &win_xform);
SelectObject(hdc, old_font);
if (deleteFont)
DeleteObject(hfont);
}
QT_END_NAMESPACE