From c0b129deb0d335a85572ef541f7e051a97363d70 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 11:54:18 +0200 Subject: [PATCH 1/2] [graf2d] Further simplify freetype resource cleanup. In looking for a memory leak (which turned out to be a freetype issue [1]), it became evident that TTGlyph can actually handle its own cleanup, allowing for simplifying the code. [1] https://gitlab.freedesktop.org/freetype/freetype/-/work_items/1399 --- graf2d/graf/inc/TTF.h | 1 + graf2d/graf/src/TTF.cxx | 16 +++++----------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/graf2d/graf/inc/TTF.h b/graf2d/graf/inc/TTF.h index 773459a9502d2..60dc87c37d279 100644 --- a/graf2d/graf/inc/TTF.h +++ b/graf2d/graf/inc/TTF.h @@ -68,6 +68,7 @@ class TTF { FT_Vector fPos; ///< position of glyph origin FT_Glyph fImage{nullptr}; ///< glyph image TTGlyph(UInt_t indx = 0) : fIndex(indx) {} + ~TTGlyph(); }; TTF() {} diff --git a/graf2d/graf/src/TTF.cxx b/graf2d/graf/src/TTF.cxx index 5621cfa749433..5d75b1444c346 100644 --- a/graf2d/graf/src/TTF.cxx +++ b/graf2d/graf/src/TTF.cxx @@ -35,6 +35,11 @@ const Float_t kScale = 0.93376068; Bool_t TTFhandle::fgHinting = kFALSE; Bool_t TTFhandle::fgSmoothing = kTRUE; +/// Free all resources of this glyph. +TTF::TTGlyph::~TTGlyph() +{ + FT_Done_Glyph(fImage); +} struct TTFontHandle { std::string name; @@ -67,8 +72,6 @@ struct TTFhandle::FT_Library_Wrapper { return _library; } - bool InitCompleted() const { return _library != nullptr; } - ~FT_Library_Wrapper() { if (_library) @@ -278,15 +281,6 @@ FT_BitmapGlyph TTFhandle::GetGlyphBitmap(UInt_t n, Bool_t smooth) void TTFhandle::CleanupGlyphs() { - bool is_lib = fFT_Library.InitCompleted(); - - for(auto &glyph : fGlyphs) { - // clear existing image if there is one - if (glyph.fImage && is_lib) { - FT_Done_Glyph(glyph.fImage); - glyph.fImage = nullptr; - } - } fGlyphs.clear(); } From d97297c212b2001c38a1a4873ceba0bea38e2c11 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 13:05:20 +0200 Subject: [PATCH 2/2] [graf2d] Ensure that the freetype library is initialised. Whenever a handle to the freetype library is created, ensure that the thread-local library is initialised. --- graf2d/graf/src/TTF.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/graf2d/graf/src/TTF.cxx b/graf2d/graf/src/TTF.cxx index 5d75b1444c346..c026beb98de4f 100644 --- a/graf2d/graf/src/TTF.cxx +++ b/graf2d/graf/src/TTF.cxx @@ -83,7 +83,11 @@ thread_local TTFhandle::FT_Library_Wrapper TTFhandle::fFT_Library; //////////////////////////////////////////////////////////////////////////////// -TTFhandle::TTFhandle() = default; +TTFhandle::TTFhandle() +{ + // Ensure that there's a freetype library in our thread + fFT_Library.Get(); +} ////////////////////////////////////////////////////////////////////////////////