diff options
author | Eskil Abrahamsen Blomfeldt <[email protected]> | 2025-05-30 09:59:31 +0200 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <[email protected]> | 2025-06-02 11:34:02 +0200 |
commit | ab7a80a9557e12735f4e3c3fe76ccc72feba2fc8 (patch) | |
tree | 7ee292923b5b34c6c531f1196ffb10bbdf8b9501 | |
parent | b23da37d71bde4673fab3510596514e4ac451053 (diff) |
If a font has an em square size of 0 it is not going to be useful.
However, if one was encountered we returned a default value to
avoid division by zero. The default implementation called ascent(),
which would depend on the em square size again and we would get an
infinite recursion for these fonts.
To avoid this, we simply return a default value of 16 in the case
of a broken font. (The Apple spec gives the range 64 .. 16384 for
the em square and the Microsoft spec says 16 .. 16384, so we use
the smallest of the two.)
Fixes: QTBUG-137277
Pick-to: 6.5 6.8 6.9
Change-Id: I63779e44c10c7021486787d1e1e818f4c6e47835
Reviewed-by: Allan Sandfeld Jensen <[email protected]>
-rw-r--r-- | src/gui/text/qfontengine.cpp | 10 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 4 | ||||
-rw-r--r-- | src/gui/text/windows/qwindowsfontenginedirectwrite.cpp | 13 | ||||
-rw-r--r-- | tests/auto/gui/text/qrawfont/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/gui/text/qrawfont/testfont_zeroem.ttf | bin | 0 -> 22704 bytes | |||
-rw-r--r-- | tests/auto/gui/text/qrawfont/tst_qrawfont.cpp | 13 |
6 files changed, 35 insertions, 6 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 59898f5c29b..68b31a7841a 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -496,6 +496,13 @@ QFixed QFontEngine::leading() const return m_leading; } + +QFixed QFontEngine::emSquareSize() const +{ + qCWarning(lcQpaFonts) << "Font engine does not reimplement emSquareSize(). Returning minimum value."; + return 16; +} + QFixed QFontEngine::ascent() const { if (!m_heightMetricsQueried) @@ -2354,6 +2361,9 @@ glyph_metrics_t QFontEngineMulti::boundingBox(glyph_t glyph) return engine(which)->boundingBox(stripped(glyph)); } +QFixed QFontEngineMulti::emSquareSize() const +{ return engine(0)->emSquareSize(); } + QFixed QFontEngineMulti::ascent() const { return engine(0)->ascent(); } diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 4d1243ccc51..5e2c2963ca4 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -163,7 +163,7 @@ public: || QChar::category(ucs4) == QChar::Other_Control; } - virtual QFixed emSquareSize() const { return ascent(); } + virtual QFixed emSquareSize() const; /* returns 0 as glyph index for non existent glyphs */ virtual glyph_t glyphIndex(uint ucs4) const = 0; @@ -425,6 +425,7 @@ public: virtual glyph_metrics_t boundingBox(glyph_t glyph) override; virtual QFontEngine *cloneWithSize(qreal pixelSize) const override; + virtual QFixed emSquareSize() const override { return _size; } virtual QFixed ascent() const override; virtual QFixed capHeight() const override; virtual QFixed descent() const override; @@ -463,6 +464,7 @@ public: virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags) override; virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = nullptr, qreal *rightBearing = nullptr) override; + virtual QFixed emSquareSize() const override; virtual QFixed ascent() const override; virtual QFixed capHeight() const override; virtual QFixed descent() const override; diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp index 17b0c431852..3e10cdad44f 100644 --- a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp @@ -369,6 +369,14 @@ void QWindowsFontEngineDirectWrite::collectMetrics() m_directWriteFontFace->GetMetrics(&metrics); m_unitsPerEm = metrics.designUnitsPerEm; + // Something is wrong with this font. Set the em square size to the minimum value in + // the spec. + if (m_unitsPerEm == 0) { + qCWarning(lcQpaFonts) << "Font" << fontDef.families << "reports an em square size of 0." + << "Clamping to minimum value."; + m_unitsPerEm = 16; + } + m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness); m_capHeight = DESIGN_TO_LOGICAL(metrics.capHeight); m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight); @@ -497,10 +505,7 @@ bool QWindowsFontEngineDirectWrite::getSfntTableData(uint tag, uchar *buffer, ui QFixed QWindowsFontEngineDirectWrite::emSquareSize() const { - if (m_unitsPerEm > 0) - return m_unitsPerEm; - else - return QFontEngine::emSquareSize(); + return m_unitsPerEm; } glyph_t QWindowsFontEngineDirectWrite::glyphIndex(uint ucs4) const diff --git a/tests/auto/gui/text/qrawfont/CMakeLists.txt b/tests/auto/gui/text/qrawfont/CMakeLists.txt index d2a318a2a36..2dcd6615951 100644 --- a/tests/auto/gui/text/qrawfont/CMakeLists.txt +++ b/tests/auto/gui/text/qrawfont/CMakeLists.txt @@ -17,6 +17,7 @@ set_source_files_properties("../../../shared/resources/testfont.ttf" ) set(testdata_resource_files "../../../shared/resources/testfont.ttf" + "testfont_zeroem.ttf" "testfont_bold_italic.ttf" "testfont_os2_v1.ttf" ) diff --git a/tests/auto/gui/text/qrawfont/testfont_zeroem.ttf b/tests/auto/gui/text/qrawfont/testfont_zeroem.ttf Binary files differnew file mode 100644 index 00000000000..04c469f4966 --- /dev/null +++ b/tests/auto/gui/text/qrawfont/testfont_zeroem.ttf diff --git a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp index 5ec2536718d..252059a7d89 100644 --- a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp +++ b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp @@ -71,10 +71,13 @@ private slots: void qtbug65923_partal_clone_data(); void qtbug65923_partal_clone(); + void zeroEmSquare(); + private: QString testFont; QString testFontBoldItalic; QString testFontOs2V1; + QString testFontNoEmSquare; #endif // QT_NO_RAWFONT }; @@ -93,7 +96,9 @@ void tst_QRawFont::initTestCase() testFont = QFINDTESTDATA("testfont.ttf"); testFontBoldItalic = QFINDTESTDATA("testfont_bold_italic.ttf"); testFontOs2V1 = QFINDTESTDATA("testfont_os2_v1.ttf"); - if (testFont.isEmpty() || testFontBoldItalic.isEmpty()) + testFontNoEmSquare = QFINDTESTDATA("testfont_zeroem.ttf"); + + if (testFont.isEmpty() || testFontBoldItalic.isEmpty() || testFontNoEmSquare.isEmpty()) QFAIL("qrawfont unittest font files not found!"); if (QFontDatabase::families().size() == 0) @@ -1079,6 +1084,12 @@ void tst_QRawFont::qtbug65923_partal_clone() QVERIFY(!outerFont.boundingRect(42).isEmpty()); } +void tst_QRawFont::zeroEmSquare() +{ + QRawFont rawFont(testFontNoEmSquare, 12); + QVERIFY(!rawFont.isValid() || rawFont.unitsPerEm() > 0); +} + #endif // QT_NO_RAWFONT QTEST_MAIN(tst_QRawFont) |