vcl/headless/svpgdi.cxx | 1 + vcl/inc/textrender.hxx | 2 ++ vcl/inc/unx/cairotextrender.hxx | 4 +--- vcl/inc/unx/glyphcache.hxx | 13 +++++++++++++ vcl/qt5/Qt5Graphics.cxx | 11 +---------- vcl/quartz/salgdi.cxx | 7 +------ vcl/source/font/fontcache.cxx | 9 +++++++++ vcl/source/gdi/salgdilayout.cxx | 1 + vcl/unx/generic/gdi/cairotextrender.cxx | 12 ++++++------ vcl/unx/generic/glyphs/glyphcache.cxx | 21 ++++++++++++++++++++- 10 files changed, 55 insertions(+), 26 deletions(-)
New commits: commit a00bdc999344db34d5926dc77ed5ca895295b0ee Author: Jan-Marek Glogowski <[email protected]> AuthorDate: Mon Nov 18 16:04:24 2019 +0000 Commit: Jan-Marek Glogowski <[email protected]> CommitDate: Tue Nov 19 12:48:03 2019 +0100 tdf#128434 correctly release fonts in destructors This adds ReleaseFonts() calls to all destructors of SalGraphics and TextRenderImpl derivated classes, which implement SetFont. During destruction a base class can't call into derivated classes, as these are already destructed, so we have to spread these calls manually. Change-Id: Ia57db04f7df665e5205212ce512119e2f60e3379 Reviewed-on: https://gerrit.libreoffice.org/82967 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <[email protected]> (cherry picked from commit f8e1f8652255cadd80a991aa3e059ee631b333b8) Reviewed-on: https://gerrit.libreoffice.org/83149 diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index 57f66d4fabf6..e34678a93932 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -612,6 +612,7 @@ SvpSalGraphics::SvpSalGraphics() SvpSalGraphics::~SvpSalGraphics() { + ReleaseFonts(); } void SvpSalGraphics::setSurface(cairo_surface_t* pSurface, const basegfx::B2IVector& rSize) diff --git a/vcl/inc/textrender.hxx b/vcl/inc/textrender.hxx index 742d8445299b..1aec8fba2301 100644 --- a/vcl/inc/textrender.hxx +++ b/vcl/inc/textrender.hxx @@ -32,10 +32,12 @@ class PhysicalFontFace; class TextRenderImpl { public: + // can't call ReleaseFonts here, as the destructor just calls this classes SetFont (pure virtual)! virtual ~TextRenderImpl() {} virtual void SetTextColor( Color nColor ) = 0; virtual void SetFont(LogicalFontInstance*, int nFallbackLevel) = 0; + void ReleaseFonts() { SetFont(nullptr, 0); } virtual void GetFontMetric( ImplFontMetricDataRef&, int nFallbackLevel ) = 0; virtual FontCharMapRef GetFontCharMap() const = 0; virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const = 0; diff --git a/vcl/inc/unx/cairotextrender.hxx b/vcl/inc/unx/cairotextrender.hxx index 33b1a622945e..c0882bc35f86 100644 --- a/vcl/inc/unx/cairotextrender.hxx +++ b/vcl/inc/unx/cairotextrender.hxx @@ -38,13 +38,11 @@ protected: virtual void getSurfaceOffset(double& nDX, double& nDY) = 0; virtual void releaseCairoContext(cairo_t* cr) = 0; - void setFont(LogicalFontInstance *pEntry, int nFallbackLevel); - virtual void clipRegion(cairo_t* cr) = 0; public: CairoTextRender(); - + virtual ~CairoTextRender() override; virtual void SetTextColor( Color nColor ) override; virtual void SetFont(LogicalFontInstance*, int nFallbackLevel) override; diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx index 5192f0b42416..8228699a2602 100644 --- a/vcl/qt5/Qt5Graphics.cxx +++ b/vcl/qt5/Qt5Graphics.cxx @@ -44,16 +44,7 @@ Qt5Graphics::Qt5Graphics( Qt5Frame *pFrame, QImage *pQImage ) m_pWidgetDraw.reset(new Qt5Graphics_Controls()); } -Qt5Graphics::~Qt5Graphics() -{ - // release the text styles - for (int i = 0; i < MAX_FALLBACK; ++i) - { - if (!m_pTextStyle[i]) - break; - m_pTextStyle[i].clear(); - } -} +Qt5Graphics::~Qt5Graphics() { ReleaseFonts(); } void Qt5Graphics::ChangeQImage(QImage* pQImage) { diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx index 8884d0bd9f3b..b6df53319e28 100644 --- a/vcl/quartz/salgdi.cxx +++ b/vcl/quartz/salgdi.cxx @@ -222,12 +222,7 @@ AquaSalGraphics::~AquaSalGraphics() CGPathRelease( mxClipPath ); } - for (int i = 0; i < MAX_FALLBACK; ++i) - { - if (!mpTextStyle[i]) - break; - mpTextStyle[i].clear(); - } + ReleaseFonts(); if( mpXorEmulation ) delete mpXorEmulation; diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx index b0fefa665bd5..de11058e4507 100644 --- a/vcl/source/gdi/salgdilayout.cxx +++ b/vcl/source/gdi/salgdilayout.cxx @@ -82,6 +82,7 @@ bool SalGraphics::initWidgetDrawBackends(bool bForce) SalGraphics::~SalGraphics() COVERITY_NOEXCEPT_FALSE { + // can't call ReleaseFonts here, as the destructor just calls this classes SetFont (pure virtual)! } #if HAVE_FEATURE_OPENGL diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx index 3b1c7f24f01a..9610a73bc1d6 100644 --- a/vcl/unx/generic/gdi/cairotextrender.cxx +++ b/vcl/unx/generic/gdi/cairotextrender.cxx @@ -81,7 +81,12 @@ CairoTextRender::CairoTextRender() rp = nullptr; } -void CairoTextRender::setFont(LogicalFontInstance *pEntry, int nFallbackLevel) +CairoTextRender::~CairoTextRender() +{ + ReleaseFonts(); +} + +void CairoTextRender::SetFont(LogicalFontInstance *pEntry, int nFallbackLevel) { // release all no longer needed font resources for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) @@ -380,11 +385,6 @@ bool CairoTextRender::GetFontCapabilities(vcl::FontCapabilities &rGetImplFontCap // SalGraphics -void CairoTextRender::SetFont(LogicalFontInstance *pEntry, int nFallbackLevel) -{ - setFont(pEntry, nFallbackLevel); -} - void CairoTextRender::SetTextColor( Color nColor ) { commit 325005697155853891ce4f23e7349931e748d7e7 Author: Jan-Marek Glogowski <[email protected]> AuthorDate: Sat Nov 16 02:21:26 2019 +0000 Commit: Jan-Marek Glogowski <[email protected]> CommitDate: Tue Nov 19 12:47:51 2019 +0100 tdf#128434 try garbage collect ImplFontCache fonts Instead of changing the harfbuzz caching, for this use case it's enough to queue all per-OutputDevice fonts for garbage collection (GC), which are managed by the OutputDevices ImplFontCache. So just try to GC all the fonts in the ImplFontCache destructor. There is no point keeping these LogicalFontInstances alive, after the OutputDevice font cache is destroyed, as these fonts aren't shared and can't be accessed later. But the main problem is still some correct accounting of harfbuzz resources and eventual even the Freetype ones, so this cleanup would not really be needed. AFAI can tell, this plugs the remaining per-document leaks of the PDF generation, except for a 72 byte basic listener leak from: basic::ImplRepository::impl_createManagerForModel(...) basicmanagerrepository.cxx:480 Change-Id: I3155be59a2bdcd85e01f6f048b990db04d88c94f Reviewed-on: https://gerrit.libreoffice.org/82968 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <[email protected]> (cherry picked from commit e6aac0b637d583d3cfb893276f813ff5aa1ade17) Reviewed-on: https://gerrit.libreoffice.org/83148 diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx index 797890a2a345..f369952faac4 100644 --- a/vcl/inc/unx/glyphcache.hxx +++ b/vcl/inc/unx/glyphcache.hxx @@ -90,6 +90,19 @@ public: FreetypeFont* CacheFont(LogicalFontInstance* pFontInstance); void UncacheFont( FreetypeFont& ); + + /** Try to GarbageCollect an explicit logical font + * + * This should just be called from the ~ImplFontCache destructor, which holds the mapping of the + * FontSelectPattern to the LogicalFontInstance per OutputDevice. All other users should just + * call CacheFont and UncacheFont correctly. When the ImplFontCache is destroyed with its + * OutputDevice, we can safely garbage collection its unused entries, as these can't be reused. + * + * It's always safe to call this, as it just ignores the used bytes when considering a font for + * garbage collection, which normally keeps unreferenced fonts alive. + **/ + void TryGarbageCollectFont(LogicalFontInstance*); + void ClearFontCache(); void ClearFontOptions(); diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx index 67217acd0472..f3f87d36616b 100644 --- a/vcl/source/font/fontcache.cxx +++ b/vcl/source/font/fontcache.cxx @@ -24,6 +24,10 @@ #include <PhysicalFontFamily.hxx> #include <sal/log.hxx> +#if !(defined(_WIN32) || defined(MACOSX) || defined(IOS)) +#include <unx/glyphcache.hxx> +#endif + size_t ImplFontCache::IFSD_Hash::operator()( const FontSelectPattern& rFSD ) const { return rFSD.hashCode(); @@ -91,7 +95,12 @@ ImplFontCache::ImplFontCache() ImplFontCache::~ImplFontCache() { for (const auto & rLFI : maFontInstanceList) + { +#if !(defined(_WIN32) || defined(MACOSX) || defined(IOS)) + GlyphCache::GetInstance().TryGarbageCollectFont(rLFI.second.get()); +#endif rLFI.second->mpFontCache = nullptr; + } } rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList, diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx b/vcl/unx/generic/glyphs/glyphcache.cxx index 34543b7731a0..9640ea70adcf 100644 --- a/vcl/unx/generic/glyphs/glyphcache.cxx +++ b/vcl/unx/generic/glyphs/glyphcache.cxx @@ -199,6 +199,21 @@ void GlyphCache::UncacheFont( FreetypeFont& rFreetypeFont ) } } +void GlyphCache::TryGarbageCollectFont(LogicalFontInstance *pFontInstance) +{ + if (maFontList.empty() || !pFontInstance) + return; + FreetypeFontInstance* pFFI = dynamic_cast<FreetypeFontInstance*>(pFontInstance); + if (!pFFI) + return; + FreetypeFont* pFreetypeFont = pFFI->GetFreetypeFont(); + if (pFreetypeFont && (pFreetypeFont->GetRefCount() <= 0)) + { + mpCurrentGCFont = pFreetypeFont; + GarbageCollect(); + } +} + void GlyphCache::GarbageCollect() { // when current GC font has been destroyed get another one @@ -236,7 +251,11 @@ void GlyphCache::GarbageCollect() if( pFreetypeFont == mpCurrentGCFont ) mpCurrentGCFont = nullptr; - maFontList.erase(pFreetypeFont->GetFontInstance()); +#ifndef NDEBUG + int nErased = +#endif + maFontList.erase(pFreetypeFont->GetFontInstance()); + assert(1 == nErased); } } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
