From 05de036a8855adbdd882942d2fb61c231b02bf5a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 14 Dec 2023 11:10:51 +0100 Subject: [PATCH] Fix synthesized bold on Windows There were a couple of problems with synthesizing boldness on Windows: For the DirectWrite font database, this was not implemented at all, so this change adds support for it. For the default GDI font database, the font engine is correctly created for a font with synthetic bold, but the function that retrieves the contours from the font does not apply the transformation. So when generating the distance fields for Qt Quick, we would get the unemboldened contours. The fix for this is simply to fall back to using DirectWrite for fonts that require any synthetization. This will later become the default anyway. Pick-to: 6.5 6.6 6.7 Fixes: QTBUG-119995 Change-Id: I5b4e3b19d0d71c6599746172da0bee41e8fb3940 Reviewed-by: Volker Hilsheimer --- .../qwindowsdirectwritefontdatabase.cpp | 35 +++++++++++++------ src/gui/text/windows/qwindowsfontdatabase.cpp | 5 ++- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp b/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp index 31870d4a08..b897e1f1db 100644 --- a/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp +++ b/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp @@ -243,28 +243,43 @@ QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QFontDef &fontDef IDWriteFontFace *face = reinterpret_cast(handle); Q_ASSERT(face != nullptr); + DWRITE_FONT_SIMULATIONS simulations = DWRITE_FONT_SIMULATIONS_NONE; + if (fontDef.weight >= QFont::DemiBold || fontDef.style != QFont::StyleNormal) { + DirectWriteScope face3; + if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3), + reinterpret_cast(&face3)))) { + if (fontDef.weight >= QFont::DemiBold && face3->GetWeight() < DWRITE_FONT_WEIGHT_DEMI_BOLD) + simulations |= DWRITE_FONT_SIMULATIONS_BOLD; + + if (fontDef.style != QFont::StyleNormal && face3->GetStyle() == DWRITE_FONT_STYLE_NORMAL) + simulations |= DWRITE_FONT_SIMULATIONS_OBLIQUE; + } + } + DirectWriteScope newFace; - if (!fontDef.variableAxisValues.isEmpty()) { + if (!fontDef.variableAxisValues.isEmpty() || simulations != DWRITE_FONT_SIMULATIONS_NONE) { DirectWriteScope face5; if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace5), reinterpret_cast(&face5)))) { DirectWriteScope font; if (SUCCEEDED(face5->GetFontResource(&font))) { UINT32 fontAxisCount = font->GetFontAxisCount(); - QVarLengthArray fontAxisValues(fontAxisCount); - if (SUCCEEDED(face5->GetFontAxisValues(fontAxisValues.data(), fontAxisCount))) { - for (UINT32 i = 0; i < fontAxisCount; ++i) { - if (auto maybeTag = QFont::Tag::fromValue(qToBigEndian(fontAxisValues[i].axisTag))) { - if (fontDef.variableAxisValues.contains(*maybeTag)) - fontAxisValues[i].value = fontDef.variableAxisValues.value(*maybeTag); + + if (!fontDef.variableAxisValues.isEmpty()) { + if (SUCCEEDED(face5->GetFontAxisValues(fontAxisValues.data(), fontAxisCount))) { + for (UINT32 i = 0; i < fontAxisCount; ++i) { + if (auto maybeTag = QFont::Tag::fromValue(qToBigEndian(fontAxisValues[i].axisTag))) { + if (fontDef.variableAxisValues.contains(*maybeTag)) + fontAxisValues[i].value = fontDef.variableAxisValues.value(*maybeTag); + } } } } - if (SUCCEEDED(font->CreateFontFace(DWRITE_FONT_SIMULATIONS_NONE, - fontAxisValues.data(), - fontAxisCount, + if (SUCCEEDED(font->CreateFontFace(simulations, + !fontDef.variableAxisValues.isEmpty() ? fontAxisValues.data() : nullptr, + !fontDef.variableAxisValues.isEmpty() ? fontAxisCount : 0, &newFace))) { face = *newFace; } else { diff --git a/src/gui/text/windows/qwindowsfontdatabase.cpp b/src/gui/text/windows/qwindowsfontdatabase.cpp index b227cf677e..ef516068a7 100644 --- a/src/gui/text/windows/qwindowsfontdatabase.cpp +++ b/src/gui/text/windows/qwindowsfontdatabase.cpp @@ -1225,6 +1225,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q HRESULT hr = data->directWriteGdiInterop->CreateFontFaceFromHdc(data->hdc, &directWriteFontFace); if (SUCCEEDED(hr)) { bool isColorFont = false; + bool needsSimulation = false; #if QT_CONFIG(direct2d) IDWriteFontFace2 *directWriteFontFace2 = nullptr; if (SUCCEEDED(directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2), @@ -1232,10 +1233,12 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q if (directWriteFontFace2->IsColorFont()) isColorFont = directWriteFontFace2->GetPaletteEntryCount() > 0; + needsSimulation = directWriteFontFace2->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE; + directWriteFontFace2->Release(); } #endif // direct2d - useDw = useDw || useDirectWrite(hintingPreference, fam, isColorFont); + useDw = useDw || useDirectWrite(hintingPreference, fam, isColorFont) || needsSimulation; qCDebug(lcQpaFonts) << __FUNCTION__ << request.families.first() << request.pointSize << "pt" << "hintingPreference=" << hintingPreference << "color=" << isColorFont