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

New commits:
commit 6c25216e461b624f556a1b2830ab0911d5df7daf
Author:     Sarper Akdemir <sarper.akdemir.ext...@allotropia.de>
AuthorDate: Wed Mar 6 13:48:14 2024 +0300
Commit:     Sarper Akdemir <sarper.akdemir.ext...@allotropia.de>
CommitDate: Thu Mar 7 15:07:27 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>

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 c70a2f1f4a2d..cb1e7f9f0b20 100644
--- a/include/svx/svdpage.hxx
+++ b/include/svx/svdpage.hxx
@@ -405,6 +405,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-ooxml4.cxx 
b/sd/qa/unit/export-tests-ooxml4.cxx
index 9ebb88208cc1..4c1e2ad1bccd 100644
--- a/sd/qa/unit/export-tests-ooxml4.cxx
+++ b/sd/qa/unit/export-tests-ooxml4.cxx
@@ -1095,6 +1095,51 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, 
testTdf157740_slideMasters)
     assertXPath(pXmlDocContent, 
"/p:sldMaster/p:sldLayoutIdLst/p:sldLayoutId"_ostr, 1);
 }
 
+CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, 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'])"_ostr);
+
+    // 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"_ostr);
+
+    assertXPath(
+        pXmlDocRels2,
+        
"(/rels:Relationships/rels:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout'])"_ostr);
+
+    // 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"_ostr);
+
+    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 c431d9868cb3..2cfd29be0fcc 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