sw/inc/IMark.hxx | 5 ++++- sw/inc/contentindex.hxx | 32 ++++++++++++++++++++++---------- sw/inc/pam.hxx | 3 +-- sw/inc/redline.hxx | 8 +++++--- sw/source/core/bastyp/index.cxx | 18 ++++++------------ sw/source/core/crsr/bookmark.cxx | 6 +++--- sw/source/core/doc/docnew.cxx | 4 ++-- sw/source/core/doc/docredln.cxx | 16 ++++++++-------- sw/source/core/text/porlay.cxx | 4 +++- sw/source/core/text/porrst.cxx | 4 +++- sw/source/core/txtnode/ndtxt.cxx | 13 ++++++++----- sw/source/core/unocore/unoportenum.cxx | 4 +++- 12 files changed, 68 insertions(+), 49 deletions(-)
New commits: commit f0a080babb9ae7bdd9eebc29343017606c5e18bf Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Wed Aug 7 21:44:17 2024 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Mon Aug 12 13:08:42 2024 +0200 SwContentIndex owner pointers we already have two things that "own" a SwContentIndex, for which we store a pointer in the SwContentIndex. I want to add more things, so rather than add more fields to a very heavily used structure, generalise the mechanism so we can store a single field (since only thing at a time will ever own a SwContentIndex). Also add an enum and a GetOwnerType() method so I can avoid dynamic_cast, this is a pretty performance-sensitive area. Change-Id: Ifb03a06b0bb69a325f41a8041e9d23cfc82c3268 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171606 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/sw/inc/IMark.hxx b/sw/inc/IMark.hxx index 8aea5ea991f0..1a5aed926bfb 100644 --- a/sw/inc/IMark.hxx +++ b/sw/inc/IMark.hxx @@ -52,9 +52,12 @@ namespace sw::mark }; class SW_DLLPUBLIC MarkBase - : virtual public sw::BroadcastingModify // inherited as interface + : public ISwContentIndexOwner, + virtual public sw::BroadcastingModify // inherited as interface { public: + virtual SwContentIndexOwnerType GetOwnerType() const override final { return SwContentIndexOwnerType::Mark; } + //getters SwPosition& GetMarkPos() const { return const_cast<SwPosition&>(*m_oPos1); } diff --git a/sw/inc/contentindex.hxx b/sw/inc/contentindex.hxx index c433782d7e38..6e62d7538401 100644 --- a/sw/inc/contentindex.hxx +++ b/sw/inc/contentindex.hxx @@ -32,6 +32,17 @@ class SwRangeRedline; namespace sw::mark { class MarkBase; } +/// enum to allow us to cast without dynamic_cast (for performance) +enum class SwContentIndexOwnerType { Redline, Mark }; + +/// Pure abstract class for a pointer to something that "owns" a SwContentIndex +class ISwContentIndexOwner +{ +public: + virtual ~ISwContentIndexOwner(); + virtual SwContentIndexOwnerType GetOwnerType() const = 0; +}; + /// Marks a character position inside a document model content node (SwContentNode) class SAL_WARN_UNUSED SW_DLLPUBLIC SwContentIndex { @@ -44,11 +55,11 @@ private: SwContentIndex * m_pNext; SwContentIndex * m_pPrev; - /// points to the SwRangeRedline (if any) that contains this SwContentIndex, via SwPosition and SwPaM - SwRangeRedline * m_pRangeRedline = nullptr; - - /// Pointer to a mark that owns this position to allow fast lookup of marks of an SwContentIndexReg. - const sw::mark::MarkBase* m_pMark; + /// This is either + /// (*) nullptr + /// (*) the SwRangeRedline (if any) that contains this SwContentIndex, via SwPosition and SwPaM + /// (*) the sw::mark::MarkBase that owns this position to allow fast lookup of marks of an SwContentIndexReg. + ISwContentIndexOwner * m_pOwner = nullptr; SwContentIndex& ChgValue( const SwContentIndex& rIdx, sal_Int32 nNewValue ); void Init(sal_Int32 const nIdx); @@ -103,11 +114,12 @@ public: const SwContentNode* GetContentNode() const { return m_pContentNode; } const SwContentIndex* GetNext() const { return m_pNext; } - const sw::mark::MarkBase* GetMark() const { return m_pMark; } - void SetMark(const sw::mark::MarkBase* pMark); - - SwRangeRedline* GetRedline() const { return m_pRangeRedline; } - void SetRedline(SwRangeRedline* pRangeRedline) { m_pRangeRedline = pRangeRedline; } + ISwContentIndexOwner* GetOwner() const { return m_pOwner; } + void SetOwner(ISwContentIndexOwner* pOwner) + { + assert(m_pOwner == nullptr && "there can be only one owner"); + m_pOwner = pOwner; + } }; SW_DLLPUBLIC std::ostream& operator <<(std::ostream& s, const SwContentIndex& index); diff --git a/sw/inc/pam.hxx b/sw/inc/pam.hxx index c9bffacb2d65..0fe773aa95b8 100644 --- a/sw/inc/pam.hxx +++ b/sw/inc/pam.hxx @@ -83,8 +83,7 @@ struct SAL_WARN_UNUSED SW_DLLPUBLIC SwPosition const SwContentNode* GetContentNode() const { return nContent.GetContentNode(); } sal_Int32 GetContentIndex() const { return nContent.GetIndex(); } - void SetMark(const sw::mark::MarkBase* pMark) { nContent.SetMark(pMark); } - void SetRedline(SwRangeRedline* pRangeRedline) { nContent.SetRedline(pRangeRedline); } + void SetOwner(ISwContentIndexOwner* pOwner) { nContent.SetOwner(pOwner); } /// These all set both nNode and nContent void Assign( const SwNode& rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset = 0 ); diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx index ef7c8129ce6a..06ea78c6d37e 100644 --- a/sw/inc/redline.hxx +++ b/sw/inc/redline.hxx @@ -161,7 +161,7 @@ public: void dumpAsXml(xmlTextWriterPtr pWriter) const; }; -class SAL_DLLPUBLIC_RTTI SwRangeRedline final : public SwPaM +class SAL_DLLPUBLIC_RTTI SwRangeRedline final : public SwPaM, public ISwContentIndexOwner { SwRedlineData* m_pRedlineData; std::optional<SwNodeIndex> m_oContentSect; @@ -187,12 +187,14 @@ public: SwPaM( rPos ), m_pRedlineData( pData ), m_nId( s_nLastId++ ), m_bDelLastPara( bDelLP ), m_bIsVisible( true ) { - GetBound().SetRedline(this); - GetBound(false).SetRedline(this); + GetBound().SetOwner(this); + GetBound(false).SetOwner(this); } SwRangeRedline( const SwRangeRedline& ); virtual ~SwRangeRedline() override; + virtual SwContentIndexOwnerType GetOwnerType() const override final { return SwContentIndexOwnerType::Redline; } + sal_uInt32 GetId() const { return m_nId; } const SwNodeIndex* GetContentIdx() const { return m_oContentSect ? &*m_oContentSect : nullptr; } // For Undo. diff --git a/sw/source/core/bastyp/index.cxx b/sw/source/core/bastyp/index.cxx index 4deeea8a7eb6..39eebfcd713e 100644 --- a/sw/source/core/bastyp/index.cxx +++ b/sw/source/core/bastyp/index.cxx @@ -24,12 +24,13 @@ #include <crossrefbookmark.hxx> +ISwContentIndexOwner::~ISwContentIndexOwner() {} + SwContentIndex::SwContentIndex(const SwContentNode * pContentNode, sal_Int32 const nIdx) : m_nIndex( nIdx ) , m_pContentNode( const_cast<SwContentNode*>(pContentNode) ) , m_pNext( nullptr ) , m_pPrev( nullptr ) - , m_pMark( nullptr ) { Init(m_nIndex); } @@ -38,7 +39,6 @@ SwContentIndex::SwContentIndex( const SwContentIndex& rIdx, short nDiff ) : m_pContentNode( rIdx.m_pContentNode ) , m_pNext( nullptr ) , m_pPrev( nullptr ) - , m_pMark( nullptr ) { ChgValue( rIdx, rIdx.m_nIndex + nDiff ); } @@ -48,7 +48,6 @@ SwContentIndex::SwContentIndex( const SwContentIndex& rIdx ) , m_pContentNode( rIdx.m_pContentNode ) , m_pNext( nullptr ) , m_pPrev( nullptr ) - , m_pMark( nullptr ) { ChgValue( rIdx, rIdx.m_nIndex ); } @@ -219,11 +218,6 @@ SwContentIndex& SwContentIndex::Assign( const SwContentNode* pArr, sal_Int32 nId return *this; } -void SwContentIndex::SetMark(const sw::mark::MarkBase* pMark) -{ - m_pMark = pMark; -} - SwContentIndexReg::SwContentIndexReg() : m_pFirst( nullptr ), m_pLast( nullptr ) { @@ -270,11 +264,11 @@ void SwContentIndexReg::Update( while( pStt ) { // HACK: avoid updating position of cross-ref bookmarks - if (!pStt->m_pMark || nullptr == dynamic_cast< - ::sw::mark::CrossRefBookmark const*>(pStt->m_pMark)) - { + if (pStt->m_pOwner && pStt->m_pOwner->GetOwnerType() == SwContentIndexOwnerType::Mark + && dynamic_cast< ::sw::mark::CrossRefBookmark const*>(pStt->m_pOwner)) + ; // do nothing + else pStt->m_nIndex = pStt->m_nIndex + nDiff; - } pStt = pStt->m_pNext; } } diff --git a/sw/source/core/crsr/bookmark.cxx b/sw/source/core/crsr/bookmark.cxx index 4e91f9ef987b..6f82c913735a 100644 --- a/sw/source/core/crsr/bookmark.cxx +++ b/sw/source/core/crsr/bookmark.cxx @@ -275,7 +275,7 @@ namespace sw::mark : m_oPos1(*aPaM.GetPoint()) , m_aName(std::move(aName)) { - m_oPos1->SetMark(this); + m_oPos1->SetOwner(this); lcl_FixPosition(*m_oPos1); if (aPaM.HasMark() && (*aPaM.GetMark() != *aPaM.GetPoint())) { @@ -298,13 +298,13 @@ namespace sw::mark void MarkBase::SetMarkPos(const SwPosition& rNewPos) { m_oPos1.emplace(rNewPos); - m_oPos1->SetMark(this); + m_oPos1->SetOwner(this); } void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos) { m_oPos2.emplace(rNewPos); - m_oPos2->SetMark(this); + m_oPos2->SetOwner(this); } OUString MarkBase::ToString( ) const diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx index 51a8a3ddd487..eb3c68a9c148 100644 --- a/sw/source/core/doc/docnew.cxx +++ b/sw/source/core/doc/docnew.cxx @@ -1145,9 +1145,9 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu IDocumentMarkAccess* pMarkAccess = getIDocumentMarkAccess(); for (const SwContentIndex* pIndex = pTextNode->GetFirstIndex(); pIndex; pIndex = pIndex->GetNext()) { - sw::mark::MarkBase* pMark = const_cast<sw::mark::MarkBase*>(pIndex->GetMark()); - if (!pMark) + if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark) continue; + sw::mark::MarkBase* pMark = static_cast<sw::mark::MarkBase*>(pIndex->GetOwner()); if (!aSeenMarks.insert(pMark).second) continue; } diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx index 53c833bf915d..dd1350c0e133 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -1408,8 +1408,8 @@ SwRangeRedline::SwRangeRedline(RedlineType eTyp, const SwPaM& rPam, sal_uInt32 n , m_nId( s_nLastId++ ) { - GetBound().SetRedline(this); - GetBound(false).SetRedline(this); + GetBound().SetOwner(this); + GetBound(false).SetOwner(this); m_bDelLastPara = false; m_bIsVisible = true; @@ -1432,8 +1432,8 @@ SwRangeRedline::SwRangeRedline( const SwRedlineData& rData, const SwPaM& rPam ) m_pRedlineData( new SwRedlineData( rData )), m_nId( s_nLastId++ ) { - GetBound().SetRedline(this); - GetBound(false).SetRedline(this); + GetBound().SetOwner(this); + GetBound(false).SetOwner(this); m_bDelLastPara = false; m_bIsVisible = true; @@ -1456,8 +1456,8 @@ SwRangeRedline::SwRangeRedline( const SwRedlineData& rData, const SwPosition& rP m_pRedlineData( new SwRedlineData( rData )), m_nId( s_nLastId++ ) { - GetBound().SetRedline(this); - GetBound(false).SetRedline(this); + GetBound().SetOwner(this); + GetBound(false).SetOwner(this); m_bDelLastPara = false; m_bIsVisible = true; @@ -1468,8 +1468,8 @@ SwRangeRedline::SwRangeRedline( const SwRangeRedline& rCpy ) m_pRedlineData( new SwRedlineData( *rCpy.m_pRedlineData )), m_nId( s_nLastId++ ) { - GetBound().SetRedline(this); - GetBound(false).SetRedline(this); + GetBound().SetOwner(this); + GetBound(false).SetOwner(this); m_bDelLastPara = false; m_bIsVisible = true; diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx index 2aec8f3b697f..c74310dda24a 100644 --- a/sw/source/core/text/porlay.cxx +++ b/sw/source/core/text/porlay.cxx @@ -2898,7 +2898,9 @@ void SwScriptInfo::selectHiddenTextProperty(const SwTextNode& rNode, for (const SwContentIndex* pIndex = rNode.GetFirstIndex(); pIndex; pIndex = pIndex->GetNext()) { - const sw::mark::MarkBase* pMark = pIndex->GetMark(); + if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark) + continue; + auto const pMark = static_cast<sw::mark::MarkBase const*>(pIndex->GetOwner()); const sw::mark::Bookmark* pBookmark = dynamic_cast<const sw::mark::Bookmark*>(pMark); if (pBookmarks && pBookmark) { diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx index ba1cafce975d..bec5faf41f9c 100644 --- a/sw/source/core/text/porrst.cxx +++ b/sw/source/core/text/porrst.cxx @@ -471,7 +471,9 @@ bool SwTextFrame::FormatEmpty() for (SwContentIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex(); pIndex; pIndex = pIndex->GetNext()) { - sw::mark::MarkBase const*const pMark = pIndex->GetMark(); + if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark) + continue; + auto const pMark = static_cast<sw::mark::MarkBase const*>(pIndex->GetOwner()); if (dynamic_cast<const sw::mark::Bookmark*>(pMark) != nullptr) { // need bookmark portions! return false; diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index e1d16d08114d..8c91d9c8b520 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -1450,9 +1450,12 @@ void SwTextNode::Update( const SwContentIndex* pContentNodeIndex = GetFirstIndex(); while (pContentNodeIndex) { - SwRangeRedline* pRedl = pContentNodeIndex->GetRedline(); - if (pRedl && (pRedl->HasMark() || this == &pRedl->GetPoint()->GetNode())) - vMyRedlines.insert(pRedl); + if (pContentNodeIndex->GetOwner() && pContentNodeIndex->GetOwner()->GetOwnerType() == SwContentIndexOwnerType::Redline) + { + auto pRedl = static_cast<SwRangeRedline*>(pContentNodeIndex->GetOwner()); + if (pRedl && (pRedl->HasMark() || this == &pRedl->GetPoint()->GetNode())) + vMyRedlines.insert(pRedl); + } pContentNodeIndex = pContentNodeIndex->GetNext(); } for (SwRangeRedline* pRedl : vMyRedlines) @@ -1497,9 +1500,9 @@ void SwTextNode::Update( for (const SwContentIndex* pIndex = GetFirstIndex(); pIndex; pIndex = next ) { next = pIndex->GetNext(); - const sw::mark::MarkBase* pMark = pIndex->GetMark(); - if (!pMark) + if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark) continue; + auto const pMark = static_cast<sw::mark::MarkBase const*>(pIndex->GetOwner()); // filter out ones that cannot match to reduce the max size of aSeenMarks const SwPosition* pMarkPos1 = &pMark->GetMarkPos(); const SwPosition* pMarkPos2 = pMark->IsExpanded() ? &pMark->GetOtherMarkPos() : nullptr; diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx index 1a9bb475af1c..33a17b85eeb9 100644 --- a/sw/source/core/unocore/unoportenum.cxx +++ b/sw/source/core/unocore/unoportenum.cxx @@ -204,8 +204,10 @@ namespace o3tl::sorted_vector<const sw::mark::MarkBase*> aSeenMarks; for (const SwContentIndex* pIndex = pTextNode->GetFirstIndex(); pIndex; pIndex = pIndex->GetNext()) { + if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark) + continue; // Need a non-cost mark here, as we'll create a UNO wrapper around it. - sw::mark::MarkBase* pBkmk = const_cast<sw::mark::MarkBase*>(pIndex->GetMark()); + sw::mark::MarkBase* pBkmk = static_cast<sw::mark::MarkBase*>(pIndex->GetOwner()); if (!pBkmk) continue; IDocumentMarkAccess::MarkType eType = IDocumentMarkAccess::GetType(*pBkmk);