sw/inc/section.hxx | 9 ++++++ sw/qa/extras/uiwriter/data/DUMMY2.odt |binary sw/qa/extras/uiwriter/data/DUMMY2B.odt |binary sw/qa/extras/uiwriter/data/tdf121119.odm |binary sw/qa/extras/uiwriter/uiwriter8.cxx | 30 +++++++++++++++++++++ sw/source/core/docnode/section.cxx | 44 ++++++++++++++++++++++++++++++- 6 files changed, 82 insertions(+), 1 deletion(-)
New commits: commit 2f135fa82c5d78ddafc14f38c0ee33358075b266 Author: László Németh <nem...@numbertext.org> AuthorDate: Wed Jan 22 20:36:03 2025 +0100 Commit: László Németh <nem...@numbertext.org> CommitDate: Thu Jan 23 17:28:07 2025 +0100 tdf#121119 master docs at-page anchor: fix missing images Images and other objects anchored at pages weren't imported from the subdocuments, resulting broken master document. Subdocuments are imported as sections of the master document, but their objects anchored at page need a document-level copy, not a section one. To calculate the new document-level page number of the copied object, store and sum the page count meta data of the previous subdocuments, added to the subdocument- level page number of the object. Note: the recent solution doesn't calculate with the own text content of the master document yet. As a workaround, to get the original page number exactly, store everything in subdocuments before the objects anchored at page. The problem is inherited from OpenOffice.org, see ooo#19131. Change-Id: I0be80bb27442565764142d2b23b0f56a3421c035 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180626 Tested-by: Jenkins Reviewed-by: László Németh <nem...@numbertext.org> diff --git a/sw/inc/section.hxx b/sw/inc/section.hxx index 0c45e470d247..b2f5fb53a54a 100644 --- a/sw/inc/section.hxx +++ b/sw/inc/section.hxx @@ -67,6 +67,7 @@ private: OUString m_sLinkFileName; OUString m_sLinkFilePassword; // Must be changed to Sequence. css::uno::Sequence <sal_Int8> m_Password; + sal_uInt16 m_nPage; // loaded meta page count for page anchored flys in master document /// It seems this flag caches the current final "hidden" state. bool m_bHiddenFlag : 1; @@ -133,6 +134,9 @@ public: bool IsConnectFlag() const { return m_bConnectFlag; } void SetConnectFlag(bool const bFlag){ m_bConnectFlag = bFlag; } + sal_uInt16 GetPageNum() const { return m_nPage; } + void SetPageNum(sal_uInt16 nPageNum){ m_nPage = nPageNum; } + void dumpAsXml(xmlTextWriterPtr pWriter) const; }; @@ -213,6 +217,11 @@ public: css::uno::Sequence<sal_Int8> const& GetPassword() const { return m_Data.GetPassword(); } + sal_uInt16 GetPageNum() const + { return m_Data.GetPageNum(); } + void SetPageNum(sal_uInt16 nPage) + { m_Data.SetPageNum(nPage); } + // Data server methods. void SetRefObject( SwServerObject* pObj ); const SwServerObject* GetObject() const { return m_RefObj.get(); } diff --git a/sw/qa/extras/uiwriter/data/DUMMY2.odt b/sw/qa/extras/uiwriter/data/DUMMY2.odt new file mode 100644 index 000000000000..9e616cc80767 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/DUMMY2.odt differ diff --git a/sw/qa/extras/uiwriter/data/DUMMY2B.odt b/sw/qa/extras/uiwriter/data/DUMMY2B.odt new file mode 100644 index 000000000000..92d6c15c51f1 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/DUMMY2B.odt differ diff --git a/sw/qa/extras/uiwriter/data/tdf121119.odm b/sw/qa/extras/uiwriter/data/tdf121119.odm new file mode 100644 index 000000000000..ea7784a20058 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf121119.odm differ diff --git a/sw/qa/extras/uiwriter/uiwriter8.cxx b/sw/qa/extras/uiwriter/uiwriter8.cxx index 63c17c5b74b5..deace483779b 100644 --- a/sw/qa/extras/uiwriter/uiwriter8.cxx +++ b/sw/qa/extras/uiwriter/uiwriter8.cxx @@ -2904,6 +2904,36 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf103612) "portion", u"Text after section"); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf121119) +{ + createSwGlobalDoc("tdf121119.odm"); + SwDoc* pDoc = getSwDoc(); + CPPUNIT_ASSERT_EQUAL( + size_t(2), pDoc->getIDocumentLinksAdministration().GetLinkManager().GetLinks().size()); + pDoc->getIDocumentLinksAdministration().GetLinkManager().UpdateAllLinks(false, false, nullptr, + u""_ustr); + + uno::Reference<text::XTextGraphicObjectsSupplier> xTextGraphicObjectsSupplier(mxComponent, + uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xIndexAccess( + xTextGraphicObjectsSupplier->getGraphicObjects(), uno::UNO_QUERY); + + // This was 0 (missing images anchored at page) + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xIndexAccess->getCount()); + + uno::Reference<drawing::XShape> xShape(xIndexAccess->getByIndex(0), uno::UNO_QUERY); + + CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_PAGE, + getProperty<text::TextContentAnchorType>(xShape, u"AnchorType"_ustr)); + + xmlDocUniquePtr pLayout = parseLayoutDump(); + // check page numbers of the objects anchored at page + assertXPath(pLayout, "/root/page[2]/anchored/fly/SwAnchoredObject", 1); + assertXPath(pLayout, "/root/page[4]/anchored/fly/SwAnchoredObject", 1); + assertXPath(pLayout, "/root/page[7]/anchored/fly/SwAnchoredObject", 1); + assertXPath(pLayout, "/root/page[9]/anchored/fly/SwAnchoredObject", 1); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf97899) { createSwDoc(); diff --git a/sw/source/core/docnode/section.cxx b/sw/source/core/docnode/section.cxx index 0fb7d171f6f8..0ef7e5705c6e 100644 --- a/sw/source/core/docnode/section.cxx +++ b/sw/source/core/docnode/section.cxx @@ -40,6 +40,9 @@ #include <IDocumentStylePoolAccess.hxx> #include <IDocumentState.hxx> #include <IDocumentLayoutAccess.hxx> +#include <IDocumentStatistics.hxx> +#include <docstat.hxx> +#include <fmtanchr.hxx> #include <node.hxx> #include <pam.hxx> #include <frmatr.hxx> @@ -95,6 +98,7 @@ namespace { SwSectionData::SwSectionData(SectionType const eType, OUString aName) : m_eType(eType) , m_sSectionName(std::move(aName)) + , m_nPage(0) , m_bHiddenFlag(false) , m_bProtectFlag(false) , m_bEditInReadonlyFlag(false) // edit in readonly sections @@ -112,6 +116,7 @@ SwSectionData::SwSectionData(SwSection const& rSection) , m_sLinkFileName(rSection.GetLinkFileName()) , m_sLinkFilePassword(rSection.GetLinkFilePassword()) , m_Password(rSection.GetPassword()) + , m_nPage(rSection.GetPageNum()) , m_bHiddenFlag(rSection.IsHiddenFlag()) , m_bProtectFlag(rSection.IsProtect()) // edit in readonly sections @@ -130,6 +135,7 @@ SwSectionData::SwSectionData(SwSectionData const& rOther) , m_sLinkFileName(rOther.m_sLinkFileName) , m_sLinkFilePassword(rOther.m_sLinkFilePassword) , m_Password(rOther.m_Password) + , m_nPage(rOther.GetPageNum()) , m_bHiddenFlag(rOther.m_bHiddenFlag) , m_bProtectFlag(rOther.m_bProtectFlag) // edit in readonly sections @@ -150,6 +156,7 @@ SwSectionData & SwSectionData::operator= (SwSectionData const& rOther) m_sLinkFilePassword = rOther.m_sLinkFilePassword; m_bConnectFlag = rOther.m_bConnectFlag; m_Password = rOther.m_Password; + m_nPage = rOther.m_nPage; m_bEditInReadonlyFlag = rOther.m_bEditInReadonlyFlag; m_bProtectFlag = rOther.m_bProtectFlag; @@ -173,7 +180,8 @@ bool SwSectionData::operator==(SwSectionData const& rOther) const && (m_bEditInReadonlyFlag == rOther.m_bEditInReadonlyFlag) && (m_sLinkFileName == rOther.m_sLinkFileName) && (m_sLinkFilePassword == rOther.m_sLinkFilePassword) - && (m_Password == rOther.m_Password); + && (m_Password == rOther.m_Password) + && (m_nPage == rOther.m_nPage); // FIXME: old code ignored m_bCondHiddenFlag m_bHiddenFlag m_bConnectFlag } @@ -1255,8 +1263,42 @@ static void lcl_UpdateLinksInSect( const SwBaseLink& rUpdLnk, SwSectionNode& rSe } } else if( pSrcDoc != pDoc ) + { + // store page count of the source document to calculate + // the physical page number of the objects anchored at page + const SwDocStat& rDStat = pSrcDoc->getIDocumentStatistics().GetDocStat(); + m_rSectFormat.GetSection()->SetPageNum(rDStat.nPage); + + // tdf#121119 keep objects anchored at page + auto pSrcFormats = pSrcDoc->GetSpzFrameFormats(); + sal_uInt32 nPrevPages = 0; + for( sw::SpzFrameFormat* pCpyFormat: *pSrcFormats) + { + SwFormatAnchor aAnchor( pCpyFormat->GetAnchor() ); + if ( RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId() ) + { + // sum page counts of the previous sections + if ( nPrevPages == 0 ) + { + const SwSectionFormats& rFormats = pDoc->GetSections(); + for( size_t n = 0; n < rFormats.size() && rFormats[n] != &m_rSectFormat; ++n ) + { + if ( const SwSection * pGlobalDocSection = rFormats[n]->GetGlobalDocSection() ) + nPrevPages += pGlobalDocSection->GetPageNum(); + } + } + + // set corrected physical page number of the object + aAnchor.SetPageNum( nPrevPages + aAnchor.GetPageNum() ); + + // copy object anchored at page to the target document + pDoc->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat, aAnchor, true, true ); + } + } + oCpyRg.emplace( pSrcDoc->GetNodes().GetEndOfExtras(), SwNodeOffset(2), pSrcDoc->GetNodes().GetEndOfContent() ); + } // #i81653# // Update links of extern linked document or extern linked