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 ); + } } } }