include/svx/sdrmasterpagedescriptor.hxx  |    3 +
 include/svx/sdrpageuser.hxx              |    3 +
 include/svx/svdpage.hxx                  |    1 
 sd/qa/unit/export-tests-ooxml3.cxx       |   47 +++++++++++++++++++++++++++++++
 sd/source/filter/eppt/pptx-epptooxml.cxx |   38 +++++++++++++++++++++----
 5 files changed, 84 insertions(+), 8 deletions(-)

New commits:
commit a20c366364bdfea41bd9063bd8801d5bb59c0092
Author:     Sarper Akdemir <sarper.akdemir.ext...@allotropia.de>
AuthorDate: Wed Mar 6 13:48:14 2024 +0300
Commit:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
CommitDate: Tue Mar 19 18:03:07 2024 +0100

    tdf#159931: pptx export: export each used slide layout for a master
    
    attempts to fix the slideLayout reference related regression
    from Idb6b88ebe87a83818d8eb27a1fa087652a002c0c.
    
    To correctly export the all used slideLayout instances for a
    given master, iterate through sdr::PageUsers of that master
    and figure out all used layouts.
    
    Change-Id: I0f58befac1ba4d5ec01aeedbb5f611c83683dcf8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164468
    Tested-by: Jenkins
    Reviewed-by: Balazs Varga <balazs.varga.ext...@allotropia.de>
    Reviewed-by: Sarper Akdemir <sarper.akdemir.ext...@allotropia.de>
    (cherry picked from commit a35831becee3781daf8628c48944660d31d84d8b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164542
    (cherry picked from commit a8f058e8ab02643ac2c8d6b6d8fcb3ab45fcf79f)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164670
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>

diff --git a/include/svx/sdrmasterpagedescriptor.hxx 
b/include/svx/sdrmasterpagedescriptor.hxx
index d7eac22a1b5c..9be1e663bcff 100644
--- a/include/svx/sdrmasterpagedescriptor.hxx
+++ b/include/svx/sdrmasterpagedescriptor.hxx
@@ -22,6 +22,7 @@
 
 #include <svx/sdrpageuser.hxx>
 #include <svx/svdsob.hxx>
+#include <svx/svxdllapi.h>
 #include <memory>
 
 class SdrPageProperties;
@@ -30,7 +31,7 @@ namespace sdr::contact { class ViewContact; }
 
 namespace sdr
 {
-    class MasterPageDescriptor final : public sdr::PageUser
+    class SVXCORE_DLLPUBLIC MasterPageDescriptor final : public sdr::PageUser
     {
     private:
         SdrPage&                                        maOwnerPage;
diff --git a/include/svx/sdrpageuser.hxx b/include/svx/sdrpageuser.hxx
index 8c31a2936c7e..5557b2729777 100644
--- a/include/svx/sdrpageuser.hxx
+++ b/include/svx/sdrpageuser.hxx
@@ -21,6 +21,7 @@
 #define INCLUDED_SVX_SDRPAGEUSER_HXX
 
 #include <vector>
+#include <svx/svxdllapi.h>
 
 class SdrPage;
 
@@ -30,7 +31,7 @@ class SdrPage;
 
 namespace sdr
 {
-    class PageUser
+    class SVXCORE_DLLPUBLIC PageUser
     {
     public:
         // this method is called from the destructor of the referenced page.
diff --git a/include/svx/svdpage.hxx b/include/svx/svdpage.hxx
index 6a65712719f1..76ab049055ca 100644
--- a/include/svx/svdpage.hxx
+++ b/include/svx/svdpage.hxx
@@ -398,6 +398,7 @@ private:
 public:
     void AddPageUser(sdr::PageUser& rNewUser);
     void RemovePageUser(sdr::PageUser& rOldUser);
+    const sdr::PageUserVector& GetPageUsers() const { return maPageUsers; };
 
     // SdrModel access on SdrPage level
     SdrModel& getSdrModelFromSdrPage() const { return mrSdrModelFromSdrPage; }
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx 
b/sd/qa/unit/export-tests-ooxml3.cxx
index 6a66e59af884..a0f36fe0688a 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -2011,6 +2011,53 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, 
testTableCellVerticalPropertyRoundtrip)
     assertXPath(pXml, "(//a:tcPr)[3]", "vert", "wordArtVert");
 }
 
+CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf159931_slideLayouts)
+{
+    createSdImpressDoc("odp/repeatBitmapMode.odp");
+    save("Impress Office Open XML");
+
+    xmlDocUniquePtr pXmlDocRels1 = 
parseExport("ppt/slides/_rels/slide1.xml.rels");
+    xmlDocUniquePtr pXmlDocRels2 = 
parseExport("ppt/slides/_rels/slide2.xml.rels");
+
+    assertXPath(pXmlDocRels1, 
"(/rels:Relationships/rels:Relationship[@Type='http://";
+                              
"schemas.openxmlformats.org/officeDocument/2006/relationships/"
+                              "slideLayout'])");
+
+    // the relative target e.g. "../slideLayouts/slideLayout2.xml"
+    OUString sRelativeLayoutPath1
+        = getXPathContent(pXmlDocRels1, 
"(/rels:Relationships/rels:Relationship[@Type='http://";
+                                        
"schemas.openxmlformats.org/officeDocument/2006/"
+                                        
"relationships/slideLayout'])/@Target");
+
+    assertXPath(pXmlDocRels2, 
"(/rels:Relationships/rels:Relationship[@Type='http://";
+                              
"schemas.openxmlformats.org/officeDocument/2006/relationships/"
+                              "slideLayout'])");
+
+    // the relative target e.g. "../slideLayouts/slideLayout1.xml"
+    OUString sRelativeLayoutPath2
+        = getXPathContent(pXmlDocRels2, 
"(/rels:Relationships/rels:Relationship[@Type='http://";
+                                        
"schemas.openxmlformats.org/officeDocument/2006/"
+                                        
"relationships/slideLayout'])/@Target");
+
+    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
+        = 
packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory),
+                                                      maTempFile.GetURL());
+
+    // Check that the referenced slideLayout files exist
+    // Without the accompanying fix in place, this test would have failed with:
+    // equality assertion failed
+    // - Expected: 1
+    // - Actual  : 0
+    // i.e. the referenced slideLayout file was missing on export.
+    OUString sSlideLayoutName1 = sRelativeLayoutPath1.getToken(2, '/');
+    OUString sSlideLayoutName2 = sRelativeLayoutPath2.getToken(2, '/');
+
+    CPPUNIT_ASSERT_EQUAL(true,
+                         bool(xNameAccess->hasByName("ppt/slideLayouts/" + 
sSlideLayoutName1)));
+    CPPUNIT_ASSERT_EQUAL(true,
+                         bool(xNameAccess->hasByName("ppt/slideLayouts/" + 
sSlideLayoutName2)));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx 
b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 0967b6a3b34e..2bf374c3d216 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -63,6 +63,7 @@
 #include "../ppt/pptanimations.hxx"
 
 #include <i18nlangtag/languagetag.hxx>
+#include <svx/sdrmasterpagedescriptor.hxx>
 #include <svx/svdpage.hxx>
 #include <svx/unoapi.hxx>
 #include <svx/svdogrp.hxx>
@@ -1515,23 +1516,48 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 
nPageNum, Reference< XPro
     // use master's id type as they have same range, mso does that as well
     pFS->startElementNS(XML_p, XML_sldLayoutIdLst);
 
-    sal_Int32 nLayout = 0;
-    OUString aSlideName;
-    css::uno::Reference< css::beans::XPropertySet >xPagePropSet;
+    auto getLayoutsUsedForMaster = [](SdrPage* pMaster) -> 
std::unordered_set<sal_Int32>
+    {
+        if (!pMaster)
+            return {};
+
+        std::unordered_set<sal_Int32> aUsedLayouts{};
+        for (const auto* pPageUser : pMaster->GetPageUsers())
+        {
+            const auto* pMasterPageDescriptor
+                = dynamic_cast<const sdr::MasterPageDescriptor*>(pPageUser);
+
+            if (!pMasterPageDescriptor)
+                continue;
+
+            AutoLayout eLayout
+                = 
static_cast<SdPage&>(pMasterPageDescriptor->GetOwnerPage()).GetAutoLayout();
+            aUsedLayouts.insert(eLayout);
+        }
+        return aUsedLayouts;
+    };
+
+    std::unordered_set<sal_Int32> aLayouts = 
getLayoutsUsedForMaster(pMasterPage);
+
+    css::uno::Reference< css::beans::XPropertySet > xPagePropSet;
     xPagePropSet.set(mXDrawPage, UNO_QUERY);
     if (xPagePropSet.is())
     {
         uno::Any aAny;
         if (GetPropertyValue(aAny, xPagePropSet, "SlideLayout"))
-            aAny >>= nLayout;
+            aLayouts.insert(aAny.get<sal_Int32>());
     }
 
+    OUString aSlideName;
     Reference< XNamed > xNamed(mXDrawPage, UNO_QUERY);
     if (xNamed.is())
         aSlideName = xNamed->getName();
 
-    ImplWritePPTXLayout(nLayout, nPageNum, aSlideName);
-    AddLayoutIdAndRelation(pFS, GetLayoutFileId(nLayout, nPageNum));
+    for (auto nLayout : aLayouts)
+    {
+        ImplWritePPTXLayout(nLayout, nPageNum, aSlideName);
+        AddLayoutIdAndRelation(pFS, GetLayoutFileId(nLayout, nPageNum));
+    }
 
     pFS->endElementNS(XML_p, XML_sldLayoutIdLst);
 

Reply via email to