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

Reply via email to