sw/inc/doc.hxx                          |    2 +
 sw/source/core/bastyp/init.cxx          |    4 +-
 sw/source/core/doc/doc.cxx              |   42 +++++++++++++++++++++--------
 sw/source/core/doc/docbasic.cxx         |   19 ++++++-------
 sw/source/core/doc/visiturl.cxx         |   46 +++++++++++++-------------------
 sw/source/core/unocore/unostyle.cxx     |   39 ++++++++++++++++-----------
 sw/source/filter/html/htmlflywriter.cxx |   19 +++----------
 sw/source/filter/ww8/wrtww8.cxx         |   26 ++++--------------
 8 files changed, 99 insertions(+), 98 deletions(-)

New commits:
commit 7f50471615fb1b083e6c4735892359d269573e81
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sat Sep 7 20:44:40 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Sun Sep 8 08:38:48 2024 +0200

    dont use GetItemSurrogates for gathering SwFormatINetFormat
    
    which is very expensive these days
    
    Change-Id: I7b552d9fec5e2971bb3c171b7dd132ee31b1a46e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173004
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index e09e51aeb0ca..e15ba644a546 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1428,6 +1428,8 @@ public:
     void DeleteAutoCorrExceptWord();
 
     const SwFormatINetFormat* FindINetAttr( std::u16string_view rName ) const;
+    /// Iterate over all SwFormatINetFormat, if the function returns false, 
iteration is stopped
+    SW_DLLPUBLIC void ForEachINetFormat( const std::function<bool(const 
SwFormatINetFormat&)>&  ) const;
 
     // Call into intransparent Basic; expect possible Return String.
     void ExecMacro( const SvxMacro& rMacro, OUString* pRet, SbxArray* pArgs );
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
index 0902b3fa3dad..123a893df3e4 100644
--- a/sw/source/core/bastyp/init.cxx
+++ b/sw/source/core/bastyp/init.cxx
@@ -340,7 +340,7 @@ ItemInfoPackage& getItemInfoPackageSwAttributes()
             // is not initialized and the translated resource strings would 
not be available.
             // Luckily this mechanism allows to also flag this ItemInfo as 
'incomplete' using
             // a nullptr as ItemPtr and implementing on-demand creation, see 
::getItemInfo
-            { RES_TXTATR_INETFMT, nullptr,  FN_TXTATR_INET, 
SFX_ITEMINFOFLAG_SUPPORT_SURROGATE },
+            { RES_TXTATR_INETFMT, nullptr,  FN_TXTATR_INET, 
SFX_ITEMINFOFLAG_NONE },
 
             { RES_TXTATR_CHARFMT, new SwFormatCharFormat( nullptr ),  0, 
SFX_ITEMINFOFLAG_NONE },
             { RES_TXTATR_CJK_RUBY, new SwFormatRuby( OUString() ),  
SID_ATTR_CHAR_CJK_RUBY, SFX_ITEMINFOFLAG_NONE },
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index 3eea7da62079..a52d1efd8f49 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -1273,23 +1273,43 @@ void SwDoc::InvalidateAutoCompleteFlag()
 
 const SwFormatINetFormat* SwDoc::FindINetAttr( std::u16string_view rName ) 
const
 {
-    ItemSurrogates aSurrogates;
-    GetAttrPool().GetItemSurrogates(aSurrogates, RES_TXTATR_INETFMT);
-    for (const SfxPoolItem* pItem : aSurrogates)
+    const SwFormatINetFormat* pRet = nullptr;
+    ForEachINetFormat(
+        [&pRet, &rName] (const SwFormatINetFormat& rFormatItem) -> bool
+        {
+            if( rFormatItem.GetName() == rName )
+            {
+                pRet = &rFormatItem;
+                return false;
+            };
+            return true;
+        });
+    return pRet;
+}
+
+/// Iterate over all SwFormatINetFormat, if the function returns false, 
iteration is stopped
+void SwDoc::ForEachINetFormat( const std::function<bool(const 
SwFormatINetFormat&)>& rFunc ) const
+{
+    SwNodeOffset nCount = GetNodes().Count();
+    for (SwNodeOffset i(0); i < nCount; ++i)
     {
-        const auto & rFormatItem = static_cast<const 
SwFormatINetFormat&>(*pItem);
-        if( rFormatItem.GetName() != rName )
+        SwNode* pNode = GetNodes()[i];
+        if (!pNode->IsTextNode())
             continue;
-        const SwTextINetFormat* pTextAttr = rFormatItem.GetTextINetFormat();
-        if( !pTextAttr )
+        SwTextNode* pTextNode = pNode->GetTextNode();
+        if (!pTextNode->HasHints())
             continue;
-        const SwTextNode* pTextNd = pTextAttr->GetpTextNode();
-        if( pTextNd && &pTextNd->GetNodes() == &GetNodes() )
+        SwpHints& rHints = pTextNode->GetSwpHints();
+        for (size_t j = 0; j < rHints.Count(); ++j)
         {
-            return &rFormatItem;
+            const SwTextAttr* pTextAttr = rHints.Get(j);
+            if (pTextAttr->Which() != RES_TXTATR_INETFMT)
+                continue;
+            const SwFormatINetFormat& rFormat = pTextAttr->GetINetFormat();
+            if (!rFunc(rFormat))
+                return;
         }
     }
-    return nullptr;
 }
 
 void SwDoc::Summary(SwDoc& rExtDoc, sal_uInt8 nLevel, sal_uInt8 nPara, bool 
bImpress)
diff --git a/sw/source/core/doc/docbasic.cxx b/sw/source/core/doc/docbasic.cxx
index 39cd7fe8f000..59d055e45ea8 100644
--- a/sw/source/core/doc/docbasic.cxx
+++ b/sw/source/core/doc/docbasic.cxx
@@ -140,17 +140,16 @@ sal_uInt16 SwDoc::CallEvent( SvMacroItemId nEvent, const 
SwCallMouseEvent& rCall
     case EVENT_OBJECT_INETATTR:
         if( bCheckPtr  )
         {
-            ItemSurrogates aSurrogates;
-            GetAttrPool().GetItemSurrogates(aSurrogates, RES_TXTATR_INETFMT);
-            for (const SfxPoolItem* pItem : aSurrogates)
-            {
-                const auto & rFormatItem = static_cast<const 
SwFormatINetFormat&>(*pItem);
-                if( SfxPoolItem::areSame(rCallEvent.PTR.pINetAttr, 
&rFormatItem) )
+            ForEachINetFormat(
+                [&rCallEvent, &bCheckPtr] (const SwFormatINetFormat& 
rFormatItem) -> bool
                 {
-                    bCheckPtr = false;       // misuse as a flag
-                    break;
-                }
-            }
+                    if( SfxPoolItem::areSame(rCallEvent.PTR.pINetAttr, 
&rFormatItem) )
+                    {
+                        bCheckPtr = false;       // misuse as a flag
+                        return false;
+                    }
+                    return true;
+                });
         }
         if( !bCheckPtr )
             pTable = rCallEvent.PTR.pINetAttr->GetMacroTable();
diff --git a/sw/source/core/doc/visiturl.cxx b/sw/source/core/doc/visiturl.cxx
index fa89ec4f7c2c..47b75ea1347d 100644
--- a/sw/source/core/doc/visiturl.cxx
+++ b/sw/source/core/doc/visiturl.cxx
@@ -57,38 +57,32 @@ void SwURLStateChanged::Notify( SfxBroadcaster& , const 
SfxHint& rHint )
         sBkmk = "#" + pIURL->GetMark();
 
     bool bAction = false, bUnLockView = false;
-    ItemSurrogates aSurrogates;
-    m_rDoc.GetAttrPool().GetItemSurrogates(aSurrogates, RES_TXTATR_INETFMT);
-    for (const SfxPoolItem* pItem : aSurrogates)
-    {
-        const SwFormatINetFormat& rFormatItem = static_cast<const 
SwFormatINetFormat&>(*pItem);
-        if( rFormatItem.GetValue() == sURL || ( !sBkmk.isEmpty() && 
rFormatItem.GetValue() == sBkmk ) )
+    m_rDoc.ForEachINetFormat(
+        [&sURL, &sBkmk, &bAction, &pESh, &bUnLockView] (const 
SwFormatINetFormat& rFormatItem) -> bool
         {
-            const SwTextINetFormat* pTextAttr = 
rFormatItem.GetTextINetFormat();
-            if (pTextAttr != nullptr)
+            if( rFormatItem.GetValue() == sURL || ( !sBkmk.isEmpty() && 
rFormatItem.GetValue() == sBkmk ) )
             {
+                const SwTextINetFormat* pTextAttr = 
rFormatItem.GetTextINetFormat();
                 const SwTextNode* pTextNd = pTextAttr->GetpTextNode();
-                if (pTextNd != nullptr)
+                if( !bAction && pESh )
                 {
-                    if( !bAction && pESh )
-                    {
-                        pESh->StartAllAction();
-                        bAction = true;
-                        bUnLockView = !pESh->IsViewLocked();
-                        pESh->LockView( true );
-                    }
-                    
const_cast<SwTextINetFormat*>(pTextAttr)->SetVisitedValid(false);
-                    const SwTextAttr* pAttr = pTextAttr;
-                    SwUpdateAttr aUpdateAttr(
-                        pAttr->GetStart(),
-                        *pAttr->End(),
-                        RES_FMT_CHG);
-
-                    
const_cast<SwTextNode*>(pTextNd)->TriggerNodeUpdate(sw::LegacyModifyHint(&aUpdateAttr,
 &aUpdateAttr));
+                    pESh->StartAllAction();
+                    bAction = true;
+                    bUnLockView = !pESh->IsViewLocked();
+                    pESh->LockView( true );
                 }
+                
const_cast<SwTextINetFormat*>(pTextAttr)->SetVisitedValid(false);
+                const SwTextAttr* pAttr = pTextAttr;
+                SwUpdateAttr aUpdateAttr(
+                    pAttr->GetStart(),
+                    *pAttr->End(),
+                    RES_FMT_CHG);
+
+                
const_cast<SwTextNode*>(pTextNd)->TriggerNodeUpdate(sw::LegacyModifyHint(&aUpdateAttr,
 &aUpdateAttr));
             }
-        }
-    }
+            return true;
+        });
+
 
     if( bAction )
         pESh->EndAllAction();
diff --git a/sw/source/filter/html/htmlflywriter.cxx 
b/sw/source/filter/html/htmlflywriter.cxx
index 31fabc882de3..a2ea1f86a35a 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -2240,23 +2240,14 @@ void SwHTMLWriter::AddLinkTarget( std::u16string_view 
aURL )
 
 void SwHTMLWriter::CollectLinkTargets()
 {
-    const SwTextINetFormat* pTextAttr;
-
-    ItemSurrogates aSurrogates;
-    m_pDoc->GetAttrPool().GetItemSurrogates(aSurrogates, RES_TXTATR_INETFMT);
-    for (const SfxPoolItem* pItem : aSurrogates)
-    {
-        const auto & rINetFormat = static_cast<const 
SwFormatINetFormat&>(*pItem);
-        const SwTextNode* pTextNd;
-
-        if( nullptr != ( pTextAttr = rINetFormat.GetTextINetFormat()) &&
-            nullptr != ( pTextNd = pTextAttr->GetpTextNode() ) &&
-            pTextNd->GetNodes().IsDocNodes() )
+    m_pDoc->ForEachINetFormat(
+        [this] (const SwFormatINetFormat& rINetFormat) -> bool
         {
             AddLinkTarget( rINetFormat.GetValue() );
-        }
-    }
+            return true;
+        });
 
+    ItemSurrogates aSurrogates;
     m_pDoc->GetAttrPool().GetItemSurrogates(aSurrogates, RES_URL);
     for (const SfxPoolItem* pItem : aSurrogates)
     {
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index 390cf2f0b226..b2cfddd9c58d 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -3368,26 +3368,14 @@ void 
MSWordExportBase::AddLinkTarget(std::u16string_view rURL)
 
 void MSWordExportBase::CollectOutlineBookmarks(const SwDoc &rDoc)
 {
-    ItemSurrogates aSurrogates;
-    rDoc.GetAttrPool().GetItemSurrogates(aSurrogates, RES_TXTATR_INETFMT);
-    for (const SfxPoolItem* pItem : aSurrogates)
-    {
-        const auto & rINetFormat = static_cast<const 
SwFormatINetFormat&>(*pItem);
-
-        const SwTextINetFormat* pTextAttr = rINetFormat.GetTextINetFormat();
-        if (!pTextAttr)
-            continue;
-
-        const SwTextNode* pTextNd = pTextAttr->GetpTextNode();
-        if (!pTextNd)
-            continue;
-
-        if (!pTextNd->GetNodes().IsDocNodes())
-            continue;
-
-        AddLinkTarget( rINetFormat.GetValue() );
-    }
+    rDoc.ForEachINetFormat(
+        [this] (const SwFormatINetFormat& rINetFormat) -> bool
+        {
+            AddLinkTarget( rINetFormat.GetValue() );
+            return true;
+        });
 
+    ItemSurrogates aSurrogates;
     rDoc.GetAttrPool().GetItemSurrogates(aSurrogates, RES_URL);
     for (const SfxPoolItem* pItem : aSurrogates)
     {
commit 1669fc8b94adf37e4a23feedc0fa486ac2592030
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sat Sep 7 20:06:06 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Sun Sep 8 08:38:38 2024 +0200

    dont use GetItemSurrogates for gathering SwFormatRuby
    
    which is very expensive these days
    
    Change-Id: I67a37cfdd758f843902dc76ebb5da34b76ad9853
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173003
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
index c4ba7f2a4394..0902b3fa3dad 100644
--- a/sw/source/core/bastyp/init.cxx
+++ b/sw/source/core/bastyp/init.cxx
@@ -343,7 +343,7 @@ ItemInfoPackage& getItemInfoPackageSwAttributes()
             { RES_TXTATR_INETFMT, nullptr,  FN_TXTATR_INET, 
SFX_ITEMINFOFLAG_SUPPORT_SURROGATE },
 
             { RES_TXTATR_CHARFMT, new SwFormatCharFormat( nullptr ),  0, 
SFX_ITEMINFOFLAG_NONE },
-            { RES_TXTATR_CJK_RUBY, new SwFormatRuby( OUString() ),  
SID_ATTR_CHAR_CJK_RUBY, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE },
+            { RES_TXTATR_CJK_RUBY, new SwFormatRuby( OUString() ),  
SID_ATTR_CHAR_CJK_RUBY, SFX_ITEMINFOFLAG_NONE },
             { RES_TXTATR_UNKNOWN_CONTAINER, new SvXMLAttrContainerItem( 
RES_TXTATR_UNKNOWN_CONTAINER ),  0, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE },
             { RES_TXTATR_INPUTFIELD, createSwFormatFieldForItemInfoPackage( 
RES_TXTATR_INPUTFIELD ),  0, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE },
             { RES_TXTATR_CONTENTCONTROL, new SwFormatContentControl( 
RES_TXTATR_CONTENTCONTROL ),  0, SFX_ITEMINFOFLAG_NONE },
diff --git a/sw/source/core/unocore/unostyle.cxx 
b/sw/source/core/unocore/unostyle.cxx
index 3cc2533c7137..a6dbf2aeffd2 100644
--- a/sw/source/core/unocore/unostyle.cxx
+++ b/sw/source/core/unocore/unostyle.cxx
@@ -119,6 +119,8 @@
 #include <hints.hxx>
 #include <uiitems.hxx>
 #include <unoxstyle.hxx>
+#include <ndtxt.hxx>
+#include <txatbase.hxx>
 
 #include <cassert>
 #include <memory>
@@ -3865,24 +3867,29 @@ SwAutoStylesEnumImpl::SwAutoStylesEnumImpl( SwDoc& 
rInitDoc, IStyleAccess::SwAut
         std::set< std::pair< sal_uInt16, text::RubyAdjust > > aRubyMap;
         SwAttrPool& rAttrPool = m_rDoc.GetAttrPool();
 
-        // do this in two phases otherwise we invalidate the iterators when we 
insert into the pool
-        std::vector<const SwFormatRuby*> vRubyItems;
-        ItemSurrogates aSurrogates;
-        rAttrPool.GetItemSurrogates(aSurrogates, RES_TXTATR_CJK_RUBY);
-        for (const SfxPoolItem* pItem : aSurrogates)
+        SwNodeOffset nCount = m_rDoc.GetNodes().Count();
+        for (SwNodeOffset i(0); i < nCount; ++i)
         {
-            const auto & rRubyItem = static_cast<const SwFormatRuby&>(*pItem);
-            if ( rRubyItem.GetTextRuby() )
-                vRubyItems.push_back(&rRubyItem);
-        }
-        for (const SwFormatRuby* pRubyItem : vRubyItems)
-        {
-            std::pair< sal_uInt16, text::RubyAdjust > aPair( 
pRubyItem->GetPosition(), pRubyItem->GetAdjustment() );
-            if ( aRubyMap.insert( aPair ).second )
+            SwNode* pNode = m_rDoc.GetNodes()[i];
+            if (!pNode->IsTextNode())
+                continue;
+            SwTextNode* pTextNode = pNode->GetTextNode();
+            if (!pTextNode->HasHints())
+                continue;
+            SwpHints& rHints = pTextNode->GetSwpHints();
+            for (size_t j = 0; j < rHints.Count(); ++j)
             {
-                auto pItemSet = 
std::make_shared<SfxItemSetFixed<RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY>>( 
rAttrPool );
-                pItemSet->Put( *pRubyItem );
-                mAutoStyles.push_back( pItemSet );
+                const SwTextAttr* pTextAttr = rHints.Get(j);
+                if (pTextAttr->Which() != RES_TXTATR_CJK_RUBY)
+                    continue;
+                const SwFormatRuby& rRubyItem = pTextAttr->GetRuby();
+                std::pair< sal_uInt16, text::RubyAdjust > aPair( 
rRubyItem.GetPosition(), rRubyItem.GetAdjustment() );
+                if ( aRubyMap.insert( aPair ).second )
+                {
+                    auto pItemSet = 
std::make_shared<SfxItemSetFixed<RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY>>( 
rAttrPool );
+                    pItemSet->Put( rRubyItem );
+                    mAutoStyles.push_back( pItemSet );
+                }
             }
         }
     }

Reply via email to