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 a8f058e8ab02643ac2c8d6b6d8fcb3ab45fcf79f 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: Sun Mar 10 13:57:34 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 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);