tdf#155512: sd: filter: eppt: add "SlideLayout" property to Slide Master

If it is importing all Slide Master from pptx file, unfortunately
it breaks the exporting to pptx due to save and reload unit test failures

According to the documentation
http://officeopenxml.com/prSlideLayout.php, so the file pptx has a
relationship Slide -> Slide Layout -> Slide Master

The Slide Layout is a template an unique to be reused
with Slide Master, so exporting requires to compare
the templates due to LibreOffice relation Slide -> Slide Master

Adjust unit test values:

SdOOXMLExportTest2::testTdf106867
revert adcde78935

SdOOXMLExportTest2::testTdf112280
revert adcde78935

SdOOXMLExportTest2::testThemeColors and
SdOOXMLExportTest3::testTdf114848
The file tdf84205.pptx does not contain theme2.xml,
and save and reload it does not caintain theme2.xml too
fix "An uncaught exception of type com.sun.star.container.NoSuchElementException"

Signed-off-by: Henry Castro <hcastro@collabora.com>
Change-Id: I622e9d5d68c406ff520387f3903808613d1cd3d9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158084
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158676
Tested-by: Jenkins
This commit is contained in:
Henry Castro
2023-10-31 12:01:43 +01:00
parent b3c12778aa
commit d590f094cc
7 changed files with 147 additions and 15 deletions
@@ -230,6 +230,9 @@ SlidePersistPtr PresentationFragmentHandler::importMasterSlide(const Reference<f
for (const auto& rEntry : *xMasterRelations)
{
if (!rEntry.second.maType.endsWith("relationships/slideLayout"))
continue;
aLayoutFragmentPath = xMasterRelations->getFragmentPathFromRelation(rEntry.second);
sal_Int32 nIndex;
@@ -286,6 +289,9 @@ SlidePersistPtr PresentationFragmentHandler::importMasterSlide(const Reference<f
pMasterPersistPtr->createBackground( rFilter );
pMasterPersistPtr->createXShapes( rFilter );
uno::Reference< beans::XPropertySet > xSet(pMasterPersistPtr->getPage(), uno::UNO_QUERY_THROW);
xSet->setPropertyValue("SlideLayout", Any(pMasterPersistPtr->getLayoutFromValueToken()));
oox::drawingml::ThemePtr pTheme = pMasterPersistPtr->getTheme();
if (pTheme)
{
+3 -3
View File
@@ -1313,7 +1313,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testTdf106867)
"/p:sld/p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/"
"p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:cmd/"
"p:cBhvr/p:tgtEl/p:spTgt",
"spid", "491");
"spid", "42");
}
CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testTdf112280)
@@ -1694,7 +1694,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testAccentColor)
"70ad47");
xmlDocUniquePtr pXmlDocTheme2 = parseExport("ppt/theme/theme2.xml");
assertXPath(pXmlDocTheme2, "/a:theme/a:themeElements/a:clrScheme/a:accent6/a:srgbClr", "val",
"70ad47");
"deb340");
// Without the accompanying fix in place, this test would have failed with:
// - Expected: Motyw pakietu Office
@@ -1709,7 +1709,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testThemeColors)
createSdImpressDoc("pptx/tdf84205.pptx");
save("Impress Office Open XML");
xmlDocUniquePtr pXmlDocTheme2 = parseExport("ppt/theme/theme2.xml");
xmlDocUniquePtr pXmlDocTheme2 = parseExport("ppt/theme/theme1.xml");
assertXPath(pXmlDocTheme2, "/a:theme/a:themeElements/a:clrScheme/a:dk2/a:srgbClr", "val",
"44546a");
assertXPath(pXmlDocTheme2, "/a:theme/a:themeElements/a:clrScheme/a:accent3/a:srgbClr", "val",
-4
View File
@@ -75,10 +75,6 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf114848)
xmlDocUniquePtr pXmlDocTheme1 = parseExport("ppt/theme/theme1.xml");
assertXPath(pXmlDocTheme1, "/a:theme/a:themeElements/a:clrScheme/a:dk2/a:srgbClr", "val",
"1f497d");
xmlDocUniquePtr pXmlDocTheme2 = parseExport("ppt/theme/theme2.xml");
assertXPath(pXmlDocTheme2, "/a:theme/a:themeElements/a:clrScheme/a:dk2/a:srgbClr", "val",
"1f497d");
}
CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf147586)
+4
View File
@@ -131,6 +131,8 @@ private:
css::uno::Reference<css::drawing::XShape> GetReferencedPlaceholderXShape(const PlaceholderType eType, PageType ePageType) const;
void WritePlaceholderReferenceShapes(PowerPointShapeExport& rDML, PageType ePageType);
long FindEquivalentMasterPage(SdrPage* pMasterPage) const;
/// Should we export as .pptm, ie. do we contain macros?
bool mbPptm;
@@ -140,12 +142,14 @@ private:
::sax_fastparser::FSHelperPtr mPresentationFS;
LayoutInfo mLayoutInfo[EPP_LAYOUT_SIZE];
std::vector<std::pair<SdrPage*, size_t>> mpSlidesMaster;
std::vector< ::sax_fastparser::FSHelperPtr > mpSlidesFSArray;
sal_Int32 mnLayoutFileIdMax;
sal_uInt32 mnSlideIdMax;
sal_uInt32 mnSlideMasterIdMax;
sal_uInt32 mnAnimationNodeIdMax;
sal_uInt32 mnThemeIdMax;
sal_uInt32 mnDiagramId;
+122 -6
View File
@@ -25,6 +25,8 @@
#include <oox/ole/vbaproject.hxx>
#include "epptooxml.hxx"
#include <oox/export/shapes.hxx>
#include <svx/svdlayer.hxx>
#include <unokywds.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/storagehelper.hxx>
@@ -40,6 +42,8 @@
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/XDrawPages.hpp>
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <com/sun/star/drawing/XMasterPageTarget.hpp>
#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/geometry/RealPoint2D.hpp>
#include <com/sun/star/office/XAnnotationEnumeration.hpp>
@@ -388,6 +392,7 @@ PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContex
, mnSlideIdMax(1 << 8)
, mnSlideMasterIdMax(1U << 31)
, mnAnimationNodeIdMax(1)
, mnThemeIdMax(0)
, mnDiagramId(1)
, mbCreateNotes(false)
, mnPlaceholderIndexMax(1)
@@ -1491,8 +1496,111 @@ void PowerPointExport::AddLayoutIdAndRelation(const FSHelperPtr& pFS, sal_Int32
FSNS(XML_r, XML_id), sRelId);
}
static bool lcl_ContainsEquivalentObject(SdrPage* pPage, SdrObject* pObj)
{
bool bFound = false;
SdrObject* pObjNext;
if (!pPage || !pObj)
return bFound;
for (size_t nObj = 0; nObj < pPage->GetObjCount(); ++nObj)
{
pObjNext = pPage->GetObj(nObj);
if (pObjNext && pObjNext->GetMergedItemSet().Equals(
pObj->GetMergedItemSet(), false))
{
bFound = true;
break;
}
}
return bFound;
}
static bool lcl_ComparePageObjects(SdrPage* pMasterPage, SdrPage* pMasterNext)
{
if (!pMasterPage || !pMasterNext)
return false;
bool bFound = true;
SdrObject* pObjNext;
SdrLayerID aLayer =
pMasterNext->GetLayerAdmin().GetLayerID(sUNO_LayerName_background_objects);
for (size_t nObj = 0; nObj < pMasterPage->GetObjCount(); ++nObj)
{
pObjNext = pMasterPage->GetObj(nObj);
if (!pObjNext || pObjNext->GetLayer() == aLayer)
continue;
if (!lcl_ContainsEquivalentObject(pMasterNext, pObjNext))
{
bFound = false;
break;
}
}
return bFound;
}
long PowerPointExport::FindEquivalentMasterPage(SdrPage* pMasterPage) const
{
SdrPage* pMasterNext;
long nFound = -1;
if (!pMasterPage)
return nFound;
for (size_t nMaster = 0; nMaster < mpSlidesMaster.size(); ++nMaster)
{
pMasterNext = mpSlidesMaster[nMaster].first;
if (!pMasterNext)
continue;
if (pMasterNext->getSdrPageProperties().GetItemSet().Equals(
pMasterPage->getSdrPageProperties().GetItemSet(), false) &&
lcl_ComparePageObjects(pMasterPage, pMasterNext))
{
nFound = nMaster;
break;
}
}
return nFound;
}
void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPropertySet > const& aXBackgroundPropSet)
{
SdrPage* pMasterPage = SdPage::getImplementation(mXDrawPage);
if (!pMasterPage)
return;
uno::Reference<beans::XPropertySet> xPropSet(mXDrawPage, uno::UNO_QUERY_THROW);
if (!xPropSet.is())
return;
sal_Int32 nLayout = 0;
Any aLayout = xPropSet->getPropertyValue("SlideLayout");
long nFound = FindEquivalentMasterPage(pMasterPage);
if (aLayout.hasValue() && nFound != -1)
{
aLayout >>= nLayout;
size_t nOffset = GetPPTXLayoutId(nLayout);
if (mLayoutInfo[nOffset].mnFileIdArray.size() < mnMasterPages)
{
mLayoutInfo[nOffset].mnFileIdArray.resize(mnMasterPages);
}
mLayoutInfo[nOffset].mnFileIdArray[nPageNum] = mpSlidesMaster[nFound].second;
if (nPageNum == mnMasterPages - 1)
mPresentationFS->endElementNS(XML_p, XML_sldMasterIdLst);
return;
}
SAL_INFO("sd.eppt", "write master slide: " << nPageNum << "\n--------------");
// slides list
@@ -1515,7 +1623,7 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPro
OUString::number(nPageNum + 1) + ".xml",
"application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml");
SdrPage* pMasterPage = SdPage::getImplementation(mXDrawPage);
model::Theme* pTheme = nullptr;
if (pMasterPage)
{
@@ -1523,12 +1631,12 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPro
}
// write theme per master
WriteTheme(nPageNum, pTheme);
WriteTheme(mnThemeIdMax, pTheme);
// add implicit relation to the presentation theme
addRelation(pFS->getOutputStream(),
oox::getRelationship(Relationship::THEME),
Concat2View("../theme/theme" + OUString::number(nPageNum + 1) + ".xml"));
Concat2View("../theme/theme" + OUString::number(++mnThemeIdMax) + ".xml"));
pFS->startElementNS(XML_p, XML_sldMaster, PNMSS);
@@ -1572,6 +1680,13 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPro
}
}
if (aLayout.hasValue())
{
aLayout >>= nLayout;
mpSlidesMaster.push_back(std::make_pair(pMasterPage,
GetLayoutFileId(GetPPTXLayoutId(nLayout), nPageNum)));
}
pFS->endElementNS(XML_p, XML_sldLayoutIdLst);
pFS->endElementNS(XML_p, XML_sldMaster);
@@ -2270,10 +2385,11 @@ Reference<XShape> PowerPointExport::GetReferencedPlaceholderXShape(const Placeho
}
else
{
pMasterPage
= &static_cast<SdPage&>(SdPage::getImplementation(mXDrawPage)->TRG_GetMasterPage());
SdrPage* pPage = &SdPage::getImplementation(mXDrawPage)->TRG_GetMasterPage();
long nFound = FindEquivalentMasterPage(pPage);
pMasterPage = dynamic_cast<SdPage*>(nFound != -1 ? mpSlidesMaster[nFound].first : pPage);
}
if (SdrObject* pMasterFooter = pMasterPage->GetPresObj(ePresObjKind))
if (SdrObject* pMasterFooter = (pMasterPage ? pMasterPage->GetPresObj(ePresObjKind) : nullptr))
return GetXShapeForSdrObject(pMasterFooter);
}
return nullptr;
+1
View File
@@ -55,6 +55,7 @@ private:
SdrModel* mpSdrModel;
bool mbIsImpressDocument;
sal_Int16 mnTempPageNumber; // for printing handouts
css::uno::Any mSlideLayout; // import slide layout pptx
const SvxItemPropertySet* mpPropSet;
void UpdateModel();
+11 -2
View File
@@ -103,7 +103,8 @@ enum WID_PAGE
WID_PAGE_PAGENUMBERVISIBLE, WID_PAGE_DATETIMEVISIBLE, WID_PAGE_DATETIMEFIXED,
WID_PAGE_DATETIMETEXT, WID_PAGE_DATETIMEFORMAT, WID_TRANSITION_TYPE, WID_TRANSITION_SUBTYPE,
WID_TRANSITION_DIRECTION, WID_TRANSITION_FADE_COLOR, WID_TRANSITION_DURATION, WID_LOOP_SOUND,
WID_NAVORDER, WID_PAGE_PREVIEWMETAFILE, WID_PAGE_THEME, WID_PAGE_THEME_UNO_REPRESENTATION
WID_NAVORDER, WID_PAGE_PREVIEWMETAFILE, WID_PAGE_THEME, WID_PAGE_THEME_UNO_REPRESENTATION,
WID_PAGE_SLIDE_LAYOUT
};
}
@@ -284,7 +285,8 @@ static const SvxItemPropertySet* ImplGetMasterPagePropertySet( PageKind ePageKin
{ u"IsBackgroundDark"_ustr, WID_PAGE_ISDARK, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
{ u"Theme"_ustr, WID_PAGE_THEME, cppu::UnoType<util::XTheme>::get(), 0, 0},
// backwards compatible view of the theme for use in tests
{ u"ThemeUnoRepresentation"_ustr, WID_PAGE_THEME_UNO_REPRESENTATION, cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get(), 0, 0}
{ u"ThemeUnoRepresentation"_ustr, WID_PAGE_THEME_UNO_REPRESENTATION, cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get(), 0, 0},
{ u"SlideLayout"_ustr, WID_PAGE_SLIDE_LAYOUT, ::cppu::UnoType<sal_Int16>::get(), 0, 0}
};
static const SfxItemPropertyMapEntry aHandoutMasterPagePropertyMap_Impl[] =
@@ -591,6 +593,7 @@ void SAL_CALL SdGenericDrawPage::setPropertyValue( const OUString& aPropertyName
case WID_PAGE_TOP:
case WID_PAGE_BOTTOM:
case WID_PAGE_LAYOUT:
case WID_PAGE_SLIDE_LAYOUT:
case WID_PAGE_DURATION:
case WID_PAGE_CHANGE:
{
@@ -618,6 +621,9 @@ void SAL_CALL SdGenericDrawPage::setPropertyValue( const OUString& aPropertyName
case WID_PAGE_LAYOUT:
GetPage()->SetAutoLayout( static_cast<AutoLayout>(nValue), true );
break;
case WID_PAGE_SLIDE_LAYOUT:
mSlideLayout <<= nValue;
break;
case WID_PAGE_DURATION:
GetPage()->SetTime(nValue);
break;
@@ -1057,6 +1063,9 @@ Any SAL_CALL SdGenericDrawPage::getPropertyValue( const OUString& PropertyName )
case WID_PAGE_LAYOUT:
aAny <<= static_cast<sal_Int16>( GetPage()->GetAutoLayout() );
break;
case WID_PAGE_SLIDE_LAYOUT:
aAny = mSlideLayout;
break;
case WID_PAGE_NUMBER:
{
const sal_uInt16 nPageNumber(GetPage()->GetPageNum());