summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <[email protected]>2025-05-30 09:59:31 +0200
committerEskil Abrahamsen Blomfeldt <[email protected]>2025-06-02 11:34:02 +0200
commitab7a80a9557e12735f4e3c3fe76ccc72feba2fc8 (patch)
tree7ee292923b5b34c6c531f1196ffb10bbdf8b9501
parentb23da37d71bde4673fab3510596514e4ac451053 (diff)
DirectWrite: Avoid infinite recursion with broken font dataHEADdev
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.cpp10
-rw-r--r--src/gui/text/qfontengine_p.h4
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite.cpp13
-rw-r--r--tests/auto/gui/text/qrawfont/CMakeLists.txt1
-rw-r--r--tests/auto/gui/text/qrawfont/testfont_zeroem.ttfbin0 -> 22704 bytes
-rw-r--r--tests/auto/gui/text/qrawfont/tst_qrawfont.cpp13
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
new file mode 100644
index 00000000000..04c469f4966
--- /dev/null
+++ b/tests/auto/gui/text/qrawfont/testfont_zeroem.ttf
Binary files differ
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)