From b4a1265b151d4008c9edafbcc2892f49abb6fe4a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 16 Aug 2021 14:41:47 +0200 Subject: [PATCH] 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 (cherry picked from commit 2f5695bed5660e32a41786d8b9ab6b4b0775caf1) Reviewed-by: Qt Cherry-pick Bot --- .../windows/qwindowsfontenginedirectwrite.cpp | 16 ++++++++ .../windows/qwindowsfontenginedirectwrite_p.h | 4 +- .../platform/windows/qprintengine_win.cpp | 38 ++++++++++++++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp index 0dac9769ef4..55aab151329 100644 --- a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp @@ -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; diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h index 4d19c3908a1..06eb5ae475b 100644 --- a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h +++ b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h @@ -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, diff --git a/src/printsupport/platform/windows/qprintengine_win.cpp b/src/printsupport/platform/windows/qprintengine_win.cpp index 454bcab069f..1ef7aa3f209 100644 --- a/src/printsupport/platform/windows/qprintengine_win.cpp +++ b/src/printsupport/platform/windows/qprintengine_win.cpp @@ -49,6 +49,9 @@ #include #include #include +#if QT_CONFIG(directwrite) +# include +#endif #include #include @@ -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(ti.fontEngine->handle())) { + if (!fallBack) { + bool deleteFont = false; + HFONT hfont = NULL; + if (ti.fontEngine->type() == QFontEngine::Win) { + hfont = static_cast(ti.fontEngine->handle()); + } +#if QT_CONFIG(directwrite) + else if (ti.fontEngine->type() == QFontEngine::DirectWrite) { + QWindowsFontEngineDirectWrite *fedw = static_cast(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(ti.fontEngine->handle()); } +#if QT_CONFIG(directwrite) + else if (ti.fontEngine->type() == QFontEngine::DirectWrite) { + QWindowsFontEngineDirectWrite *fedw = static_cast(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