From 98d03964ac4d8bc8c19c3c0340daf4a1ae949421 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 1 Nov 2024 09:37:52 +0100 Subject: [PATCH] Windows: Fix missing glyphs for very large font When the font size gets to a certain size (at some point after 1200 pixels), DirectWrite will just return an empty rect as the bound for it and does not want to render it. At this point, you might want to consider other ways of rendering the text, but since the same did not happen e.g. with the Freetype backend, it was an unfortunate platform difference. As a fail safe, we detect when this occurs and fall back to the QFontEngine base class approach of drawing the glyph as a QPainterPath instead. [ChangeLog][Windows] Fixed an issue where glyphs might be missing for very large fonts. Fixes: QTBUG-126671 Change-Id: I13cc1e5d71fae114e2a7933a7c5f7b9980237390 Reviewed-by: Eirik Aavitsland (cherry picked from commit a5ddcbb76b674470f0c3d1d5e0bb7697a2828d25) Reviewed-by: Qt Cherry-pick Bot --- src/gui/text/qfontengine.cpp | 10 ++++-- src/gui/text/qfontengine_p.h | 1 + .../windows/qwindowsfontenginedirectwrite.cpp | 36 ++++++++++++------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index ee74c7f8fb8..f5aec978099 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -868,7 +868,7 @@ QFontEngine::Glyph *QFontEngine::glyphData(glyph_t, return nullptr; } -QImage QFontEngine::alphaMapForGlyph(glyph_t glyph) +QImage QFontEngine::renderedPathForGlyph(glyph_t glyph, const QColor &color) { glyph_metrics_t gm = boundingBox(glyph); int glyph_x = qFloor(gm.x.toReal()); @@ -889,10 +889,16 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph) p.setRenderHint(QPainter::Antialiasing); addGlyphsToPath(&glyph, &pt, 1, &path, { }); p.setPen(Qt::NoPen); - p.setBrush(Qt::black); + p.setBrush(color); p.drawPath(path); p.end(); + return im; +} + +QImage QFontEngine::alphaMapForGlyph(glyph_t glyph) +{ + QImage im = renderedPathForGlyph(glyph, Qt::black); QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); for (int y=0; y(im.constScanLine(y)); - uchar *dst = alphaMap.scanLine(y); - for (int x=0; xpow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.); - ++dst; - ++src; + for (int y=0; y(im.constScanLine(y)); + uchar *dst = alphaMap.scanLine(y); + for (int x=0; xpow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.); + ++dst; + ++src; + } } - } - return alphaMap; + return alphaMap; + } else { + return QFontEngine::alphaMapForGlyph(glyph, t); + } } QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, @@ -794,8 +798,10 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, : DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - if (rect.top == rect.bottom || rect.left == rect.right) + if (rect.top == rect.bottom || rect.left == rect.right) { + qCDebug(lcQpaFonts) << __FUNCTION__ << "Cannot get alpha texture bounds. Falling back to slower rendering path."; return QImage(); + } QRect boundingRect = QRect(QPoint(rect.left - margin, rect.top - margin), @@ -1009,6 +1015,12 @@ QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t, glyphMargin(QFontEngine::Format_A32), xform); + if (mask.isNull()) { + mask = QFontEngine::renderedPathForGlyph(t, Qt::white); + if (!xform.isIdentity()) + mask = mask.transformed(xform); + } + return mask.depth() == 32 ? mask : mask.convertToFormat(QImage::Format_RGB32); @@ -1157,7 +1169,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph int margin = glyphMargin(format); if (rect.left == rect.right || rect.top == rect.bottom) - return glyph_metrics_t(); + return bbox; return glyph_metrics_t(rect.left, rect.top,