sd/qa/unit/data/pptx/tdf59323.pptx       |binary
 sd/qa/unit/export-tests-ooxml2.cxx       |   37 ++++
 sd/source/filter/eppt/epptooxml.hxx      |    3 
 sd/source/filter/eppt/pptx-epptooxml.cxx |  240 ++++++++++++++++++++++++++++++-
 4 files changed, 279 insertions(+), 1 deletion(-)

New commits:
commit c8321e9bb9e14b0b081cfd1fb21d0774c0e2632d
Author:     Sarper Akdemir <[email protected]>
AuthorDate: Wed Jun 9 08:24:12 2021 +0300
Commit:     Mike Kaganski <[email protected]>
CommitDate: Wed Jun 23 23:32:55 2021 +0200

    tdf#59323: pptx export: slide footers roundtrip unit test
    
    Roundtrip test that checks the slide footers, and their placeholder indexes.
    
    Change-Id: I9c4b819092ac6699617d71538c35b066d6e6f974
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117013
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117541
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sd/qa/unit/data/pptx/tdf59323.pptx 
b/sd/qa/unit/data/pptx/tdf59323.pptx
new file mode 100755
index 000000000000..0660c0af4f23
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf59323.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx 
b/sd/qa/unit/export-tests-ooxml2.cxx
index 27d42132557f..f9ad89a6272f 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -189,6 +189,7 @@ public:
     void testTdf132282();
     void testTdf128213ShapeRot();
     void testTdf96061_textHighlight();
+    void testTdf59323_slideFooters();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -296,6 +297,7 @@ public:
     CPPUNIT_TEST(testTdf132282);
     CPPUNIT_TEST(testTdf128213ShapeRot);
     CPPUNIT_TEST(testTdf96061_textHighlight);
+    CPPUNIT_TEST(testTdf59323_slideFooters);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -2788,6 +2790,41 @@ void SdOOXMLExportTest2::testTdf96061_textHighlight()
     CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aColor);
 }
 
+void SdOOXMLExportTest2::testTdf59323_slideFooters()
+{
+    ::sd::DrawDocShellRef xDocShRef
+        = 
loadURL(m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/tdf59323.pptx"), 
PPTX);
+
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+
+    uno::Reference<drawing::XDrawPagesSupplier> 
xDoc(xDocShRef->GetDoc()->getUnoModel(),
+                                                     uno::UNO_QUERY_THROW);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xDoc->getDrawPages()->getCount());
+
+    for (int nPageIndex = 0; nPageIndex < 3; nPageIndex++)
+    {
+        uno::Reference<drawing::XDrawPage> xPage(getPage(0, xDocShRef));
+        uno::Reference<beans::XPropertySet> xPropSet(xPage, uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(true, 
xPropSet->getPropertyValue("IsFooterVisible").get<bool>());
+        CPPUNIT_ASSERT_EQUAL(true, 
xPropSet->getPropertyValue("IsDateTimeVisible").get<bool>());
+        CPPUNIT_ASSERT_EQUAL(true, 
xPropSet->getPropertyValue("IsPageNumberVisible").get<bool>());
+    }
+
+    // Test placeholder indexes
+    xmlDocPtr pXmlDocMaster = parseExport(tempFile, 
"ppt/slideMasters/slideMaster1.xml");
+    assertXPath(pXmlDocMaster, "//p:ph [@type='dt']", "idx", "1");
+    assertXPath(pXmlDocMaster, "//p:ph [@type='ftr']", "idx", "2");
+    assertXPath(pXmlDocMaster, "//p:ph [@type='sldNum']", "idx", "3");
+
+    xmlDocPtr pXmlDocSlide1 = parseExport(tempFile, "ppt/slides/slide1.xml");
+    assertXPath(pXmlDocSlide1, "//p:ph [@type='dt']", "idx", "1");
+    assertXPath(pXmlDocSlide1, "//p:ph [@type='ftr']", "idx", "2");
+    assertXPath(pXmlDocSlide1, "//p:ph [@type='sldNum']", "idx", "3");
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit 8c43681f87e38aa5cedd16862bc7488ee8618e91
Author:     Sarper Akdemir <[email protected]>
AuthorDate: Wed Jun 9 08:21:27 2021 +0300
Commit:     Mike Kaganski <[email protected]>
CommitDate: Wed Jun 23 23:32:35 2021 +0200

    tdf#59323: pptx export: add support for slide footers
    
    Adds support for exporting slide footers to PPTX.
    
    Slide footers are exported as shapes that use placeholder indexes to refer 
to
    the shapes on master.
    
    To make the references work they are exported to layout slides too.
    
    Change-Id: I8bfde520b0aec66405523c719844e69c6fc15b79
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117012
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117540
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sd/source/filter/eppt/epptooxml.hxx 
b/sd/source/filter/eppt/epptooxml.hxx
index 0b9f5f5fd812..eefec66f0432 100644
--- a/sd/source/filter/eppt/epptooxml.hxx
+++ b/sd/source/filter/eppt/epptooxml.hxx
@@ -125,6 +125,9 @@ private:
         @returns Placeholder index
     */
     unsigned CreateNewPlaceholderIndex(const 
css::uno::Reference<css::drawing::XShape>& rXShape);
+    css::uno::Reference<css::drawing::XShape> 
GetReferencedPlaceholderXShape(const PlaceholderType eType, PageType ePageType) 
const;
+    void WritePlaceholderReferenceShapes(PowerPointShapeExport& rDML, PageType 
ePageType);
+
     /// Should we export as .pptm, ie. do we contain macros?
     bool mbPptm;
 
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx 
b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 2c7a0dc2fb94..e9b7e7a6dddd 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -28,6 +28,7 @@
 
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/storagehelper.hxx>
+#include <comphelper/xmltools.hxx>
 #include <sax/fshelper.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <sal/log.hxx>
@@ -52,6 +53,10 @@
 #include "pptx-animations.hxx"
 #include "../ppt/pptanimations.hxx"
 
+#include <svx/svdpage.hxx>
+#include <svx/unoapi.hxx>
+#include <sdpage.hxx>
+
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/document/XStorageBasedDocument.hpp>
 #include <utility>
@@ -109,7 +114,11 @@ public:
     ShapeExport&        WriteTextShape(const Reference< XShape >& xShape) 
override;
     ShapeExport&        WriteUnknownShape(const Reference< XShape >& xShape) 
override;
     ShapeExport&        WritePlaceholderShape(const Reference< XShape >& 
xShape, PlaceholderType ePlaceholder);
+    /** Writes a placeholder shape that references the placeholder on the 
master slide */
+    ShapeExport&        WritePlaceholderReferenceShape(PlaceholderType 
ePlaceholder, unsigned nReferencedPlaceholderIdx, PageType ePageType, 
Reference<XPropertySet>& rXPagePropSet);
     ShapeExport&        WritePageShape(const Reference< XShape >& xShape, 
PageType ePageType, bool bPresObj);
+    /** Writes textbody of a placeholder that references the placeholder on 
the master slide */
+    ShapeExport&        WritePlaceholderReferenceTextBody(PlaceholderType 
ePlaceholder, PageType ePageType, const Reference<XPropertySet> xPagePropSet);
 
     // helper parts
     bool WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType 
ePlaceholder, bool bMaster);
@@ -1440,6 +1449,8 @@ void PowerPointExport::WriteShapeTree(const FSHelperPtr& 
pFS, PageType ePageType
         }
     }
 
+    if ( ePageType == NORMAL || ePageType == LAYOUT )
+        WritePlaceholderReferenceShapes(aDML, ePageType);
     pFS->endElementNS(XML_p, XML_spTree);
 }
 
@@ -1505,13 +1516,146 @@ ShapeExport& 
PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
         WriteBlipFill(xProps, "Graphic");
     mpFS->endElementNS(XML_p, XML_spPr);
 
-    WriteTextBox(xShape, XML_p);
+    WriteTextBox(xShape, XML_p, bUsePlaceholderIndex);
+
+    mpFS->endElementNS(XML_p, XML_sp);
+
+    return *this;
+}
+
+ShapeExport& PowerPointShapeExport::WritePlaceholderReferenceShape(
+    PlaceholderType ePlaceholder, unsigned nReferencedPlaceholderIdx, PageType 
ePageType,
+    Reference<XPropertySet>& rXPagePropSet)
+{
+    mpFS->startElementNS(XML_p, XML_sp);
+
+    // non visual shape properties
+    mpFS->startElementNS(XML_p, XML_nvSpPr);
+    const OString aPlaceholderID("PlaceHolder " + 
OString::number(mnShapeIdMax++));
+    GetFS()->singleElementNS(XML_p, XML_cNvPr, XML_id, 
OString::number(mnShapeIdMax), XML_name,
+                             aPlaceholderID.getStr());
+
+    mpFS->startElementNS(XML_p, XML_cNvSpPr);
+    mpFS->singleElementNS(XML_a, XML_spLocks, XML_noGrp, "1");
+    mpFS->endElementNS(XML_p, XML_cNvSpPr);
+    mpFS->startElementNS(XML_p, XML_nvPr);
+
+    const char* pType = getPlaceholderTypeName(ePlaceholder);
+    mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType, XML_idx,
+                          OString::number(nReferencedPlaceholderIdx));
+    mpFS->endElementNS(XML_p, XML_nvPr);
+    mpFS->endElementNS(XML_p, XML_nvSpPr);
+
+    // visual shape properties
+    mpFS->startElementNS(XML_p, XML_spPr);
+    mpFS->endElementNS(XML_p, XML_spPr);
+
+    WritePlaceholderReferenceTextBody(ePlaceholder, ePageType, rXPagePropSet);
 
     mpFS->endElementNS(XML_p, XML_sp);
 
     return *this;
 }
 
+ShapeExport& PowerPointShapeExport::WritePlaceholderReferenceTextBody(
+    PlaceholderType ePlaceholder, PageType ePageType, const 
Reference<XPropertySet> xPagePropSet)
+{
+    mpFS->startElementNS(XML_p, XML_txBody);
+    mpFS->singleElementNS(XML_a, XML_bodyPr);
+    mpFS->startElementNS(XML_a, XML_p);
+
+    switch (ePlaceholder)
+    {
+        case Header:
+            break;
+        case Footer:
+        {
+            OUString aFooterText;
+            if (ePageType == LAYOUT)
+            {
+                aFooterText = "Footer";
+            }
+            else
+            {
+                xPagePropSet->getPropertyValue("FooterText") >>= aFooterText;
+            }
+            mpFS->startElementNS(XML_a, XML_r);
+            mpFS->startElementNS(XML_a, XML_t);
+            mpFS->writeEscaped(aFooterText);
+            mpFS->endElementNS(XML_a, XML_t);
+            mpFS->endElementNS(XML_a, XML_r);
+            break;
+        }
+        case SlideNumber:
+        {
+            OUString aSlideNum;
+            sal_Int32 nSlideNum = 0;
+            if (ePageType == LAYOUT)
+            {
+                aSlideNum = "<#>";
+            }
+            else
+            {
+                xPagePropSet->getPropertyValue("Number") >>= nSlideNum;
+                aSlideNum = OUString::number(nSlideNum);
+            }
+            OString aUUID(comphelper::xml::generateGUIDString());
+            mpFS->startElementNS(XML_a, XML_fld, XML_id, aUUID.getStr(), 
XML_type, "slidenum");
+            mpFS->startElementNS(XML_a, XML_t);
+            mpFS->writeEscaped(aSlideNum);
+            mpFS->endElementNS(XML_a, XML_t);
+            mpFS->endElementNS(XML_a, XML_fld);
+            break;
+        }
+        case DateAndTime:
+        {
+            OUString aDateTimeType = "datetime1";
+            bool bIsDateTimeFixed;
+            xPagePropSet->getPropertyValue("IsDateTimeFixed") >>= 
bIsDateTimeFixed;
+
+            if(ePageType != LAYOUT && !bIsDateTimeFixed)
+            {
+                sal_Int32 nDateTimeFormat;
+                xPagePropSet->getPropertyValue("DateTimeFormat") >>= 
nDateTimeFormat;
+
+                // 4 LSBs represent the date
+                SvxDateFormat eDate = 
static_cast<SvxDateFormat>(nDateTimeFormat & 0x0f);
+                // the 4 bits after the date bits represent the time
+                SvxTimeFormat eTime = 
static_cast<SvxTimeFormat>(nDateTimeFormat >> 4);
+                aDateTimeType = GetDatetimeTypeFromDateTime(eDate, eTime);
+
+                if (aDateTimeType == "datetime")
+                    aDateTimeType = "datetime1";
+            }
+
+            if(!bIsDateTimeFixed)
+            {
+                OString aUUID(comphelper::xml::generateGUIDString());
+                mpFS->startElementNS(XML_a, XML_fld, XML_id, aUUID.getStr(), 
XML_type, aDateTimeType.toUtf8());
+                mpFS->endElementNS(XML_a, XML_fld);
+            }
+            else
+            {
+                OUString aDateTimeText;
+                xPagePropSet->getPropertyValue("DateTimeText") >>= 
aDateTimeText;
+                mpFS->startElementNS(XML_a, XML_r);
+                mpFS->startElementNS(XML_a, XML_t);
+                mpFS->writeEscaped(aDateTimeText);
+                mpFS->endElementNS(XML_a, XML_t);
+                mpFS->endElementNS(XML_a, XML_r);
+            }
+            break;
+        }
+        default:
+            SAL_INFO("sd.eppt", "warning: no defined textbody for referenced 
placeholder type: "
+                                    << ePlaceholder);
+    }
+    mpFS->endElementNS(XML_a, XML_p);
+    mpFS->endElementNS(XML_p, XML_txBody);
+
+    return *this;
+}
+
 #define SYS_COLOR_SCHEMES "      <a:dk1>\
         <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
       </a:dk1>\
@@ -2020,12 +2164,106 @@ void PowerPointExport::WriteDiagram(const FSHelperPtr& 
pFS, PowerPointShapeExpor
     pFS->endElementNS(XML_p, XML_graphicFrame);
 }
 
+void PowerPointExport::WritePlaceholderReferenceShapes(PowerPointShapeExport& 
rDML, PageType ePageType)
+{
+    bool bCheckProps = ePageType == NORMAL;
+    Reference<XShape> xShape;
+    Any aAny;
+    OUString aText;
+    if (ePageType == LAYOUT
+        || (bCheckProps && PropValue::GetPropertyValue(aAny, mXPagePropSet, 
"IsFooterVisible", true)
+            && aAny == true && GetPropertyValue(aAny, mXPagePropSet, 
"FooterText", true)
+            && (aAny >>= aText) && !aText.isEmpty()))
+    {
+        if ((xShape = GetReferencedPlaceholderXShape(Footer, ePageType)))
+            rDML.WritePlaceholderReferenceShape(Footer,
+                                                
maPlaceholderShapeToIndexMap.find(xShape)->second,
+                                                ePageType, mXPagePropSet);
+    }
+
+    if (ePageType == LAYOUT
+        || (bCheckProps
+            && PropValue::GetPropertyValue(aAny, mXPagePropSet, 
"IsPageNumberVisible", true)
+            && aAny == true))
+    {
+        if ((xShape = GetReferencedPlaceholderXShape(SlideNumber, ePageType)))
+            rDML.WritePlaceholderReferenceShape(SlideNumber,
+                                                
maPlaceholderShapeToIndexMap.find(xShape)->second,
+                                                ePageType, mXPagePropSet);
+    }
+
+    if (ePageType == LAYOUT
+        || (bCheckProps
+            && PropValue::GetPropertyValue(aAny, mXPagePropSet, 
"IsDateTimeVisible", true)
+            && aAny == true
+            && ((GetPropertyValue(aAny, mXPagePropSet, "DateTimeText", true) 
&& (aAny >>= aText)
+                 && !aText.isEmpty())
+                || mXPagePropSet->getPropertyValue("IsDateTimeFixed") == 
false)))
+    {
+        if ((xShape = GetReferencedPlaceholderXShape(DateAndTime, ePageType)))
+            rDML.WritePlaceholderReferenceShape(DateAndTime,
+                                                
maPlaceholderShapeToIndexMap.find(xShape)->second,
+                                                ePageType, mXPagePropSet);
+    }
+}
+
 unsigned PowerPointExport::CreateNewPlaceholderIndex(const 
css::uno::Reference<XShape> &rXShape)
 {
     maPlaceholderShapeToIndexMap.insert({rXShape, mnPlaceholderIndexMax});
     return mnPlaceholderIndexMax++;
 }
 
+Reference<XShape> PowerPointExport::GetReferencedPlaceholderXShape(const 
PlaceholderType eType,
+                                                        PageType ePageType) 
const
+{
+    PresObjKind ePresObjKind = PresObjKind::PRESOBJ_NONE;
+    switch (eType)
+    {
+        case oox::core::None:
+            break;
+        case oox::core::SlideImage:
+            break;
+        case oox::core::Notes:
+            break;
+        case oox::core::Header:
+            ePresObjKind = PresObjKind::PRESOBJ_HEADER;
+            break;
+        case oox::core::Footer:
+            ePresObjKind = PresObjKind::PRESOBJ_FOOTER;
+            break;
+        case oox::core::SlideNumber:
+            ePresObjKind = PresObjKind::PRESOBJ_SLIDENUMBER;
+            break;
+        case oox::core::DateAndTime:
+            ePresObjKind = PresObjKind::PRESOBJ_DATETIME;
+            break;
+        case oox::core::Outliner:
+            break;
+        case oox::core::Title:
+            ePresObjKind = PresObjKind::PRESOBJ_TITLE;
+            break;
+        case oox::core::Subtitle:
+            break;
+    }
+    if (ePresObjKind != PresObjKind::PRESOBJ_NONE)
+    {
+        SdPage* pMasterPage;
+        if (ePageType == LAYOUT)
+        {
+            // since Layout pages do not have drawpages themselves - 
mXDrawPage is still the master they reference to..
+            pMasterPage = SdPage::getImplementation(mXDrawPage);
+        }
+        else
+        {
+            pMasterPage
+                = 
&static_cast<SdPage&>(SdPage::getImplementation(mXDrawPage)->TRG_GetMasterPage());
+        }
+        if (SdrObject* pMasterFooter = pMasterPage->GetPresObj(ePresObjKind))
+            return GetXShapeForSdrObject(pMasterFooter);
+    }
+    return nullptr;
+}
+
 // UNO component
 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
 css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,
_______________________________________________
Libreoffice-commits mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to