sw/inc/fmtcol.hxx                   |   32 ++++++------------------
 sw/inc/shellio.hxx                  |    1 
 sw/source/core/doc/fmtcol.cxx       |   31 ++++++++++++++++++++++-
 sw/source/core/inc/swfntcch.hxx     |   47 ++++--------------------------------
 sw/source/core/layout/ftnfrm.cxx    |    4 +--
 sw/source/core/layout/pagechg.cxx   |    4 +--
 sw/source/core/text/atrhndl.hxx     |    2 -
 sw/source/core/text/atrstck.cxx     |    2 -
 sw/source/core/text/frmcrsr.cxx     |    4 +--
 sw/source/core/text/frmpaint.cxx    |    4 +--
 sw/source/core/text/porrst.cxx      |    4 +--
 sw/source/core/text/redlnitr.cxx    |    8 +++---
 sw/source/core/text/txtinit.cxx     |    2 -
 sw/source/core/txtnode/swfntcch.cxx |   35 ++------------------------
 sw/source/filter/html/swhtml.cxx    |   13 ---------
 sw/source/filter/ww8/ww8par.cxx     |   13 ---------
 16 files changed, 63 insertions(+), 143 deletions(-)

New commits:
commit ba462fddf5acb4db510aecb014614ff89aa433f0
Author:     Noel Grandin <[email protected]>
AuthorDate: Thu Oct 9 16:27:12 2025 +0200
Commit:     Noel Grandin <[email protected]>
CommitDate: Thu Feb 12 12:09:56 2026 +0100

    remove SwFontObj cache
    
    makes approx no difference to memory consumption when loading
    a 100+ page document, and shaves 5% off the load time.
    
    Change-Id: I72a19338ea52e806cc763e5cd9d2bb1c2dfd7033
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192107
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <[email protected]>

diff --git a/sw/inc/fmtcol.hxx b/sw/inc/fmtcol.hxx
index 4a9e5ea739fa..4e09f0aefb8b 100644
--- a/sw/inc/fmtcol.hxx
+++ b/sw/inc/fmtcol.hxx
@@ -31,6 +31,8 @@
 #include <memory>
 
 class SwAttrPool;
+class SwViewShell;
+class SwFontObj;
 namespace sw{ class DocumentStylePoolManager; }
 
 /// SwFormatColl is just an SwFormat subclass that defaults to 
m_bAutoFormat=false, expressing that
@@ -63,23 +65,17 @@ class SW_DLLPUBLIC SwTextFormatColl
 
     bool mbAssignedToOutlineStyle;
 
-    bool m_bInSwFntCache;
-
     SwTextFormatColl *mpNextTextFormatColl;
 
     SwCharFormat* mpLinkedCharFormat = nullptr;
 
+    /** cached/temporary font layout information */
+    mutable std::unique_ptr<SwFontObj> mxFontObj;
+
 protected:
     SwTextFormatColl( SwAttrPool& rPool, const UIName &rFormatCollName,
                     SwTextFormatColl* pDerFrom = nullptr,
-                    sal_uInt16 nFormatWh = RES_TXTFMTCOLL )
-        : SwFormatColl(rPool, rFormatCollName, aTextFormatCollSetRange, 
pDerFrom, nFormatWh)
-        , mbStayAssignedToListLevelOfOutlineStyle(false)
-        , mbAssignedToOutlineStyle(false)
-        , m_bInSwFntCache(false)
-    {
-        mpNextTextFormatColl = this;
-    }
+                    sal_uInt16 nFormatWh = RES_TXTFMTCOLL );
 
     /// To get UL- / LR- / FontHeight-changes.
     virtual void SwClientNotify(const SwModify&, const SfxHint&) override;
@@ -136,19 +132,9 @@ public:
         if(HasWriterListeners() && !IsModifyLocked())
             CallSwClientNotify(sw::LegacyModifyHint(&rDrop, &rDrop));
     };
-    bool IsInSwFntCache() const { return m_bInSwFntCache; };
-    void SetInSwFntCache() { m_bInSwFntCache = true; };
-    virtual void InvalidateInSwFntCache(sal_uInt16 nWhich) override
-    {
-        if(isCHRATR(nWhich))
-        {
-            m_bInSwFntCache = false;
-        }
-    };
-    virtual void InvalidateInSwFntCache() override
-    {
-        m_bInSwFntCache = false;
-    }
+    virtual void InvalidateInSwFntCache(sal_uInt16 nWhich) override;
+    virtual void InvalidateInSwFntCache() override;
+    const SwFontObj & GetFontObj(SwViewShell *pSh) const;
 };
 
 class SwGrfFormatColl final : public SwFormatColl
diff --git a/sw/inc/shellio.hxx b/sw/inc/shellio.hxx
index f7c7cb3b292b..064a0d0f5741 100644
--- a/sw/inc/shellio.hxx
+++ b/sw/inc/shellio.hxx
@@ -206,7 +206,6 @@ extern "C" SAL_DLLPUBLIC_EXPORT bool 
TestImportDOCX(SvStream &rStream);
 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportRTF(SvStream &rStream);
 extern "C" SAL_DLLPUBLIC_EXPORT bool TestPDFExportRTF(SvStream &rStream);
 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportHTML(SvStream &rStream);
-SAL_DLLPUBLIC_EXPORT void FlushFontCache();
 
 class SW_DLLPUBLIC Reader
 {
diff --git a/sw/source/core/doc/fmtcol.cxx b/sw/source/core/doc/fmtcol.cxx
index 32d76a11cae3..7463f6e3dc34 100644
--- a/sw/source/core/doc/fmtcol.cxx
+++ b/sw/source/core/doc/fmtcol.cxx
@@ -108,10 +108,19 @@ namespace TextFormatCollFunc
     }
 } // end of namespace TextFormatCollFunc
 
+SwTextFormatColl::SwTextFormatColl( SwAttrPool& rPool, const UIName 
&rFormatCollName,
+                SwTextFormatColl* pDerFrom,
+                sal_uInt16 nFormatWh )
+: SwFormatColl(rPool, rFormatCollName, aTextFormatCollSetRange, pDerFrom, 
nFormatWh)
+, mbStayAssignedToListLevelOfOutlineStyle(false)
+, mbAssignedToOutlineStyle(false)
+{
+    mpNextTextFormatColl = this;
+}
+
 SwTextFormatColl::~SwTextFormatColl()
 {
-    if(m_bInSwFntCache)
-        pSwFontCache->Delete( this );
+    mxFontObj.reset();
 
     if (GetDoc().IsInDtor())
     {
@@ -723,4 +732,22 @@ void 
SwTextFormatColl::DeleteAssignmentToListLevelOfOutlineStyle()
     ResetFormatAttr(RES_PARATR_OUTLINELEVEL);
 }
 
+void SwTextFormatColl::InvalidateInSwFntCache(sal_uInt16 nWhich)
+{
+    if(isCHRATR(nWhich))
+        mxFontObj.reset();
+};
+
+void SwTextFormatColl::InvalidateInSwFntCache()
+{
+    mxFontObj.reset();
+}
+
+const SwFontObj & SwTextFormatColl::GetFontObj(SwViewShell *pSh) const
+{
+    if (!mxFontObj)
+        mxFontObj = std::make_unique<SwFontObj>(this, pSh);
+    return *mxFontObj;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swfntcch.hxx b/sw/source/core/inc/swfntcch.hxx
index 844e9f3590a2..43c4c0e43e80 100644
--- a/sw/source/core/inc/swfntcch.hxx
+++ b/sw/source/core/inc/swfntcch.hxx
@@ -16,62 +16,27 @@
  *   except in compliance with the License. You may obtain a copy of
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
-#ifndef INCLUDED_SW_SOURCE_CORE_INC_SWFNTCCH_HXX
-#define INCLUDED_SW_SOURCE_CORE_INC_SWFNTCCH_HXX
+#pragma once
 
 #define NUM_DEFAULT_VALUES 40
 
-#include "swcache.hxx"
 #include "swfont.hxx"
 
 class SwViewShell;
 class SfxPoolItem;
 class SwTextFormatColl;
 
-class SwFontCache : public SwCache
+class SwFontObj
 {
 public:
+    SwFontObj( const SwTextFormatColl *pOwner, SwViewShell *pSh );
+    ~SwFontObj();
 
-    SwFontCache() : SwCache(50
-#ifdef DBG_UTIL
-    , "Global AttributeSet/Font-Cache pSwFontCache"_ostr
-#endif
-    ) {}
-
-};
-
-// AttributeSet/Font-Cache, globale Variable, in FontCache.Cxx angelegt
-extern SwFontCache *pSwFontCache;
-
-class SwFontObj final : public SwCacheObj
-{
-    friend class SwFontAccess;
-
+    const SwFont& GetFont() const { return m_aSwFont; }
+    const SfxPoolItem* const* GetDefault() const { return m_pDefaultArray; }
 private:
     SwFont m_aSwFont;
     const SfxPoolItem* m_pDefaultArray[ NUM_DEFAULT_VALUES ];
-
-public:
-    SwFontObj( const SwTextFormatColl* pOwner, SwViewShell *pSh );
-
-    virtual ~SwFontObj() override;
-
-    SwFont& GetFont()        { return m_aSwFont; }
-    const SwFont& GetFont() const  { return m_aSwFont; }
-    const SfxPoolItem** GetDefault() { return m_pDefaultArray; }
-};
-
-class SwFontAccess final : public SwCacheAccess
-{
-    SwViewShell *m_pShell;
-
-    virtual SwCacheObj *NewObj( ) override;
-
-public:
-    SwFontAccess( const SwTextFormatColl *pOwner, SwViewShell *pSh );
-    SwFontObj *Get();
 };
 
-#endif
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
index 210b6e23f4ba..df069300105d 100644
--- a/sw/source/core/layout/ftnfrm.cxx
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -69,8 +69,8 @@ bool FootnoteSeparatorHeightFromParagraph(SwDoc& rDoc, 
SwTwips& rHeight)
             return false;
         }
 
-        SwFontAccess aFontAccess(pDefaultParaFormat, pSh);
-        SwFont aFont(aFontAccess.Get()->GetFont());
+        const SwFontObj& rFontAccess = pDefaultParaFormat->GetFontObj(pSh);
+        SwFont aFont(rFontAccess.GetFont());
         OutputDevice& rOut = pSh->GetRefDev();
         rHeight = aFont.GetHeight(pSh, rOut);
         return true;
diff --git a/sw/source/core/layout/pagechg.cxx 
b/sw/source/core/layout/pagechg.cxx
index de760fbe6bac..a3559a4785e3 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -1120,8 +1120,8 @@ void SwPageFrame::ComputeRegister(const SwTextFormatColl* 
pFormat, sal_uInt16& r
     else
     {
         SwViewShell *pSh = getRootFrame()->GetCurrShell();
-        SwFontAccess aFontAccess( pFormat, pSh );
-        SwFont aFnt( aFontAccess.Get()->GetFont() );
+        const SwFontObj& rFontAccess = pFormat->GetFontObj(pSh);
+        SwFont aFnt( rFontAccess.GetFont() );
 
         OutputDevice *pOut = nullptr;
         if(pSh)
diff --git a/sw/source/core/text/atrhndl.hxx b/sw/source/core/text/atrhndl.hxx
index 6330857deb18..979b99800124 100644
--- a/sw/source/core/text/atrhndl.hxx
+++ b/sw/source/core/text/atrhndl.hxx
@@ -73,7 +73,7 @@ public:
     // set default attributes to values in rAttrSet or from cache
     void Init( const SwAttrSet& rAttrSet,
                const IDocumentSettingAccess& rIDocumentSettingAccess );
-    void Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAttrSet,
+    void Init( const SfxPoolItem* const* pPoolItem, const SwAttrSet* pAttrSet,
                const IDocumentSettingAccess& rIDocumentSettingAccess,
                const SwViewShell* pShell, SwFont& rFnt,
                bool bVertLayout, bool bVertLayoutLRBT );
diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx
index 1af5e50d8550..82cec27250fc 100644
--- a/sw/source/core/text/atrstck.cxx
+++ b/sw/source/core/text/atrstck.cxx
@@ -287,7 +287,7 @@ void SwAttrHandler::Init( const SwAttrSet& rAttrSet,
         m_pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i );
 }
 
-void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS,
+void SwAttrHandler::Init( const SfxPoolItem* const* pPoolItem, const 
SwAttrSet* pAS,
                           const IDocumentSettingAccess& rIDocumentSettingAcces,
                           const SwViewShell* pSh,
                           SwFont& rFnt, bool bVL, bool bVertLayoutLRBT )
diff --git a/sw/source/core/text/frmcrsr.cxx b/sw/source/core/text/frmcrsr.cxx
index 8ccf62981872..24dfeb49af1f 100644
--- a/sw/source/core/text/frmcrsr.cxx
+++ b/sw/source/core/text/frmcrsr.cxx
@@ -1424,8 +1424,8 @@ void SwTextFrame::FillCursorPos( SwFillData& rFill ) const
     }
     else
     {
-        SwFontAccess aFontAccess( pColl, pSh );
-        pFnt.reset(new SwFont( aFontAccess.Get()->GetFont() ));
+        const SwFontObj& rFontAccess = pColl->GetFontObj(pSh);
+        pFnt.reset(new SwFont( rFontAccess.GetFont() ));
         pFnt->CheckFontCacheId( pSh, pFnt->GetActual() );
     }
     OutputDevice* pOut = pSh->GetOut();
diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
index 007e0dfda7d3..eaad242df740 100644
--- a/sw/source/core/text/frmpaint.cxx
+++ b/sw/source/core/text/frmpaint.cxx
@@ -537,8 +537,8 @@ bool SwTextFrame::PaintEmpty( const SwRect &rRect, bool 
bCheck ) const
             }
             else
             {
-                SwFontAccess aFontAccess( &rTextNode.GetTextFormatColl(), pSh 
);
-                pFnt.reset(new SwFont( aFontAccess.Get()->GetFont() ));
+                const SwFontObj& rFontAccess = 
rTextNode.GetTextFormatColl().GetFontObj(pSh);
+                pFnt.reset(new SwFont( rFontAccess.GetFont() ));
             }
 
             const IDocumentRedlineAccess& rIDRA = 
rTextNode.getIDocumentRedlineAccess();
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index aa278dd71fde..984de976225d 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -372,8 +372,8 @@ SwTwips SwTextFrame::EmptyHeight() const
     }
     else
     {
-        SwFontAccess aFontAccess( &rTextNode.GetTextFormatColl(), pSh);
-        pFnt.reset(new SwFont( aFontAccess.Get()->GetFont() ));
+        const SwFontObj& rFontAccess = 
rTextNode.GetTextFormatColl().GetFontObj(pSh);
+        pFnt.reset(new SwFont( rFontAccess.GetFont() ));
         pFnt->CheckFontCacheId( pSh, pFnt->GetActual() );
     }
 
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 0cebaa0a83f9..90e05b183ca9 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -629,18 +629,18 @@ void SwAttrIter::InitFontAndAttrHandler(
         bool const*const pbVertLayoutLRBT)
 {
     // Build a font matching the default paragraph style:
-    SwFontAccess aFontAccess( &rPropsNode.GetTextFormatColl(), m_pViewShell );
+    const SwFontObj& rFontAccess = 
rPropsNode.GetTextFormatColl().GetFontObj(m_pViewShell);
     // It is possible that Init is called more than once, e.g., in a
     // SwTextFrame::FormatOnceMore situation or (since sw_redlinehide)
     // from SwAttrIter::Seek(); in the latter case SwTextSizeInfo::m_pFnt
     // is an alias of m_pFont so it must not be deleted!
     if (m_pFont)
     {
-        *m_pFont = aFontAccess.Get()->GetFont();
+        *m_pFont = rFontAccess.GetFont();
     }
     else
     {
-        m_pFont = new SwFont( aFontAccess.Get()->GetFont() );
+        m_pFont = new SwFont( rFontAccess.GetFont() );
     }
 
     // set font to vertical if frame layout is vertical
@@ -658,7 +658,7 @@ void SwAttrIter::InitFontAndAttrHandler(
     // If any further attributes for the paragraph are given in pAttrSet
     // consider them during construction of the default array, and apply
     // them to the font
-    m_aAttrHandler.Init(aFontAccess.Get()->GetDefault(), 
rTextNode.GetpSwAttrSet(),
+    m_aAttrHandler.Init(rFontAccess.GetDefault(), rTextNode.GetpSwAttrSet(),
            *rTextNode.getIDocumentSettingAccess(), m_pViewShell, *m_pFont,
            pbVertLayout ? *pbVertLayout : m_aAttrHandler.IsVertLayout(),
            bVertLayoutLRBT );
diff --git a/sw/source/core/text/txtinit.cxx b/sw/source/core/text/txtinit.cxx
index 98d85f9ebe8b..fbb5c70dd1e3 100644
--- a/sw/source/core/text/txtinit.cxx
+++ b/sw/source/core/text/txtinit.cxx
@@ -36,14 +36,12 @@ SwDropCapCache *pDropCapCache = nullptr;
 void TextInit_()
 {
     pFntCache = new SwFntCache; // Cache for SwSubFont -> SwFntObj = { Font 
aFont, Font* pScrFont, Font* pPrtFont, OutputDevice* pPrinter, ... }
-    pSwFontCache = new SwFontCache; // Cache for SwTextFormatColl -> SwFontObj 
= { SwFont aSwFont, SfxPoolItem* pDefaultArray }
     PROTOCOL_INIT
 }
 
 void TextFinit()
 {
     PROTOCOL_STOP
-    delete pSwFontCache;
     delete pFntCache;
     delete pContourCache;
     SwDropPortion::DeleteDropCapCache();
diff --git a/sw/source/core/txtnode/swfntcch.cxx 
b/sw/source/core/txtnode/swfntcch.cxx
index 34c796d4fbd0..0f1b8eb8a322 100644
--- a/sw/source/core/txtnode/swfntcch.cxx
+++ b/sw/source/core/txtnode/swfntcch.cxx
@@ -29,15 +29,11 @@
 // from atrstck.cxx
 extern const sal_uInt8 StackPos[];
 
-// FontCache is created in txtinit.cxx TextInit_ and deleted in TextFinit
-SwFontCache *pSwFontCache = nullptr;
-
-SwFontObj::SwFontObj( const SwTextFormatColl *pOwn, SwViewShell *pSh ) :
-    SwCacheObj( pOwn ),
-    m_aSwFont( &pOwn->GetAttrSet(), pSh ? &pSh->getIDocumentSettingAccess() : 
nullptr )
+SwFontObj::SwFontObj( const SwTextFormatColl *pOwner, SwViewShell *pSh ) :
+    m_aSwFont( &pOwner->GetAttrSet(), pSh ? &pSh->getIDocumentSettingAccess() 
: nullptr )
 {
     m_aSwFont.AllocFontCacheId( pSh, m_aSwFont.GetActual() );
-    const SwAttrSet& rAttrSet = pOwn->GetAttrSet();
+    const SwAttrSet& rAttrSet = pOwner->GetAttrSet();
     for (sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
         m_pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i );
 }
@@ -46,29 +42,4 @@ SwFontObj::~SwFontObj()
 {
 }
 
-SwFontAccess::SwFontAccess( const SwTextFormatColl *pOwn, SwViewShell *pSh ) :
-    SwCacheAccess( *pSwFontCache, pOwn, pOwn->IsInSwFntCache() ),
-    m_pShell( pSh )
-{
-}
-
-SwFontObj *SwFontAccess::Get( )
-{
-    return static_cast<SwFontObj *>( SwCacheAccess::Get( ) );
-}
-
-SwCacheObj *SwFontAccess::NewObj( )
-{
-    const_cast<SwTextFormatColl*>(static_cast<const 
SwTextFormatColl*>(m_pOwner))->SetInSwFntCache();
-    return new SwFontObj( static_cast<const SwTextFormatColl*>(m_pOwner), 
m_pShell );
-}
-
-SAL_DLLPUBLIC_EXPORT void FlushFontCache()
-{
-    if (pSwFontCache)
-        pSwFontCache->Flush();
-    if (pFntCache)
-        pFntCache->Flush();
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/swhtml.cxx b/sw/source/filter/html/swhtml.cxx
index bbad5e302d3b..626ed1e19ac5 100644
--- a/sw/source/filter/html/swhtml.cxx
+++ b/sw/source/filter/html/swhtml.cxx
@@ -5651,21 +5651,8 @@ void HTMLReader::SetupFilterOptions()
         m_aNamespace = aNamespace;
 }
 
-namespace
-{
-    class FontCacheGuard
-    {
-    public:
-        ~FontCacheGuard()
-        {
-            FlushFontCache();
-        }
-    };
-}
-
 bool TestImportHTML(SvStream &rStream)
 {
-    FontCacheGuard aFontCacheGuard;
     HTMLReader aReader;
     aReader.m_pStream = &rStream;
 
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index 2c641edaac32..f16fcb74e26c 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -6175,21 +6175,8 @@ extern "C" SAL_DLLPUBLIC_EXPORT Reader* ImportDOC()
     return new WW8Reader;
 }
 
-namespace
-{
-    class FontCacheGuard
-    {
-    public:
-        ~FontCacheGuard()
-        {
-            FlushFontCache();
-        }
-    };
-}
-
 bool TestImportDOC(SvStream &rStream, const OUString &rFltName)
 {
-    FontCacheGuard aFontCacheGuard;
     std::unique_ptr<Reader> xReader(ImportDOC());
 
     rtl::Reference<SotStorage> xStorage;

Reply via email to