tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / sd / source / filter / eppt / pptx-epptooxml.cxx
blob01174b023902b2aae26420b7693e3d9f9c261cd0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stdio.h>
21 #include <oox/drawingml/clrscheme.hxx>
22 #include <oox/token/namespaces.hxx>
23 #include <oox/token/tokens.hxx>
24 #include <oox/token/relationship.hxx>
25 #include <oox/ole/vbaproject.hxx>
26 #include "epptooxml.hxx"
27 #include <oox/export/shapes.hxx>
29 #include <comphelper/sequenceashashmap.hxx>
30 #include <comphelper/storagehelper.hxx>
31 #include <comphelper/xmltools.hxx>
32 #include <sax/fshelper.hxx>
33 #include <rtl/ustrbuf.hxx>
34 #include <sal/log.hxx>
35 #include <tools/UnitConversion.hxx>
36 #include <tools/datetime.hxx>
37 #include <unotools/securityoptions.hxx>
38 #include <com/sun/star/animations/TransitionType.hpp>
39 #include <com/sun/star/animations/TransitionSubType.hpp>
40 #include <com/sun/star/beans/XPropertySetInfo.hpp>
41 #include <com/sun/star/drawing/FillStyle.hpp>
42 #include <com/sun/star/drawing/XDrawPages.hpp>
43 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
44 #include <com/sun/star/embed/ElementModes.hpp>
45 #include <com/sun/star/geometry/RealPoint2D.hpp>
46 #include <com/sun/star/office/XAnnotationEnumeration.hpp>
47 #include <com/sun/star/office/XAnnotationAccess.hpp>
48 #include <com/sun/star/presentation/AnimationSpeed.hpp>
49 #include <com/sun/star/util/DateTime.hpp>
50 #include <com/sun/star/task/XStatusIndicator.hpp>
51 #include <com/sun/star/frame/XModel.hpp>
52 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
53 #include <com/sun/star/presentation/XCustomPresentationSupplier.hpp>
54 #include <com/sun/star/container/XIndexContainer.hpp>
55 #include <com/sun/star/container/XNamed.hpp>
56 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
57 #include <comphelper/diagnose_ex.hxx>
59 #include <oox/export/utils.hxx>
60 #include <oox/export/ThemeExport.hxx>
61 #include <docmodel/theme/Theme.hxx>
63 #include "pptx-animations.hxx"
64 #include "../ppt/pptanimations.hxx"
66 #include <i18nlangtag/languagetag.hxx>
67 #include <svx/sdrmasterpagedescriptor.hxx>
68 #include <svx/svdpage.hxx>
69 #include <svx/unoapi.hxx>
70 #include <svx/svdogrp.hxx>
71 #include <svx/ColorSets.hxx>
72 #include <sdmod.hxx>
73 #include <sdpage.hxx>
75 #include <vcl/svapp.hxx>
76 #include <vcl/settings.hxx>
78 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
79 #include <com/sun/star/document/XStorageBasedDocument.hpp>
80 #include <utility>
81 #if OSL_DEBUG_LEVEL > 1
82 #include <com/sun/star/drawing/RectanglePoint.hpp>
83 #endif
85 // presentation namespaces
86 #define PNMSS FSNS(XML_xmlns, XML_a), this->getNamespaceURL(OOX_NS(dml)), \
87 FSNS(XML_xmlns, XML_p), this->getNamespaceURL(OOX_NS(ppt)), \
88 FSNS(XML_xmlns, XML_r), this->getNamespaceURL(OOX_NS(officeRel)), \
89 FSNS(XML_xmlns, XML_p14), this->getNamespaceURL(OOX_NS(p14)), \
90 FSNS(XML_xmlns, XML_p15), this->getNamespaceURL(OOX_NS(p15)), \
91 FSNS(XML_xmlns, XML_mc), this->getNamespaceURL(OOX_NS(mce))
93 // presentationPr namespace
94 #define PPRNMSS FSNS(XML_xmlns, XML_a), this->getNamespaceURL(OOX_NS(dml)), \
95 FSNS(XML_xmlns, XML_r), this->getNamespaceURL(OOX_NS(officeRel)), \
96 FSNS(XML_xmlns, XML_p), this->getNamespaceURL(OOX_NS(ppt))
98 using namespace ::com::sun::star;
99 using namespace ::com::sun::star::animations;
100 using namespace ::com::sun::star::beans;
101 using namespace ::com::sun::star::container;
102 using namespace ::com::sun::star::drawing;
103 using namespace ::com::sun::star::geometry;
104 using namespace ::com::sun::star::presentation;
105 using namespace ::com::sun::star::office;
106 using namespace ::com::sun::star::text;
107 using namespace ::com::sun::star::uno;
108 using namespace ::com::sun::star::util;
109 using namespace ::ppt;
110 using ::com::sun::star::beans::XPropertySet;
111 using ::com::sun::star::beans::XPropertySetInfo;
112 using ::sax_fastparser::FSHelperPtr;
113 using namespace oox::drawingml;
114 using namespace oox::core;
116 #if OSL_DEBUG_LEVEL > 1
117 void dump_pset(Reference< XPropertySet > const& rXPropSet);
118 #endif
120 namespace oox::core
123 class PowerPointShapeExport : public ShapeExport
125 PowerPointExport& mrExport;
126 PageType mePageType;
127 bool mbMaster;
128 public:
129 PowerPointShapeExport(FSHelperPtr pFS, ShapeHashMap* pShapeMap, PowerPointExport* pFB);
130 void SetMaster(bool bMaster);
131 void SetPageType(PageType ePageType);
132 ShapeExport& WriteNonVisualProperties(const Reference< XShape >& xShape) override;
133 ShapeExport& WriteTextShape(const Reference< XShape >& xShape) override;
134 ShapeExport& WriteUnknownShape(const Reference< XShape >& xShape) override;
135 ShapeExport& WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder);
136 /** Writes a placeholder shape that references the placeholder on the master slide */
137 ShapeExport& WritePlaceholderReferenceShape(PlaceholderType ePlaceholder, sal_Int32 nReferencedPlaceholderIdx, PageType ePageType, const Reference<XPropertySet>& rXPagePropSet);
138 ShapeExport& WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj);
139 /** Writes textbody of a placeholder that references the placeholder on the master slide */
140 ShapeExport& WritePlaceholderReferenceTextBody(PlaceholderType ePlaceholder, PageType ePageType, const Reference<XPropertySet>& xPagePropSet);
142 // helper parts
143 bool WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster);
147 namespace
149 void WriteSndAc(const FSHelperPtr& pFS, const OUString& sSoundRelId, const OUString& sSoundName)
151 pFS->startElementNS(XML_p, XML_sndAc);
152 pFS->startElementNS(XML_p, XML_stSnd);
153 pFS->singleElementNS(XML_p, XML_snd, FSNS(XML_r, XML_embed),
154 sax_fastparser::UseIf(sSoundRelId, !sSoundRelId.isEmpty()), XML_name,
155 sax_fastparser::UseIf(sSoundName, !sSoundName.isEmpty()));
156 pFS->endElement(FSNS(XML_p, XML_stSnd));
157 pFS->endElement(FSNS(XML_p, XML_sndAc));
160 const char* getPlaceholderTypeName(PlaceholderType ePlaceholder)
162 switch (ePlaceholder)
164 case SlideImage:
165 return "sldImg";
166 case Notes:
167 return "body";
168 case Header:
169 return "hdr";
170 case Footer:
171 return "ftr";
172 case SlideNumber:
173 return "sldNum";
174 case DateAndTime:
175 return "dt";
176 case Outliner:
177 return "body";
178 case Title:
179 return "title";
180 case Subtitle:
181 return "subTitle";
182 default:
183 SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
184 return "";
190 namespace {
192 struct PPTXLayoutInfo
194 int nType;
195 const char* sName;
196 const char* sType;
201 const PPTXLayoutInfo aLayoutInfo[OOXML_LAYOUT_SIZE] =
203 { 0, "Title Slide", "title" },
204 { 1, "Title and text", "tx" },
205 { 2, "Title and chart", "chart" },
206 { 3, "Title, text on left, text on right", "twoObj" },
207 { 4, "Title, text on left and chart on right", "txAndChart" },
208 { 6, "Title, text on left, clip art on right", "txAndClipArt" },
209 { 6, "Title, text on left, media on right", "txAndMedia" },
210 { 7, "Title, chart on left and text on right", "chartAndTx" },
211 { 8, "Title and table", "tbl" },
212 { 9, "Title, clipart on left, text on right", "clipArtAndTx" },
213 { 10, "Title, text on left, object on right", "txAndObj" },
214 { 1, "Title and object", "obj" },
215 { 12, "Title, text on left, two objects on right", "txAndTwoObj" },
216 { 13, "Title, object on left, text on right", "objAndTx" },
217 { 14, "Title, object on top, text on bottom", "objOverTx" },
218 { 15, "Title, two objects on left, text on right", "twoObjAndTx" },
219 { 16, "Title, two objects on top, text on bottom", "twoObjOverTx" },
220 { 17, "Title, text on top, object on bottom", "txOverObj" },
221 { 18, "Title and four objects", "fourObj" },
222 { 19, "Title Only", "titleOnly" },
223 { 20, "Blank Slide", "blank" },
224 { 21, "Vertical title on right, vertical text on top, chart on bottom", "vertTitleAndTxOverChart" },
225 { 22, "Vertical title on right, vertical text on left", "vertTitleAndTx" },
226 { 23, "Title and vertical text body", "vertTx" },
227 { 24, "Title, clip art on left, vertical text on right", "clipArtAndVertTx" },
228 { 20, "Title, two objects each with text", "twoTxTwoObj" },
229 { 15, "Title, two objects on left, one object on right", "twoObjAndObj" },
230 { 20, "Title, object and caption text", "objTx" },
231 { 20, "Title, picture, and caption text", "picTx" },
232 { 20, "Section header title and subtitle text", "secHead" },
233 { 32, "Object only", "objOnly" },
234 { 12, "Title, one object on left, two objects on right", "objAndTwoObj" },
235 { 20, "Title, media on left, text on right", "mediaAndTx" },
236 { 34, "Title, 6 Content", "blank" }, // not defined in OOXML => blank
237 { 2, "Title and diagram", "dgm" },
238 { 0, "Custom layout defined by user", "cust" },
241 PowerPointShapeExport::PowerPointShapeExport(FSHelperPtr pFS, ShapeHashMap* pShapeMap,
242 PowerPointExport* pFB)
243 : ShapeExport(XML_p, std::move(pFS), pShapeMap, pFB)
244 , mrExport(*pFB)
245 , mePageType(UNDEFINED)
246 , mbMaster(false)
250 void PowerPointShapeExport::SetMaster(bool bMaster)
252 mbMaster = bMaster;
255 void PowerPointShapeExport::SetPageType(PageType ePageType)
257 mePageType = ePageType;
260 ShapeExport& PowerPointShapeExport::WriteNonVisualProperties(const Reference< XShape >&)
262 GetFS()->singleElementNS(XML_p, XML_nvPr);
264 return *this;
267 ShapeExport& PowerPointShapeExport::WriteTextShape(const Reference< XShape >& xShape)
269 OUString sShapeType = xShape->getShapeType();
271 SAL_INFO("sd.eppt", "shape(text) : " << sShapeType.toUtf8());
273 if (sShapeType == "com.sun.star.drawing.TextShape" || sShapeType == "com.sun.star.drawing.GraphicObjectShape")
275 ShapeExport::WriteTextShape(xShape);
277 else if (sShapeType == "com.sun.star.presentation.DateTimeShape")
279 if (!WritePlaceholder(xShape, DateAndTime, mbMaster))
280 ShapeExport::WriteTextShape(xShape);
282 else if (sShapeType == "com.sun.star.presentation.FooterShape")
284 if (!WritePlaceholder(xShape, Footer, mbMaster))
285 ShapeExport::WriteTextShape(xShape);
287 else if (sShapeType == "com.sun.star.presentation.HeaderShape")
289 if (!WritePlaceholder(xShape, Header, mbMaster))
290 ShapeExport::WriteTextShape(xShape);
292 else if (sShapeType == "com.sun.star.presentation.NotesShape")
294 if (mePageType == NOTICE && mrExport.GetPresObj())
295 WritePlaceholderShape(xShape, Notes);
296 else
297 ShapeExport::WriteTextShape(xShape);
299 else if (sShapeType == "com.sun.star.presentation.OutlinerShape")
301 if (!WritePlaceholder(xShape, Outliner, mbMaster))
302 ShapeExport::WriteTextShape(xShape);
304 else if (sShapeType == "com.sun.star.presentation.SlideNumberShape")
306 if (!WritePlaceholder(xShape, SlideNumber, mbMaster))
307 ShapeExport::WriteTextShape(xShape);
309 else if (sShapeType == "com.sun.star.presentation.TitleTextShape")
311 if (!WritePlaceholder(xShape, Title, mbMaster))
312 ShapeExport::WriteTextShape(xShape);
314 else
315 SAL_WARN("sd.eppt", "PowerPointShapeExport::WriteTextShape: shape of type '" << sShapeType << "' is ignored");
317 return *this;
320 ShapeExport& PowerPointShapeExport::WriteUnknownShape(const Reference< XShape >& xShape)
322 OUString sShapeType = xShape->getShapeType();
324 SAL_INFO("sd.eppt", "shape(unknown): " << sShapeType.toUtf8());
326 if (sShapeType == "com.sun.star.presentation.PageShape")
328 WritePageShape(xShape, mePageType, mrExport.GetPresObj());
330 else if (sShapeType == "com.sun.star.presentation.SubtitleShape")
332 if(mePageType != MASTER)
334 if (!WritePlaceholder(xShape, Subtitle, mbMaster))
335 ShapeExport::WriteTextShape(xShape);
338 else
339 SAL_WARN("sd.eppt", "unknown shape not handled: " << sShapeType.toUtf8());
341 return *this;
344 PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContext, const uno::Sequence<uno::Any>& rArguments)
345 : XmlFilterBase(rContext)
346 , mpAuthorIDs( new SvtSecurityMapPersonalInfo )
347 , mnLayoutFileIdMax(1)
348 , mnSlideIdMax(1 << 8)
349 , mnSlideMasterIdMax(1U << 31)
350 , mnAnimationNodeIdMax(1)
351 , mnDiagramId(1)
352 , mbCreateNotes(false)
353 , mnPlaceholderIndexMax(1)
355 comphelper::SequenceAsHashMap aArgumentsMap(rArguments);
356 mbPptm = aArgumentsMap.getUnpackedValueOrDefault(u"IsPPTM"_ustr, false);
357 mbExportTemplate = aArgumentsMap.getUnpackedValueOrDefault(u"IsTemplate"_ustr, false);
360 PowerPointExport::~PowerPointExport()
364 void PowerPointExport::writeDocumentProperties()
366 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(mXModel, uno::UNO_QUERY);
367 uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
369 if (xDocProps.is())
371 bool bSecurityOptOpenReadOnly = false;
372 uno::Reference< lang::XMultiServiceFactory > xFactory(mXModel, uno::UNO_QUERY);
373 uno::Reference< beans::XPropertySet > xSettings(xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY);
376 xSettings->getPropertyValue(u"LoadReadonly"_ustr) >>= bSecurityOptOpenReadOnly;
378 catch( Exception& )
381 exportDocumentProperties(xDocProps, bSecurityOptOpenReadOnly);
384 exportCustomFragments();
387 bool PowerPointExport::importDocument() noexcept
389 return false;
392 bool PowerPointExport::exportDocument()
394 drawingml::DrawingML::ResetMlCounters();
395 auto& rGraphicExportCache = drawingml::GraphicExportCache::get();
397 rGraphicExportCache.push();
399 maShapeMap.clear();
401 mXModel = getModel();
403 //write document properties
404 writeDocumentProperties();
406 addRelation(oox::getRelationship(Relationship::OFFICEDOCUMENT), u"ppt/presentation.xml");
408 OUString aMediaType;
409 if (mbPptm)
411 if (mbExportTemplate)
413 aMediaType = "application/vnd.ms-powerpoint.template.macroEnabled.main+xml";
415 else
417 aMediaType = "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml";
420 else
422 if (mbExportTemplate)
424 aMediaType = "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml";
426 else
428 aMediaType = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
432 mPresentationFS = openFragmentStreamWithSerializer(u"ppt/presentation.xml"_ustr, aMediaType);
434 addRelation(mPresentationFS->getOutputStream(),
435 oox::getRelationship(Relationship::THEME),
436 u"theme/theme1.xml");
438 mPresentationFS->startElementNS(XML_p, XML_presentation, PNMSS);
440 mXStatusIndicator = getStatusIndicator();
442 std::vector< PropertyValue > aProperties;
443 PropertyValue aProperty;
444 aProperty.Name = "BaseURI";
445 aProperty.Value <<= getFileUrl();
446 aProperties.push_back(aProperty);
448 exportPPT(aProperties);
450 mPresentationFS->singleElementNS(XML_p, XML_sldSz,
451 XML_cx, OString::number(PPTtoEMU(maDestPageSize.Width)),
452 XML_cy, OString::number(PPTtoEMU(maDestPageSize.Height)));
453 // for some reason if added before slides list it will not load the slides (alas with error reports) in mso
454 mPresentationFS->singleElementNS(XML_p, XML_notesSz,
455 XML_cx, OString::number(PPTtoEMU(maNotesPageSize.Width)),
456 XML_cy, OString::number(PPTtoEMU(maNotesPageSize.Height)));
458 WriteCustomSlideShow();
460 WritePresentationProps();
462 WriteAuthors();
464 WriteVBA();
466 WriteModifyVerifier();
468 mPresentationFS->endElementNS(XML_p, XML_presentation);
469 mPresentationFS->endDocument();
470 mPresentationFS.reset();
471 // Free all FSHelperPtr, to flush data before committing storage
472 for (auto& serializer : mpSlidesFSArray)
474 if (!serializer)
475 continue;
476 serializer->endDocument();
478 mpSlidesFSArray.clear();
480 commitStorage();
482 rGraphicExportCache.pop();
484 maShapeMap.clear();
485 maAuthors.clear();
486 maRelId.clear();
488 return true;
491 ::oox::ole::VbaProject* PowerPointExport::implCreateVbaProject() const
493 return new ::oox::ole::VbaProject(getComponentContext(), getModel(), u"Impress");
496 void PowerPointExport::WriteCustomSlideShow()
498 Reference<XCustomPresentationSupplier> aXCPSup(mXModel, css::uno::UNO_QUERY);
499 if (!aXCPSup.is() || !aXCPSup->getCustomPresentations()->hasElements())
500 return;
502 mPresentationFS->startElementNS(XML_p, XML_custShowLst);
504 Reference<XDrawPagesSupplier> xDPS(getModel(), uno::UNO_QUERY_THROW);
505 Reference<XDrawPages> xDrawPages(xDPS->getDrawPages(), uno::UNO_SET_THROW);
506 Reference<XNameContainer> aXNameCont(aXCPSup->getCustomPresentations());
507 const Sequence<OUString> aNameSeq(aXNameCont->getElementNames());
509 OUString sRelId;
510 sal_uInt32 nCustomShowIndex = 0;
511 sal_Int32 nSlideCount = xDrawPages->getCount();
513 for (OUString const& customShowName : aNameSeq)
515 mPresentationFS->startElementNS(XML_p, XML_custShow, XML_name, customShowName, XML_id,
516 OUString::number(nCustomShowIndex++));
518 mAny = aXNameCont->getByName(customShowName);
519 Reference<XIndexContainer> aXIContainer;
520 if (mAny >>= aXIContainer)
522 mPresentationFS->startElementNS(XML_p, XML_sldLst);
524 sal_Int32 nCustomShowSlideCount = aXIContainer->getCount();
525 for (sal_Int32 i = 0; i < nCustomShowSlideCount; ++i)
527 Reference<XDrawPage> aXCustomShowDrawPage;
528 aXIContainer->getByIndex(i) >>= aXCustomShowDrawPage;
529 Reference<XNamed> aXName(aXCustomShowDrawPage, UNO_QUERY_THROW);
530 OUString sCustomShowSlideName = aXName->getName();
532 for (sal_Int32 j = 0; j < nSlideCount; ++j)
534 Reference<XDrawPage> xDrawPage;
535 xDrawPages->getByIndex(j) >>= xDrawPage;
536 Reference<XNamed> xNamed(xDrawPage, UNO_QUERY_THROW);
537 OUString sSlideName = xNamed->getName();
539 if (sCustomShowSlideName == sSlideName)
541 sRelId = maRelId[j];
542 break;
545 mPresentationFS->singleElementNS(XML_p, XML_sld, FSNS(XML_r, XML_id), sRelId);
547 mPresentationFS->endElementNS(XML_p, XML_sldLst);
549 mPresentationFS->endElementNS(XML_p, XML_custShow);
551 mPresentationFS->endElementNS(XML_p, XML_custShowLst);
554 void PowerPointExport::ImplWriteBackground(const FSHelperPtr& pFS, const Reference< XPropertySet >& rXPropSet)
556 FillStyle aFillStyle(FillStyle_NONE);
557 if (ImplGetPropertyValue(rXPropSet, u"FillStyle"_ustr))
558 mAny >>= aFillStyle;
560 if (aFillStyle == FillStyle_NONE ||
561 aFillStyle == FillStyle_HATCH)
562 return;
564 pFS->startElementNS(XML_p, XML_bg);
565 pFS->startElementNS(XML_p, XML_bgPr);
567 PowerPointShapeExport aDML(pFS, &maShapeMap, this);
568 aDML.SetBackgroundDark(mbIsBackgroundDark);
569 aDML.WriteFill(rXPropSet, maPageSize);
571 pFS->endElementNS(XML_p, XML_bgPr);
572 pFS->endElementNS(XML_p, XML_bg);
575 #define MAIN_GROUP \
576 "<p:nvGrpSpPr>\
577 <p:cNvPr id=\"1\" name=\"\"/>\
578 <p:cNvGrpSpPr/>\
579 <p:nvPr/>\
580 </p:nvGrpSpPr>\
581 <p:grpSpPr>\
582 <a:xfrm>\
583 <a:off x=\"0\" y=\"0\"/>\
584 <a:ext cx=\"0\" cy=\"0\"/>\
585 <a:chOff x=\"0\" y=\"0\"/>\
586 <a:chExt cx=\"0\" cy=\"0\"/>\
587 </a:xfrm>\
588 </p:grpSpPr>"
590 const char* PowerPointExport::GetSideDirection(sal_uInt8 nDirection)
592 const char* pDirection = nullptr;
594 switch (nDirection)
596 case 0:
597 pDirection = "l";
598 break;
599 case 1:
600 pDirection = "u";
601 break;
602 case 2:
603 pDirection = "r";
604 break;
605 case 3:
606 pDirection = "d";
607 break;
610 return pDirection;
613 const char* PowerPointExport::GetCornerDirection(sal_uInt8 nDirection)
615 const char* pDirection = nullptr;
617 switch (nDirection)
619 case 4:
620 pDirection = "lu";
621 break;
622 case 5:
623 pDirection = "ru";
624 break;
625 case 6:
626 pDirection = "ld";
627 break;
628 case 7:
629 pDirection = "rd";
630 break;
633 return pDirection;
636 const char* PowerPointExport::Get8Direction(sal_uInt8 nDirection)
638 const char* pDirection = GetSideDirection(nDirection);
640 if (!pDirection)
641 pDirection = GetCornerDirection(nDirection);
643 return pDirection;
646 void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
648 FadeEffect eFadeEffect = FadeEffect_NONE;
649 if (ImplGetPropertyValue(mXPagePropSet, u"Effect"_ustr))
650 mAny >>= eFadeEffect;
652 sal_Int16 nTransitionType = 0, nTransitionSubtype = 0;
653 sal_Int8 nPPTTransitionType = 0;
654 sal_uInt8 nDirection = 0;
656 OUString sSoundUrl;
657 OUString sSoundRelId;
658 OUString sSoundName;
660 if (ImplGetPropertyValue(mXPagePropSet, u"TransitionType"_ustr) && (mAny >>= nTransitionType) &&
661 ImplGetPropertyValue(mXPagePropSet, u"TransitionSubtype"_ustr) && (mAny >>= nTransitionSubtype))
663 // FADEOVERCOLOR with black -> fade, with white -> flash
664 sal_Int32 nTransitionFadeColor = 0;
665 if( ImplGetPropertyValue(mXPagePropSet, u"TransitionFadeColor"_ustr))
666 mAny >>= nTransitionFadeColor;
667 nPPTTransitionType = GetTransition(nTransitionType, nTransitionSubtype, eFadeEffect, nTransitionFadeColor, nDirection);
670 if (!nPPTTransitionType && eFadeEffect != FadeEffect_NONE)
671 nPPTTransitionType = GetTransition(eFadeEffect, nDirection);
673 if (ImplGetPropertyValue(mXPagePropSet, u"Sound"_ustr) && (mAny >>= sSoundUrl))
674 embedEffectAudio(pFS, sSoundUrl, sSoundRelId, sSoundName);
676 bool bOOXmlSpecificTransition = false;
678 sal_Int32 nTransition = 0;
679 const char* pDirection = nullptr;
680 const char* pOrientation = nullptr;
681 const char* pThruBlk = nullptr;
682 const char* pSpokes = nullptr;
684 char pSpokesTmp[2] = "0";
686 // p14
687 sal_Int32 nTransition14 = 0;
688 const char* pDirection14 = nullptr;
689 const char* pInverted = nullptr;
690 const char* pPattern = nullptr; // diamond or hexagon
692 //p15
693 const char* pPresetTransition = nullptr;
695 if (!nPPTTransitionType)
697 switch (nTransitionType)
699 case animations::TransitionType::BARWIPE:
701 if (nTransitionSubtype == animations::TransitionSubType::FADEOVERCOLOR)
703 nTransition = XML_cut;
704 pThruBlk = "true";
705 bOOXmlSpecificTransition = true;
707 break;
709 case animations::TransitionType::MISCSHAPEWIPE:
711 switch (nTransitionSubtype)
713 case animations::TransitionSubType::TOPTOBOTTOM: // Turn around
714 nTransition = XML_fade;
715 nTransition14 = XML_flip;
716 pDirection14 = "l";
717 bOOXmlSpecificTransition = true;
718 break;
719 case animations::TransitionSubType::BOTTOMRIGHT: // Rochade
720 nTransition = XML_fade;
721 nTransition14 = XML_switch;
722 pDirection14 = "r";
723 bOOXmlSpecificTransition = true;
724 break;
725 case animations::TransitionSubType::VERTICAL: // Vortex
726 nTransition = XML_fade;
727 nTransition14 = XML_vortex;
728 bOOXmlSpecificTransition = true;
729 break;
730 case animations::TransitionSubType::HORIZONTAL: // Ripple
731 nTransition = XML_fade;
732 nTransition14 = XML_ripple;
733 bOOXmlSpecificTransition = true;
734 break;
735 case animations::TransitionSubType::LEFTTORIGHT: // Fall
736 nTransition = XML_fade;
737 pPresetTransition = "fallOver";
738 bOOXmlSpecificTransition = true;
739 break;
740 case animations::TransitionSubType::CORNERSIN: // Inside turning cube
741 pInverted = "true";
742 [[fallthrough]];
743 case animations::TransitionSubType::CORNERSOUT: // Outside turning cube
744 nTransition = XML_fade;
745 nTransition14 = XML_prism;
746 bOOXmlSpecificTransition = true;
747 break;
748 case animations::TransitionSubType::DIAMOND: // Glitter
749 nTransition = XML_fade;
750 nTransition14 = XML_glitter;
751 pDirection14 = "l";
752 pPattern = "hexagon";
753 bOOXmlSpecificTransition = true;
754 break;
755 case animations::TransitionSubType::HEART: // Honeycomb
756 nTransition = XML_fade;
757 nTransition14 = XML_honeycomb;
758 bOOXmlSpecificTransition = true;
759 break;
761 break;
766 AnimationSpeed animationSpeed = AnimationSpeed_MEDIUM;
767 const char* speed = nullptr;
768 sal_Int32 advanceTiming = -1;
769 sal_Int32 changeType = 0;
771 sal_Int32 nTransitionDuration = -1;
772 bool isTransitionDurationSet = false;
774 // try to use TransitionDuration instead of old Speed property
775 if (ImplGetPropertyValue(mXPagePropSet, u"TransitionDuration"_ustr))
777 double fTransitionDuration = -1.0;
778 mAny >>= fTransitionDuration;
779 if (fTransitionDuration >= 0)
781 nTransitionDuration = fTransitionDuration * 1000.0;
783 // override values because in MS formats meaning of fast/medium/slow is different
784 if (nTransitionDuration <= 500)
786 // fast is default
787 speed = nullptr;
789 else if (nTransitionDuration >= 1000)
791 speed = "slow";
793 else
795 speed = "med";
798 bool isStandardValue = nTransitionDuration == 500
799 || nTransitionDuration == 750
800 || nTransitionDuration == 1000;
802 if(!isStandardValue)
803 isTransitionDurationSet = true;
806 else if (ImplGetPropertyValue(mXPagePropSet, u"Speed"_ustr))
808 mAny >>= animationSpeed;
810 switch (animationSpeed)
812 default:
813 case AnimationSpeed_MEDIUM:
814 speed = "med";
815 break;
816 case AnimationSpeed_SLOW:
817 speed = "slow";
818 break;
819 case AnimationSpeed_FAST:
820 break;
824 // check if we resolved what transition to export or time is set
825 if (!nPPTTransitionType && !bOOXmlSpecificTransition && !isTransitionDurationSet)
826 return;
828 if (ImplGetPropertyValue(mXPagePropSet, u"Change"_ustr))
829 mAny >>= changeType;
831 // 1 means automatic, 2 half automatic - not sure what it means - at least I don't see it in UI
832 if (changeType == 1 && ImplGetPropertyValue(mXPagePropSet, u"Duration"_ustr))
833 mAny >>= advanceTiming;
835 if (!bOOXmlSpecificTransition)
837 switch (nPPTTransitionType)
839 case PPT_TRANSITION_TYPE_BLINDS:
840 nTransition = XML_blinds;
841 pDirection = (nDirection == 0) ? "vert" : "horz";
842 break;
843 case PPT_TRANSITION_TYPE_CHECKER:
844 nTransition = XML_checker;
845 pDirection = (nDirection == 1) ? "vert" : "horz";
846 break;
847 case PPT_TRANSITION_TYPE_CIRCLE:
848 nTransition = XML_circle;
849 break;
850 case PPT_TRANSITION_TYPE_COMB:
851 nTransition = XML_comb;
852 pDirection = (nDirection == 1) ? "vert" : "horz";
853 break;
854 case PPT_TRANSITION_TYPE_COVER:
855 nTransition = XML_cover;
856 pDirection = Get8Direction(nDirection);
857 break;
858 case PPT_TRANSITION_TYPE_DIAMOND:
859 nTransition = XML_diamond;
860 break;
861 case PPT_TRANSITION_TYPE_DISSOLVE:
862 nTransition = XML_dissolve;
863 break;
864 case PPT_TRANSITION_TYPE_FADE:
865 nTransition = XML_fade;
866 pThruBlk = "true";
867 break;
868 case PPT_TRANSITION_TYPE_SMOOTHFADE:
869 nTransition = XML_fade;
870 break;
871 case PPT_TRANSITION_TYPE_NEWSFLASH:
872 nTransition = XML_newsflash;
873 break;
874 case PPT_TRANSITION_TYPE_PLUS:
875 nTransition = XML_plus;
876 break;
877 case PPT_TRANSITION_TYPE_PULL:
878 nTransition = XML_pull;
879 pDirection = Get8Direction(nDirection);
880 break;
881 case PPT_TRANSITION_TYPE_PUSH:
882 nTransition = XML_push;
883 pDirection = GetSideDirection(nDirection);
884 break;
885 case PPT_TRANSITION_TYPE_RANDOM:
886 nTransition = XML_random;
887 break;
888 case PPT_TRANSITION_TYPE_RANDOM_BARS:
889 nTransition = XML_randomBar;
890 pDirection = (nDirection == 1) ? "vert" : "horz";
891 break;
892 case PPT_TRANSITION_TYPE_SPLIT:
893 nTransition = XML_split;
894 pDirection = (nDirection & 1) ? "in" : "out";
895 pOrientation = (nDirection < 2) ? "horz" : "vert";
896 break;
897 case PPT_TRANSITION_TYPE_STRIPS:
898 nTransition = XML_strips;
899 pDirection = GetCornerDirection(nDirection);
900 break;
901 case PPT_TRANSITION_TYPE_WEDGE:
902 nTransition = XML_wedge;
903 break;
904 case PPT_TRANSITION_TYPE_WHEEL:
905 nTransition = XML_wheel;
906 if (nDirection != 4 && nDirection <= 9)
908 pSpokesTmp[0] = '0' + nDirection;
909 pSpokes = pSpokesTmp;
911 break;
912 case PPT_TRANSITION_TYPE_WIPE:
913 nTransition = XML_wipe;
914 pDirection = GetSideDirection(nDirection);
915 break;
916 case PPT_TRANSITION_TYPE_ZOOM:
917 nTransition = XML_zoom;
918 pDirection = (nDirection == 1) ? "in" : "out";
919 break;
920 case PPT_TRANSITION_TYPE_FLASH:
921 nTransition14 = XML_flash;
922 nTransition = XML_fade;
923 bOOXmlSpecificTransition = true;
924 break;
925 // coverity[dead_error_line] - following conditions exist to avoid compiler warning
926 case PPT_TRANSITION_TYPE_NONE:
927 default:
928 nTransition = 0;
929 break;
933 bool isAdvanceTimingSet = advanceTiming != -1;
934 if (nTransition14 || pPresetTransition || isTransitionDurationSet)
936 const char* pRequiresNS = (nTransition14 || isTransitionDurationSet) ? "p14" : "p15";
938 pFS->startElement(FSNS(XML_mc, XML_AlternateContent));
939 pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS);
941 if(isTransitionDurationSet && isAdvanceTimingSet)
943 pFS->startElementNS(XML_p, XML_transition,
944 XML_spd, speed,
945 XML_advTm, OString::number(advanceTiming * 1000),
946 FSNS(XML_p14, XML_dur), OString::number(nTransitionDuration));
948 else if(isTransitionDurationSet)
950 pFS->startElementNS(XML_p, XML_transition,
951 XML_spd, speed,
952 FSNS(XML_p14, XML_dur), OString::number(nTransitionDuration));
954 else if(isAdvanceTimingSet)
956 pFS->startElementNS(XML_p, XML_transition,
957 XML_spd, speed,
958 XML_advTm, OString::number(advanceTiming * 1000));
960 else
962 pFS->startElementNS(XML_p, XML_transition, XML_spd, speed);
965 if (nTransition14)
967 pFS->singleElementNS(XML_p14, nTransition14,
968 XML_isInverted, pInverted,
969 XML_dir, pDirection14,
970 XML_pattern, pPattern);
972 else if (pPresetTransition)
974 pFS->singleElementNS(XML_p15, XML_prstTrans,
975 XML_prst, pPresetTransition);
977 else if (isTransitionDurationSet && nTransition)
979 pFS->singleElementNS(XML_p, nTransition,
980 XML_dir, pDirection,
981 XML_orient, pOrientation,
982 XML_spokes, pSpokes,
983 XML_thruBlk, pThruBlk);
986 if (!sSoundRelId.isEmpty())
987 WriteSndAc(pFS, sSoundRelId, sSoundName);
989 pFS->endElement(FSNS(XML_p, XML_transition));
991 pFS->endElement(FSNS(XML_mc, XML_Choice));
992 pFS->startElement(FSNS(XML_mc, XML_Fallback));
995 pFS->startElementNS(XML_p, XML_transition,
996 XML_spd, speed,
997 XML_advTm, sax_fastparser::UseIf(OString::number(advanceTiming * 1000), isAdvanceTimingSet));
999 if (nTransition)
1001 pFS->singleElementNS(XML_p, nTransition,
1002 XML_dir, pDirection,
1003 XML_orient, pOrientation,
1004 XML_spokes, pSpokes,
1005 XML_thruBlk, pThruBlk);
1008 if (!sSoundRelId.isEmpty())
1009 WriteSndAc(pFS, sSoundRelId, sSoundName);
1011 pFS->endElementNS(XML_p, XML_transition);
1013 if (nTransition14 || pPresetTransition || isTransitionDurationSet)
1015 pFS->endElement(FSNS(XML_mc, XML_Fallback));
1016 pFS->endElement(FSNS(XML_mc, XML_AlternateContent));
1020 void PowerPointExport::WriteAuthors()
1022 if (maAuthors.empty())
1023 return;
1025 FSHelperPtr pFS = openFragmentStreamWithSerializer(u"ppt/commentAuthors.xml"_ustr,
1026 u"application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml"_ustr);
1027 addRelation(mPresentationFS->getOutputStream(),
1028 oox::getRelationship(Relationship::COMMENTAUTHORS),
1029 u"commentAuthors.xml");
1031 pFS->startElementNS(XML_p, XML_cmAuthorLst,
1032 FSNS(XML_xmlns, XML_p), getNamespaceURL(OOX_NS(ppt)));
1034 for (const AuthorsMap::value_type& i : maAuthors)
1036 pFS->singleElementNS(XML_p, XML_cmAuthor,
1037 XML_id, OString::number(i.second.nId),
1038 XML_name, i.first,
1039 XML_initials, i.second.sInitials,
1040 XML_lastIdx, OString::number(i.second.nLastIndex),
1041 XML_clrIdx, OString::number(i.second.nId));
1044 pFS->endElementNS(XML_p, XML_cmAuthorLst);
1046 pFS->endDocument();
1049 sal_Int32 PowerPointExport::GetAuthorIdAndLastIndex(const OUString& sAuthor,
1050 const OUString& sInitials,
1051 sal_Int32& nLastIndex)
1053 if (maAuthors.count(sAuthor) <= 0)
1054 maAuthors.emplace(sAuthor, AuthorComments(maAuthors.size(), 0, sInitials));
1056 nLastIndex = ++maAuthors[ sAuthor ].nLastIndex;
1058 return maAuthors[ sAuthor ].nId;
1061 void PowerPointExport::WritePresentationProps()
1063 Reference<XPresentationSupplier> xPresentationSupplier(mXModel, uno::UNO_QUERY);
1064 if (!xPresentationSupplier.is())
1065 return;
1067 Reference<beans::XPropertySet> xPresentationProps(xPresentationSupplier->getPresentation(),
1068 uno::UNO_QUERY);
1069 bool bEndlessVal = xPresentationProps->getPropertyValue(u"IsEndless"_ustr).get<bool>();
1070 bool bChangeManually = xPresentationProps->getPropertyValue(u"IsAutomatic"_ustr).get<bool>();
1071 OUString sFirstPage = xPresentationProps->getPropertyValue(u"FirstPage"_ustr).get<OUString>();
1072 OUString sCustomShow = xPresentationProps->getPropertyValue(u"CustomShow"_ustr).get<OUString>();
1074 FSHelperPtr pFS = openFragmentStreamWithSerializer(
1075 u"ppt/presProps.xml"_ustr,
1076 u"application/vnd.openxmlformats-officedocument.presentationml.presProps+xml"_ustr);
1078 addRelation(mPresentationFS->getOutputStream(),
1079 oox::getRelationship(Relationship::PRESPROPS), u"presProps.xml");
1081 pFS->startElementNS(XML_p, XML_presentationPr, PPRNMSS);
1083 pFS->startElementNS(XML_p, XML_showPr, XML_loop, sax_fastparser::UseIf("1", bEndlessVal),
1084 XML_useTimings, sax_fastparser::UseIf("0", bChangeManually),
1085 XML_showNarration, "1");
1087 Reference<drawing::XDrawPagesSupplier> xDPS(mXModel, uno::UNO_QUERY_THROW);
1088 Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(), uno::UNO_SET_THROW);
1089 if (!sFirstPage.isEmpty())
1091 sal_Int32 nStartSlide = 1;
1092 sal_Int32 nEndSlide = xDrawPages->getCount();
1093 for (sal_Int32 i = 0; i < nEndSlide; i++)
1095 Reference<drawing::XDrawPage> xDrawPage;
1096 xDrawPages->getByIndex(i) >>= xDrawPage;
1097 Reference<container::XNamed> xNamed(xDrawPage, uno::UNO_QUERY_THROW);
1098 if (xNamed->getName() == sFirstPage)
1100 nStartSlide = i + 1;
1101 break;
1105 pFS->singleElementNS(XML_p, XML_sldRg, XML_st, OUString::number(nStartSlide), XML_end,
1106 OUString::number(nEndSlide));
1109 if (!sCustomShow.isEmpty())
1111 css::uno::Reference<css::presentation::XCustomPresentationSupplier>
1112 XCustPresentationSupplier(mXModel, css::uno::UNO_QUERY_THROW);
1113 css::uno::Reference<css::container::XNameContainer> mxCustShows;
1114 mxCustShows = XCustPresentationSupplier->getCustomPresentations();
1115 const css::uno::Sequence<OUString> aNameSeq(mxCustShows->getElementNames());
1117 sal_Int32 nCustShowIndex = 0;
1118 for (sal_Int32 i = 0; i < aNameSeq.getLength(); i++)
1120 if (aNameSeq[i] == sCustomShow)
1122 nCustShowIndex = i;
1123 break;
1127 pFS->singleElementNS(XML_p, XML_custShow, XML_id, OUString::number(nCustShowIndex));
1130 pFS->endElementNS(XML_p, XML_showPr);
1132 pFS->endElementNS(XML_p, XML_presentationPr);
1134 pFS->endDocument();
1137 bool PowerPointExport::WriteComments(sal_uInt32 nPageNum)
1139 Reference< XAnnotationAccess > xAnnotationAccess(mXDrawPage, uno::UNO_QUERY);
1140 if (xAnnotationAccess.is())
1142 Reference< XAnnotationEnumeration > xAnnotationEnumeration(xAnnotationAccess->createAnnotationEnumeration());
1144 if (xAnnotationEnumeration->hasMoreElements())
1146 bool bRemoveCommentAuthorDates
1147 = SvtSecurityOptions::IsOptionSet(
1148 SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo)
1149 && !SvtSecurityOptions::IsOptionSet(
1150 SvtSecurityOptions::EOption::DocWarnKeepNoteAuthorDateInfo);
1152 FSHelperPtr pFS = openFragmentStreamWithSerializer(
1153 "ppt/comments/comment" + OUString::number(nPageNum + 1) + ".xml",
1154 u"application/vnd.openxmlformats-officedocument.presentationml.comments+xml"_ustr);
1156 pFS->startElementNS(XML_p, XML_cmLst,
1157 FSNS(XML_xmlns, XML_p), this->getNamespaceURL(OOX_NS(ppt)));
1161 Reference< XAnnotation > xAnnotation(xAnnotationEnumeration->nextElement());
1162 util::DateTime aDateTime(xAnnotation->getDateTime());
1163 RealPoint2D aRealPoint2D(xAnnotation->getPosition());
1164 Reference< XText > xText(xAnnotation->getTextRange());
1165 sal_Int32 nLastIndex;
1166 OUString sAuthor(bRemoveCommentAuthorDates
1167 ? "Author"
1168 + OUString::number(GetInfoID(xAnnotation->getAuthor()))
1169 : xAnnotation->getAuthor());
1170 OUString sInitials(bRemoveCommentAuthorDates
1171 ? "A" + OUString::number(GetInfoID(xAnnotation->getAuthor()))
1172 : xAnnotation->getInitials());
1173 sal_Int32 nId = GetAuthorIdAndLastIndex(sAuthor, sInitials, nLastIndex);
1174 char cDateTime[sizeof("-32768-65535-65535T65535:65535:65535.4294967295")];
1175 // reserve enough space for hypothetical max length
1177 snprintf(cDateTime, sizeof cDateTime, "%02" SAL_PRIdINT32 "-%02" SAL_PRIuUINT32 "-%02" SAL_PRIuUINT32 "T%02" SAL_PRIuUINT32 ":%02" SAL_PRIuUINT32 ":%02" SAL_PRIuUINT32 ".%09" SAL_PRIuUINT32, sal_Int32(aDateTime.Year), sal_uInt32(aDateTime.Month), sal_uInt32(aDateTime.Day), sal_uInt32(aDateTime.Hours), sal_uInt32(aDateTime.Minutes), sal_uInt32(aDateTime.Seconds), aDateTime.NanoSeconds);
1179 util::DateTime aEmptyDate;
1180 if (bRemoveCommentAuthorDates || aDateTime == aEmptyDate)
1182 pFS->startElementNS(XML_p, XML_cm,
1183 XML_authorId, OString::number(nId),
1184 XML_idx, OString::number(nLastIndex));
1186 else
1188 pFS->startElementNS(XML_p, XML_cm,
1189 XML_authorId, OString::number(nId),
1190 XML_dt, cDateTime,
1191 XML_idx, OString::number(nLastIndex));
1194 pFS->singleElementNS(XML_p, XML_pos,
1195 XML_x, OString::number(std::round(convertMm100ToMasterUnit(aRealPoint2D.X * 100))),
1196 XML_y, OString::number(std::round(convertMm100ToMasterUnit(aRealPoint2D.Y * 100))));
1198 pFS->startElementNS(XML_p, XML_text);
1199 pFS->write(xText->getString());
1200 pFS->endElementNS(XML_p, XML_text);
1202 pFS->endElementNS(XML_p, XML_cm);
1205 while (xAnnotationEnumeration->hasMoreElements());
1207 pFS->endElementNS(XML_p, XML_cmLst);
1209 pFS->endDocument();
1211 return true;
1215 return false;
1218 void PowerPointExport::WriteVBA()
1220 if (!mbPptm)
1221 return;
1223 uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
1224 if (!xStorageBasedDocument.is())
1225 return;
1227 uno::Reference<embed::XStorage> xDocumentStorage = xStorageBasedDocument->getDocumentStorage();
1228 OUString aMacrosName(u"_MS_VBA_Macros"_ustr);
1229 if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aMacrosName))
1230 return;
1232 const sal_Int32 nOpenMode = embed::ElementModes::READ;
1233 uno::Reference<io::XInputStream> xMacrosStream(xDocumentStorage->openStreamElement(aMacrosName, nOpenMode), uno::UNO_QUERY);
1234 if (!xMacrosStream.is())
1235 return;
1237 uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream(u"ppt/vbaProject.bin"_ustr, u"application/vnd.ms-office.vbaProject"_ustr);
1238 comphelper::OStorageHelper::CopyInputToOutput(xMacrosStream, xOutputStream);
1240 // Write the relationship.
1241 addRelation(mPresentationFS->getOutputStream(), oox::getRelationship(Relationship::VBAPROJECT), u"vbaProject.bin");
1244 void PowerPointExport::WriteModifyVerifier()
1246 Sequence<PropertyValue> aInfo;
1250 Reference<lang::XMultiServiceFactory> xFactory(mXModel, UNO_QUERY);
1251 Reference<XPropertySet> xDocSettings(
1252 xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), UNO_QUERY);
1253 xDocSettings->getPropertyValue(u"ModifyPasswordInfo"_ustr) >>= aInfo;
1255 catch (const Exception&)
1259 if (aInfo.hasElements())
1261 OUString sAlgorithm, sSalt, sHash;
1262 sal_Int32 nCount = 0;
1263 for (auto& prop : aInfo)
1265 if (prop.Name == "algorithm-name")
1266 prop.Value >>= sAlgorithm;
1267 else if (prop.Name == "salt")
1268 prop.Value >>= sSalt;
1269 else if (prop.Name == "iteration-count")
1270 prop.Value >>= nCount;
1271 else if (prop.Name == "hash")
1272 prop.Value >>= sHash;
1274 if (!sAlgorithm.isEmpty() && !sSalt.isEmpty() && !sHash.isEmpty())
1276 sal_Int32 nAlgorithmSid = 0;
1277 if (sAlgorithm == "MD2")
1278 nAlgorithmSid = 1;
1279 else if (sAlgorithm == "MD4")
1280 nAlgorithmSid = 2;
1281 else if (sAlgorithm == "MD5")
1282 nAlgorithmSid = 3;
1283 else if (sAlgorithm == "SHA-1")
1284 nAlgorithmSid = 4;
1285 else if (sAlgorithm == "MAC")
1286 nAlgorithmSid = 5;
1287 else if (sAlgorithm == "RIPEMD")
1288 nAlgorithmSid = 6;
1289 else if (sAlgorithm == "RIPEMD-160")
1290 nAlgorithmSid = 7;
1291 else if (sAlgorithm == "HMAC")
1292 nAlgorithmSid = 9;
1293 else if (sAlgorithm == "SHA-256")
1294 nAlgorithmSid = 12;
1295 else if (sAlgorithm == "SHA-384")
1296 nAlgorithmSid = 13;
1297 else if (sAlgorithm == "SHA-512")
1298 nAlgorithmSid = 14;
1300 if (nAlgorithmSid != 0)
1301 mPresentationFS->singleElementNS(XML_p, XML_modifyVerifier,
1302 XML_cryptProviderType, "rsaAES",
1303 XML_cryptAlgorithmClass, "hash",
1304 XML_cryptAlgorithmType, "typeAny",
1305 XML_cryptAlgorithmSid, OString::number(nAlgorithmSid),
1306 XML_spinCount, OString::number(nCount),
1307 XML_saltData, sSalt,
1308 XML_hashData, sHash);
1313 void PowerPointExport::ImplWriteSlide(sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_uInt16 /* nMode */,
1314 bool bHasBackground, Reference< XPropertySet > const& aXBackgroundPropSet)
1316 SAL_INFO("sd.eppt", "write slide: " << nPageNum << "\n----------------");
1318 // slides list
1319 if (nPageNum == 0)
1320 mPresentationFS->startElementNS(XML_p, XML_sldIdLst);
1322 // add explicit relation of presentation to this slide
1323 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1324 oox::getRelationship(Relationship::SLIDE),
1325 Concat2View("slides/slide" + OUString::number(nPageNum + 1) +".xml"));
1327 mPresentationFS->singleElementNS(XML_p, XML_sldId,
1328 XML_id, OString::number(GetNewSlideId()),
1329 FSNS(XML_r, XML_id), sRelId);
1331 maRelId.push_back(sRelId);
1333 if (nPageNum == mnPages - 1)
1334 mPresentationFS->endElementNS(XML_p, XML_sldIdLst);
1336 FSHelperPtr pFS = openFragmentStreamWithSerializer(
1337 "ppt/slides/slide" + OUString::number(nPageNum + 1) + ".xml",
1338 u"application/vnd.openxmlformats-officedocument.presentationml.slide+xml"_ustr);
1340 if (mpSlidesFSArray.size() < mnPages)
1341 mpSlidesFSArray.resize(mnPages);
1342 mpSlidesFSArray[ nPageNum ] = pFS;
1344 const char* pShow = nullptr;
1345 const char* pShowMasterShape = nullptr;
1347 if (ImplGetPropertyValue(mXPagePropSet, u"Visible"_ustr))
1349 bool bShow(false);
1350 if ((mAny >>= bShow) && !bShow)
1351 pShow = "0";
1354 if (ImplGetPropertyValue(mXPagePropSet, u"IsBackgroundObjectsVisible"_ustr))
1356 bool bShowMasterShape(false);
1357 if ((mAny >>= bShowMasterShape) && !bShowMasterShape)
1358 pShowMasterShape = "0";
1361 pFS->startElementNS(XML_p, XML_sld, PNMSS, XML_show, pShow, XML_showMasterSp, pShowMasterShape);
1363 pFS->startElementNS(XML_p, XML_cSld);
1365 // background
1366 if (bHasBackground)
1368 ImplWriteBackground(pFS, aXBackgroundPropSet);
1371 WriteShapeTree(pFS, NORMAL, false);
1373 pFS->endElementNS(XML_p, XML_cSld);
1375 WriteTransition(pFS);
1376 WriteAnimations(pFS, mXDrawPage, *this);
1378 pFS->endElementNS(XML_p, XML_sld);
1380 // add implicit relation to slide layout
1381 addRelation(pFS->getOutputStream(),
1382 oox::getRelationship(Relationship::SLIDELAYOUT),
1383 Concat2View("../slideLayouts/slideLayout" +
1384 OUString::number(GetLayoutFileId(GetLayoutOffset(mXPagePropSet), nMasterNum)) +
1385 ".xml"));
1387 if (WriteComments(nPageNum))
1388 // add implicit relation to slide comments
1389 addRelation(pFS->getOutputStream(),
1390 oox::getRelationship(Relationship::COMMENTS),
1391 Concat2View("../comments/comment" + OUString::number(nPageNum + 1) + ".xml"));
1393 SAL_INFO("sd.eppt", "----------------");
1396 void PowerPointExport::ImplWriteNotes(sal_uInt32 nPageNum)
1398 if (!mbCreateNotes || !ContainsOtherShapeThanPlaceholders())
1399 return;
1401 SAL_INFO("sd.eppt", "write Notes " << nPageNum << "\n----------------");
1403 FSHelperPtr pFS = openFragmentStreamWithSerializer(
1404 "ppt/notesSlides/notesSlide" +
1405 OUString::number(nPageNum + 1) +
1406 ".xml",
1407 u"application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml"_ustr);
1409 pFS->startElementNS(XML_p, XML_notes, PNMSS);
1411 pFS->startElementNS(XML_p, XML_cSld);
1413 WriteShapeTree(pFS, NOTICE, false);
1415 pFS->endElementNS(XML_p, XML_cSld);
1417 pFS->endElementNS(XML_p, XML_notes);
1419 // add implicit relation to slide
1420 addRelation(pFS->getOutputStream(),
1421 oox::getRelationship(Relationship::SLIDE),
1422 Concat2View("../slides/slide" + OUString::number(nPageNum + 1) + ".xml"));
1424 // add slide implicit relation to notes
1425 if (nPageNum < mpSlidesFSArray.size())
1426 addRelation(mpSlidesFSArray[ nPageNum ]->getOutputStream(),
1427 oox::getRelationship(Relationship::NOTESSLIDE),
1428 Concat2View("../notesSlides/notesSlide" + OUString::number(nPageNum + 1) + ".xml"));
1430 // add implicit relation to notes master
1431 addRelation(pFS->getOutputStream(),
1432 oox::getRelationship(Relationship::NOTESMASTER),
1433 u"../notesMasters/notesMaster1.xml");
1435 SAL_INFO("sd.eppt", "-----------------");
1437 pFS->endDocument();
1440 void PowerPointExport::AddLayoutIdAndRelation(const FSHelperPtr& pFS, sal_Int32 nLayoutFileId)
1442 // add implicit relation of slide master to slide layout
1443 OUString sRelId = addRelation(pFS->getOutputStream(),
1444 oox::getRelationship(Relationship::SLIDELAYOUT),
1445 Concat2View("../slideLayouts/slideLayout" + OUString::number(nLayoutFileId) + ".xml"));
1447 pFS->singleElementNS(XML_p, XML_sldLayoutId,
1448 XML_id, OString::number(GetNewSlideMasterId()),
1449 FSNS(XML_r, XML_id), sRelId);
1452 void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPropertySet > const& aXBackgroundPropSet)
1454 SAL_INFO("sd.eppt", "write master slide: " << nPageNum << "\n--------------");
1456 // slides list
1457 if (nPageNum == 0)
1458 mPresentationFS->startElementNS(XML_p, XML_sldMasterIdLst);
1460 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1461 oox::getRelationship(Relationship::SLIDEMASTER),
1462 Concat2View("slideMasters/slideMaster" + OUString::number(nPageNum + 1) + ".xml"));
1464 mPresentationFS->singleElementNS(XML_p, XML_sldMasterId,
1465 XML_id, OString::number(GetNewSlideMasterId()),
1466 FSNS(XML_r, XML_id), sRelId);
1468 if (nPageNum == mnMasterPages - 1)
1469 mPresentationFS->endElementNS(XML_p, XML_sldMasterIdLst);
1471 FSHelperPtr pFS =
1472 openFragmentStreamWithSerializer("ppt/slideMasters/slideMaster" +
1473 OUString::number(nPageNum + 1) + ".xml",
1474 u"application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"_ustr);
1476 SdrPage* pMasterPage = SdPage::getImplementation(mXDrawPage);
1477 model::Theme* pTheme = nullptr;
1478 if (pMasterPage)
1480 pTheme = pMasterPage->getSdrPageProperties().getTheme().get();
1483 // write theme per master
1484 WriteTheme(nPageNum, pTheme);
1486 // add implicit relation to the presentation theme
1487 addRelation(pFS->getOutputStream(),
1488 oox::getRelationship(Relationship::THEME),
1489 Concat2View("../theme/theme" + OUString::number(nPageNum + 1) + ".xml"));
1491 pFS->startElementNS(XML_p, XML_sldMaster, PNMSS);
1493 pFS->startElementNS(XML_p, XML_cSld);
1495 if (aXBackgroundPropSet)
1496 ImplWriteBackground(pFS, aXBackgroundPropSet);
1497 WriteShapeTree(pFS, MASTER, true);
1499 pFS->endElementNS(XML_p, XML_cSld);
1501 css::uno::Reference< css::beans::XPropertySet > xDocPropSet(getModel(), uno::UNO_QUERY);
1502 if (xDocPropSet.is())
1504 uno::Sequence<beans::PropertyValue> aGrabBag;
1505 if (xDocPropSet->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr))
1506 xDocPropSet->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag;
1508 std::vector<OUString> aClrMap;
1509 aClrMap.reserve(12);
1510 uno::Sequence<beans::PropertyValue> aClrMapPropValue;
1511 if(aGrabBag.hasElements())
1513 for (const auto& rProp : aGrabBag)
1515 if (rProp.Name == "OOXColorMap")
1517 rProp.Value >>= aClrMapPropValue;
1518 break;
1523 if (aClrMapPropValue.getLength())
1525 OUString sName;
1526 sal_Int32 nToken = XML_TOKEN_INVALID;
1527 for(const auto& item : aClrMapPropValue)
1529 item.Value >>= nToken;
1530 switch (nToken)
1532 case XML_dk1: sName = u"dk1"_ustr; break;
1533 case XML_lt1: sName = u"lt1"_ustr; break;
1534 case XML_dk2: sName = u"dk2"_ustr; break;
1535 case XML_lt2: sName = u"lt2"_ustr; break;
1536 case XML_accent1: sName = u"accent1"_ustr; break;
1537 case XML_accent2: sName = u"accent2"_ustr; break;
1538 case XML_accent3: sName = u"accent3"_ustr; break;
1539 case XML_accent4: sName = u"accent4"_ustr; break;
1540 case XML_accent5: sName = u"accent5"_ustr; break;
1541 case XML_accent6: sName = u"accent6"_ustr; break;
1542 case XML_hlink: sName = u"hlink"_ustr; break;
1543 case XML_folHlink: sName = u"folHlink"_ustr; break;
1545 aClrMap.push_back(sName);
1547 assert(aClrMap.size() == 12 && "missing entries for ClrMap");
1549 else
1551 // default clrMap to export ".odp" files to ".pptx"
1552 aClrMap = { u"lt1"_ustr, u"dk1"_ustr, u"lt2"_ustr, u"dk2"_ustr,
1553 u"accent1"_ustr, u"accent2"_ustr, u"accent3"_ustr, u"accent4"_ustr,
1554 u"accent5"_ustr, u"accent6"_ustr, u"hlink"_ustr, u"folHlink"_ustr };
1557 pFS->singleElementNS(XML_p, XML_clrMap,
1558 XML_bg1, aClrMap[0],
1559 XML_tx1, aClrMap[1],
1560 XML_bg2, aClrMap[2],
1561 XML_tx2, aClrMap[3],
1562 XML_accent1, aClrMap[4],
1563 XML_accent2, aClrMap[5],
1564 XML_accent3, aClrMap[6],
1565 XML_accent4, aClrMap[7],
1566 XML_accent5, aClrMap[8],
1567 XML_accent6, aClrMap[9],
1568 XML_hlink, aClrMap[10],
1569 XML_folHlink, aClrMap[11]);
1572 // use master's id type as they have same range, mso does that as well
1573 pFS->startElementNS(XML_p, XML_sldLayoutIdLst);
1575 auto getLayoutsUsedForMaster = [](SdrPage* pMaster) -> std::unordered_set<sal_Int32>
1577 if (!pMaster)
1578 return {};
1580 std::unordered_set<sal_Int32> aUsedLayouts{};
1581 for (const auto* pPageUser : pMaster->GetPageUsers())
1583 const auto* pMasterPageDescriptor
1584 = dynamic_cast<const sdr::MasterPageDescriptor*>(pPageUser);
1586 if (!pMasterPageDescriptor)
1587 continue;
1589 AutoLayout eLayout
1590 = static_cast<SdPage&>(pMasterPageDescriptor->GetOwnerPage()).GetAutoLayout();
1591 aUsedLayouts.insert(eLayout);
1593 return aUsedLayouts;
1596 std::unordered_set<sal_Int32> aLayouts = getLayoutsUsedForMaster(pMasterPage);
1598 css::uno::Reference< css::beans::XPropertySet > xPagePropSet;
1599 xPagePropSet.set(mXDrawPage, UNO_QUERY);
1600 if (xPagePropSet.is())
1602 uno::Any aAny;
1603 if (GetPropertyValue(aAny, xPagePropSet, u"SlideLayout"_ustr))
1604 aLayouts.insert(aAny.get<sal_Int32>());
1607 OUString aSlideName;
1608 Reference< XNamed > xNamed(mXDrawPage, UNO_QUERY);
1609 if (xNamed.is())
1610 aSlideName = xNamed->getName();
1612 for (auto nLayout : aLayouts)
1614 ImplWritePPTXLayout(nLayout, nPageNum, aSlideName);
1615 AddLayoutIdAndRelation(pFS, GetLayoutFileId(nLayout, nPageNum));
1618 pFS->endElementNS(XML_p, XML_sldLayoutIdLst);
1620 pFS->endElementNS(XML_p, XML_sldMaster);
1622 SAL_INFO("sd.eppt", "----------------");
1624 pFS->endDocument();
1627 sal_Int32 PowerPointExport::GetLayoutFileId(sal_Int32 nOffset, sal_uInt32 nMasterNum)
1629 SAL_INFO("sd.eppt", "GetLayoutFileId offset: " << nOffset << " master: " << nMasterNum);
1630 if (mLayoutInfo[ nOffset ].mnFileIdArray.size() <= nMasterNum)
1631 return 0;
1633 return mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ];
1636 void PowerPointExport::ImplWritePPTXLayout(sal_Int32 nOffset, sal_uInt32 nMasterNum, const OUString& aSlideName)
1638 SAL_INFO("sd.eppt", "write layout: " << nOffset);
1640 Reference< drawing::XDrawPagesSupplier > xDPS(getModel(), uno::UNO_QUERY);
1641 Reference< drawing::XDrawPages > xDrawPages = xDPS->getDrawPages();
1642 Reference< drawing::XDrawPage > xSlide = xDrawPages->insertNewByIndex(xDrawPages->getCount());
1644 #if OSL_DEBUG_LEVEL >= 2
1645 if (xSlide.is())
1646 printf("new page created\n");
1647 #endif
1649 Reference< beans::XPropertySet > xPropSet(xSlide, uno::UNO_QUERY);
1650 xPropSet->setPropertyValue(u"Layout"_ustr, Any(short(aLayoutInfo[ nOffset ].nType)));
1651 #if OSL_DEBUG_LEVEL > 1
1652 dump_pset(xPropSet);
1653 #endif
1654 mXPagePropSet.set(xSlide, UNO_QUERY);
1655 mXShapes = xSlide;
1657 if (mLayoutInfo[ nOffset ].mnFileIdArray.size() < mnMasterPages)
1659 mLayoutInfo[ nOffset ].mnFileIdArray.resize(mnMasterPages);
1662 if (mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] != 0)
1663 return;
1665 FSHelperPtr pFS
1666 = openFragmentStreamWithSerializer("ppt/slideLayouts/slideLayout" +
1667 OUString::number(mnLayoutFileIdMax) + ".xml",
1668 u"application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"_ustr);
1670 // add implicit relation of slide layout to slide master
1671 addRelation(pFS->getOutputStream(),
1672 oox::getRelationship(Relationship::SLIDEMASTER),
1673 Concat2View("../slideMasters/slideMaster" + OUString::number(nMasterNum + 1) + ".xml"));
1675 pFS->startElementNS(XML_p, XML_sldLayout,
1676 PNMSS,
1677 XML_type, aLayoutInfo[ nOffset ].sType,
1678 XML_preserve, "1");
1680 if (!aSlideName.isEmpty())
1682 pFS->startElementNS(XML_p, XML_cSld,
1683 XML_name, aSlideName);
1685 else
1687 pFS->startElementNS(XML_p, XML_cSld,
1688 XML_name, aLayoutInfo[nOffset].sName);
1690 //pFS->write( MINIMAL_SPTREE ); // TODO: write actual shape tree
1691 WriteShapeTree(pFS, LAYOUT, true);
1693 pFS->endElementNS(XML_p, XML_cSld);
1695 pFS->endElementNS(XML_p, XML_sldLayout);
1697 mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] = mnLayoutFileIdMax;
1699 mnLayoutFileIdMax ++;
1701 xDrawPages->remove(xSlide);
1703 pFS->endDocument();
1706 void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType, bool bMaster)
1708 PowerPointShapeExport aDML(pFS, &maShapeMap, this);
1709 aDML.SetMaster(bMaster);
1710 aDML.SetPageType(ePageType);
1711 aDML.SetBackgroundDark(mbIsBackgroundDark);
1713 pFS->startElementNS(XML_p, XML_spTree);
1714 pFS->write(MAIN_GROUP);
1716 ResetGroupTable(mXShapes->getCount());
1718 while (GetNextGroupEntry())
1721 sal_uInt32 nGroups = GetGroupsClosed();
1722 for (sal_uInt32 i = 0; i < nGroups; i++)
1724 SAL_INFO("sd.eppt", "leave group");
1727 if (GetShapeByIndex(GetCurrentGroupIndex(), true))
1729 SAL_INFO("sd.eppt", "mType: " << mType);
1730 const SdrObjGroup* pDiagramCandidate(dynamic_cast<const SdrObjGroup*>(SdrObject::getSdrObjectFromXShape(mXShape)));
1731 const bool bIsDiagram(nullptr != pDiagramCandidate && pDiagramCandidate->isDiagram());
1733 if (bIsDiagram)
1734 WriteDiagram(pFS, aDML, mXShape, mnDiagramId++);
1735 else
1736 aDML.WriteShape(mXShape);
1740 if ( ePageType == NORMAL || ePageType == LAYOUT )
1741 WritePlaceholderReferenceShapes(aDML, ePageType);
1742 pFS->endElementNS(XML_p, XML_spTree);
1745 ShapeExport& PowerPointShapeExport::WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj)
1747 if ((ePageType == NOTICE && bPresObj) || ePageType == LAYOUT || ePageType == MASTER)
1748 return WritePlaceholderShape(xShape, SlideImage);
1750 return WriteTextShape(xShape);
1753 bool PowerPointShapeExport::WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster)
1755 SAL_INFO("sd.eppt", "WritePlaceholder " << bMaster << " " << ShapeExport::NonEmptyText(xShape));
1756 if (!xShape)
1757 return false;
1760 Reference<XPropertySet> xShapeProps(xShape, UNO_QUERY);
1761 if (xShapeProps->getPropertyValue(u"IsPresentationObject"_ustr).get<bool>())
1763 WritePlaceholderShape(xShape, ePlaceholder);
1765 return true;
1768 catch (Exception&)
1770 return false;
1772 return false;
1775 ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder)
1777 Reference<XPropertySet> xProps(xShape, UNO_QUERY);
1778 bool bUseBackground(false);
1779 if (xProps.is() && xProps->getPropertySetInfo()->hasPropertyByName(u"FillUseSlideBackground"_ustr))
1780 xProps->getPropertyValue(u"FillUseSlideBackground"_ustr) >>= bUseBackground;
1782 if (bUseBackground)
1783 mpFS->startElementNS(XML_p, XML_sp, XML_useBgFill, "1");
1784 else
1785 mpFS->startElementNS(XML_p, XML_sp);
1787 // non visual shape properties
1788 mpFS->startElementNS(XML_p, XML_nvSpPr);
1789 const OString aPlaceholderID("PlaceHolder " + OString::number(mnShapeIdMax++));
1790 WriteNonVisualDrawingProperties(xShape, aPlaceholderID.getStr());
1791 mpFS->startElementNS(XML_p, XML_cNvSpPr);
1792 mpFS->singleElementNS(XML_a, XML_spLocks, XML_noGrp, "1");
1793 mpFS->endElementNS(XML_p, XML_cNvSpPr);
1794 mpFS->startElementNS(XML_p, XML_nvPr);
1796 bool bUsePlaceholderIndex
1797 = ePlaceholder == Footer || ePlaceholder == DateAndTime || ePlaceholder == SlideNumber;
1798 const char* pType = getPlaceholderTypeName(ePlaceholder);
1800 SAL_INFO("sd.eppt", "write placeholder " << pType);
1801 if (bUsePlaceholderIndex)
1803 mpFS->singleElementNS(
1804 XML_p, XML_ph, XML_type, pType, XML_idx,
1805 OString::number(
1806 static_cast<PowerPointExport*>(GetFB())->CreateNewPlaceholderIndex(xShape)));
1808 else
1810 if ((mePageType == PageType::LAYOUT || mePageType == PageType::NORMAL)
1811 && ePlaceholder == Outliner)
1812 mpFS->singleElementNS(XML_p, XML_ph);
1813 else
1814 mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
1816 mpFS->endElementNS(XML_p, XML_nvPr);
1817 mpFS->endElementNS(XML_p, XML_nvSpPr);
1819 // visual shape properties
1820 mpFS->startElementNS(XML_p, XML_spPr);
1821 WriteShapeTransformation(xShape, XML_a);
1822 WritePresetShape("rect"_ostr);
1823 if (xProps.is())
1825 WriteBlipFill(xProps, u"Graphic"_ustr);
1826 // Do not forget to export the visible properties.
1827 WriteFill( xProps, xShape->getSize());
1828 WriteOutline( xProps );
1829 WriteShapeEffects( xProps );
1831 bool bHas3DEffectinShape = false;
1832 uno::Sequence<beans::PropertyValue> grabBag;
1833 if (xProps->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr))
1834 xProps->getPropertyValue(u"InteropGrabBag"_ustr) >>= grabBag;
1836 for (auto const& it : grabBag)
1837 if (it.Name == "3DEffectProperties")
1838 bHas3DEffectinShape = true;
1840 if( bHas3DEffectinShape)
1841 Write3DEffects( xProps, /*bIsText=*/false );
1843 mpFS->endElementNS(XML_p, XML_spPr);
1845 WriteTextBox(xShape, XML_p, /*bWritePropertiesAsLstStyles=*/bUsePlaceholderIndex);
1847 mpFS->endElementNS(XML_p, XML_sp);
1849 return *this;
1852 ShapeExport& PowerPointShapeExport::WritePlaceholderReferenceShape(
1853 PlaceholderType ePlaceholder, sal_Int32 nReferencedPlaceholderIdx, PageType ePageType,
1854 const Reference<XPropertySet>& rXPagePropSet)
1856 mpFS->startElementNS(XML_p, XML_sp);
1858 // non visual shape properties
1859 mpFS->startElementNS(XML_p, XML_nvSpPr);
1860 const OString aPlaceholderID("PlaceHolder " + OString::number(mnShapeIdMax++));
1861 GetFS()->singleElementNS(XML_p, XML_cNvPr, XML_id, OString::number(mnShapeIdMax), XML_name,
1862 aPlaceholderID);
1864 mpFS->startElementNS(XML_p, XML_cNvSpPr);
1865 mpFS->singleElementNS(XML_a, XML_spLocks, XML_noGrp, "1");
1866 mpFS->endElementNS(XML_p, XML_cNvSpPr);
1867 mpFS->startElementNS(XML_p, XML_nvPr);
1869 const char* pType = getPlaceholderTypeName(ePlaceholder);
1870 mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType, XML_idx,
1871 OString::number(nReferencedPlaceholderIdx));
1872 mpFS->endElementNS(XML_p, XML_nvPr);
1873 mpFS->endElementNS(XML_p, XML_nvSpPr);
1875 // visual shape properties
1876 mpFS->startElementNS(XML_p, XML_spPr);
1877 mpFS->endElementNS(XML_p, XML_spPr);
1879 WritePlaceholderReferenceTextBody(ePlaceholder, ePageType, rXPagePropSet);
1881 mpFS->endElementNS(XML_p, XML_sp);
1883 return *this;
1886 ShapeExport& PowerPointShapeExport::WritePlaceholderReferenceTextBody(
1887 PlaceholderType ePlaceholder, PageType ePageType, const Reference<XPropertySet>& xPagePropSet)
1889 mpFS->startElementNS(XML_p, XML_txBody);
1890 mpFS->singleElementNS(XML_a, XML_bodyPr);
1891 mpFS->startElementNS(XML_a, XML_p);
1893 switch (ePlaceholder)
1895 case Header:
1896 break;
1897 case Footer:
1899 OUString aFooterText;
1900 if (ePageType == LAYOUT)
1902 aFooterText = "Footer";
1904 else
1906 xPagePropSet->getPropertyValue(u"FooterText"_ustr) >>= aFooterText;
1908 mpFS->startElementNS(XML_a, XML_r);
1909 mpFS->startElementNS(XML_a, XML_t);
1910 mpFS->writeEscaped(aFooterText);
1911 mpFS->endElementNS(XML_a, XML_t);
1912 mpFS->endElementNS(XML_a, XML_r);
1913 break;
1915 case SlideNumber:
1917 OUString aSlideNum;
1918 sal_Int32 nSlideNum = 0;
1919 if (ePageType == LAYOUT)
1921 aSlideNum = "<#>";
1923 else
1925 xPagePropSet->getPropertyValue(u"Number"_ustr) >>= nSlideNum;
1926 aSlideNum = OUString::number(nSlideNum);
1928 OString aUUID(comphelper::xml::generateGUIDString());
1929 mpFS->startElementNS(XML_a, XML_fld, XML_id, aUUID, XML_type, "slidenum");
1930 mpFS->startElementNS(XML_a, XML_t);
1931 mpFS->writeEscaped(aSlideNum);
1932 mpFS->endElementNS(XML_a, XML_t);
1933 mpFS->endElementNS(XML_a, XML_fld);
1934 break;
1936 case DateAndTime:
1938 OUString aDateTimeType = u"datetime1"_ustr;
1939 bool bIsDateTimeFixed = false;
1940 xPagePropSet->getPropertyValue(u"IsDateTimeFixed"_ustr) >>= bIsDateTimeFixed;
1942 OUString aDateTimeText = u"Date"_ustr;
1943 const LanguageTag& rLanguageTag = Application::GetSettings().GetLanguageTag();
1945 if(ePageType != LAYOUT && !bIsDateTimeFixed)
1947 sal_Int32 nDateTimeFormat = 0;
1948 xPagePropSet->getPropertyValue(u"DateTimeFormat"_ustr) >>= nDateTimeFormat;
1950 // 4 LSBs represent the date
1951 SvxDateFormat eDate = static_cast<SvxDateFormat>(nDateTimeFormat & 0x0f);
1952 // the 4 bits after the date bits represent the time
1953 SvxTimeFormat eTime = static_cast<SvxTimeFormat>(nDateTimeFormat >> 4);
1954 aDateTimeType = GetDatetimeTypeFromDateTime(eDate, eTime);
1956 if (aDateTimeType == "datetime")
1957 aDateTimeType = "datetime1";
1959 ::DateTime aDateTime( ::DateTime::SYSTEM );
1961 aDateTimeText = SvxDateTimeField::GetFormatted(
1962 aDateTime, aDateTime, eDate,
1963 eTime, *(SdModule::get()->GetNumberFormatter()),
1964 rLanguageTag.getLanguageType());
1967 if(!bIsDateTimeFixed)
1969 OString aUUID(comphelper::xml::generateGUIDString());
1970 mpFS->startElementNS(XML_a, XML_fld, XML_id, aUUID, XML_type, aDateTimeType);
1972 else
1974 xPagePropSet->getPropertyValue(u"DateTimeText"_ustr) >>= aDateTimeText;
1975 mpFS->startElementNS(XML_a, XML_r);
1978 mpFS->startElementNS(XML_a, XML_rPr, XML_lang, rLanguageTag.getBcp47MS());
1979 mpFS->endElementNS(XML_a, XML_rPr);
1981 mpFS->startElementNS(XML_a, XML_t);
1982 mpFS->writeEscaped(aDateTimeText);
1983 mpFS->endElementNS(XML_a, XML_t);
1985 mpFS->endElementNS(XML_a, bIsDateTimeFixed ? XML_r : XML_fld);
1986 break;
1988 default:
1989 SAL_INFO("sd.eppt", "warning: no defined textbody for referenced placeholder type: "
1990 << ePlaceholder);
1992 mpFS->endElementNS(XML_a, XML_p);
1993 mpFS->endElementNS(XML_p, XML_txBody);
1995 return *this;
1998 void PowerPointExport::WriteDefaultColorSchemes(const FSHelperPtr& pFS)
2000 for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
2002 OUString sName(getPredefinedClrNames(static_cast<PredefinedClrSchemeId>(nId)));
2003 sal_Int32 nColor = 0;
2005 switch (nId)
2007 case PredefinedClrSchemeId::dk2:
2008 nColor = 0x1F497D;
2009 break;
2010 case PredefinedClrSchemeId::lt2:
2011 nColor = 0xEEECE1;
2012 break;
2013 case PredefinedClrSchemeId::accent1:
2014 nColor = 0x4F81BD;
2015 break;
2016 case PredefinedClrSchemeId::accent2:
2017 nColor = 0xC0504D;
2018 break;
2019 case PredefinedClrSchemeId::accent3:
2020 nColor = 0x9BBB59;
2021 break;
2022 case PredefinedClrSchemeId::accent4:
2023 nColor = 0x8064A2;
2024 break;
2025 case PredefinedClrSchemeId::accent5:
2026 nColor = 0x4BACC6;
2027 break;
2028 case PredefinedClrSchemeId::accent6:
2029 nColor = 0xF79646;
2030 break;
2031 case PredefinedClrSchemeId::hlink:
2032 nColor = 0x0000FF;
2033 break;
2034 case PredefinedClrSchemeId::folHlink:
2035 nColor = 0x800080;
2036 break;
2039 OUString sOpenColorScheme = "<a:" + sName + ">";
2040 pFS->write(sOpenColorScheme);
2042 pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor));
2044 OUString sCloseColorScheme = "</a:" + sName + ">";
2045 pFS->write(sCloseColorScheme);
2049 void PowerPointExport::WriteTheme(sal_Int32 nThemeNum, model::Theme* pTheme)
2051 if (!pTheme)
2052 return;
2053 OUString sThemePath = "ppt/theme/theme" + OUString::number(nThemeNum + 1) + ".xml";
2055 oox::ThemeExport aThemeExport(this, DOCUMENT_PPTX);
2057 aThemeExport.write(sThemePath, *pTheme);
2060 bool PowerPointExport::ImplCreateDocument()
2062 mbCreateNotes = false;
2064 for (sal_uInt32 i = 0; i < mnPages; i++)
2066 if (!GetPageByIndex(i, NOTICE))
2067 return false;
2069 if (ContainsOtherShapeThanPlaceholders())
2071 mbCreateNotes = true;
2072 break;
2076 return true;
2079 void PowerPointExport::WriteNotesMaster()
2081 SAL_INFO("sd.eppt", "write Notes master\n---------------");
2083 mPresentationFS->startElementNS(XML_p, XML_notesMasterIdLst);
2085 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
2086 oox::getRelationship(Relationship::NOTESMASTER),
2087 u"notesMasters/notesMaster1.xml");
2089 mPresentationFS->singleElementNS(XML_p, XML_notesMasterId,
2090 FSNS(XML_r, XML_id), sRelId);
2092 mPresentationFS->endElementNS(XML_p, XML_notesMasterIdLst);
2094 FSHelperPtr pFS =
2095 openFragmentStreamWithSerializer(u"ppt/notesMasters/notesMaster1.xml"_ustr,
2096 u"application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml"_ustr);
2097 // write theme per master
2099 // TODO: Need to implement theme support for note master, so the
2100 // note master has his own theme associated.
2102 // For now just use the default theme
2103 auto const* pDefaultColorSet = svx::ColorSets::get().getColorSet(u"LibreOffice");
2104 if (pDefaultColorSet)
2106 auto pTheme = std::make_shared<model::Theme>("Office Theme");
2107 pTheme->setColorSet(std::make_shared<model::ColorSet>(*pDefaultColorSet));
2109 WriteTheme(mnMasterPages, pTheme.get());
2111 // add implicit relation to the presentation theme
2112 addRelation(pFS->getOutputStream(),
2113 oox::getRelationship(Relationship::THEME),
2114 Concat2View("../theme/theme" + OUString::number(mnMasterPages + 1) + ".xml"));
2117 pFS->startElementNS(XML_p, XML_notesMaster, PNMSS);
2119 pFS->startElementNS(XML_p, XML_cSld);
2121 Reference< XPropertySet > aXBackgroundPropSet;
2122 if (ImplGetPropertyValue(mXPagePropSet, u"Background"_ustr) &&
2123 (mAny >>= aXBackgroundPropSet))
2124 ImplWriteBackground(pFS, aXBackgroundPropSet);
2126 WriteShapeTree(pFS, NOTICE, true);
2128 pFS->endElementNS(XML_p, XML_cSld);
2130 // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
2131 pFS->singleElementNS(XML_p, XML_clrMap,
2132 XML_bg1, "lt1",
2133 XML_bg2, "lt2",
2134 XML_tx1, "dk1",
2135 XML_tx2, "dk2",
2136 XML_accent1, "accent1",
2137 XML_accent2, "accent2",
2138 XML_accent3, "accent3",
2139 XML_accent4, "accent4",
2140 XML_accent5, "accent5",
2141 XML_accent6, "accent6",
2142 XML_hlink, "hlink",
2143 XML_folHlink, "folHlink");
2145 pFS->endElementNS(XML_p, XML_notesMaster);
2147 SAL_INFO("sd.eppt", "----------------");
2149 pFS->endDocument();
2152 void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& sUrl, OUString& sRelId, OUString& sName)
2154 comphelper::LifecycleProxy aProxy;
2156 if (!sUrl.endsWithIgnoreAsciiCase(".wav"))
2157 return;
2159 uno::Reference<io::XInputStream> xAudioStream;
2162 if (sUrl.startsWith("vnd.sun.star.Package:"))
2164 uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
2165 if (!xStorageBasedDocument.is())
2166 return;
2168 uno::Reference<embed::XStorage> xDocumentStorage = xStorageBasedDocument->getDocumentStorage();
2169 if (!xDocumentStorage.is())
2170 return;
2172 uno::Reference<io::XStream> xStream = comphelper::OStorageHelper::GetStreamAtPackageURL(xDocumentStorage, sUrl,
2173 css::embed::ElementModes::READ, aProxy);
2175 if (xStream.is())
2176 xAudioStream = xStream->getInputStream();
2178 else
2179 xAudioStream = comphelper::OStorageHelper::GetInputStreamFromURL(sUrl, getComponentContext());
2181 catch (const Exception&)
2183 TOOLS_WARN_EXCEPTION("sd", "PowerPointExport::embedEffectAudio");
2186 if (!xAudioStream.is())
2187 return;
2189 int nLastSlash = sUrl.lastIndexOf('/');
2190 sName = sUrl.copy(nLastSlash >= 0 ? nLastSlash + 1 : 0);
2192 OUString sPath = "../media/" + sName;
2193 sRelId = addRelation(pFS->getOutputStream(),
2194 oox::getRelationship(Relationship::AUDIO), sPath);
2196 uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream(sPath.replaceAt(0, 2, u"/ppt"),
2197 u"audio/x-wav"_ustr);
2199 comphelper::OStorageHelper::CopyInputToOutput(xAudioStream, xOutputStream);
2202 sal_Int32 PowerPointExport::GetShapeID(const Reference<XShape>& rXShape)
2204 return ShapeExport::GetShapeID(rXShape, &maShapeMap);
2207 sal_Int32 PowerPointExport::GetNextAnimationNodeID()
2209 return mnAnimationNodeIdMax++;
2212 bool PowerPointExport::ImplCreateMainNotes()
2214 if (mbCreateNotes)
2215 WriteNotesMaster();
2217 return true;
2220 OUString PowerPointExport::getImplementationName()
2222 return u"com.sun.star.comp.Impress.oox.PowerPointExport"_ustr;
2225 void PowerPointExport::WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId)
2227 SAL_INFO("sd.eppt", "writing Diagram " + OUString::number(nDiagramId));
2228 pFS->startElementNS(XML_p, XML_graphicFrame);
2229 rDML.WriteDiagram(rXShape, nDiagramId);
2230 pFS->endElementNS(XML_p, XML_graphicFrame);
2233 void PowerPointExport::WritePlaceholderReferenceShapes(PowerPointShapeExport& rDML, PageType ePageType)
2235 bool bCheckProps = ePageType == NORMAL;
2236 Reference<XShape> xShape;
2237 Any aAny;
2238 OUString aText;
2239 if (ePageType == LAYOUT
2240 || (bCheckProps && PropValue::GetPropertyValue(aAny, mXPagePropSet, u"IsFooterVisible"_ustr, true)
2241 && aAny == true && GetPropertyValue(aAny, mXPagePropSet, u"FooterText"_ustr, true)
2242 && (aAny >>= aText) && !aText.isEmpty()))
2244 if ((xShape = GetReferencedPlaceholderXShape(Footer, ePageType)))
2246 const auto iter = maPlaceholderShapeToIndexMap.find(xShape);
2247 assert(iter != maPlaceholderShapeToIndexMap.end());
2248 rDML.WritePlaceholderReferenceShape(Footer,
2249 iter->second,
2250 ePageType, mXPagePropSet);
2254 if (ePageType == LAYOUT
2255 || (bCheckProps
2256 && PropValue::GetPropertyValue(aAny, mXPagePropSet, u"IsPageNumberVisible"_ustr, true)
2257 && aAny == true))
2259 if ((xShape = GetReferencedPlaceholderXShape(SlideNumber, ePageType)))
2261 const auto iter = maPlaceholderShapeToIndexMap.find(xShape);
2262 assert(iter != maPlaceholderShapeToIndexMap.end());
2263 rDML.WritePlaceholderReferenceShape(SlideNumber,
2264 iter->second,
2265 ePageType, mXPagePropSet);
2269 if (ePageType == LAYOUT
2270 || (bCheckProps
2271 && PropValue::GetPropertyValue(aAny, mXPagePropSet, u"IsDateTimeVisible"_ustr, true)
2272 && aAny == true
2273 && ((GetPropertyValue(aAny, mXPagePropSet, u"DateTimeText"_ustr, true) && (aAny >>= aText)
2274 && !aText.isEmpty())
2275 || mXPagePropSet->getPropertyValue(u"IsDateTimeFixed"_ustr) == false)))
2277 if ((xShape = GetReferencedPlaceholderXShape(DateAndTime, ePageType)))
2279 const auto iter = maPlaceholderShapeToIndexMap.find(xShape);
2280 assert(iter != maPlaceholderShapeToIndexMap.end());
2281 rDML.WritePlaceholderReferenceShape(DateAndTime,
2282 iter->second,
2283 ePageType, mXPagePropSet);
2288 sal_Int32 PowerPointExport::CreateNewPlaceholderIndex(const css::uno::Reference<XShape> &rXShape)
2290 maPlaceholderShapeToIndexMap.insert({rXShape, mnPlaceholderIndexMax});
2291 return mnPlaceholderIndexMax++;
2294 Reference<XShape> PowerPointExport::GetReferencedPlaceholderXShape(const PlaceholderType eType,
2295 PageType ePageType) const
2297 PresObjKind ePresObjKind = PresObjKind::NONE;
2298 switch (eType)
2300 case oox::core::None:
2301 break;
2302 case oox::core::SlideImage:
2303 break;
2304 case oox::core::Notes:
2305 break;
2306 case oox::core::Header:
2307 ePresObjKind = PresObjKind::Header;
2308 break;
2309 case oox::core::Footer:
2310 ePresObjKind = PresObjKind::Footer;
2311 break;
2312 case oox::core::SlideNumber:
2313 ePresObjKind = PresObjKind::SlideNumber;
2314 break;
2315 case oox::core::DateAndTime:
2316 ePresObjKind = PresObjKind::DateTime;
2317 break;
2318 case oox::core::Outliner:
2319 break;
2320 case oox::core::Title:
2321 ePresObjKind = PresObjKind::Title;
2322 break;
2323 case oox::core::Subtitle:
2324 break;
2326 if (ePresObjKind != PresObjKind::NONE)
2328 SdPage* pMasterPage;
2329 if (ePageType == LAYOUT)
2331 // since Layout pages do not have drawpages themselves - mXDrawPage is still the master they reference to..
2332 pMasterPage = SdPage::getImplementation(mXDrawPage);
2334 else
2336 pMasterPage = &static_cast<SdPage&>(SdPage::getImplementation(mXDrawPage)->TRG_GetMasterPage());
2338 if (SdrObject* pMasterFooter = pMasterPage->GetPresObj(ePresObjKind))
2339 return GetXShapeForSdrObject(pMasterFooter);
2341 return nullptr;
2344 // UNO component
2345 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
2346 css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,
2347 uno::Sequence<css::uno::Any> const& rArguments)
2349 return cppu::acquire(new PowerPointExport(rxCtxt, rArguments));
2352 #if OSL_DEBUG_LEVEL > 1
2353 void dump_pset(Reference< XPropertySet > const& rXPropSet)
2355 Reference< XPropertySetInfo > info = rXPropSet->getPropertySetInfo();
2356 Sequence< beans::Property > props = info->getProperties();
2358 for (int i=0; i < props.getLength(); i++)
2360 OString name = OUStringToOString(props [i].Name, RTL_TEXTENCODING_UTF8);
2362 Any value = rXPropSet->getPropertyValue(props [i].Name);
2364 OUString strValue;
2365 sal_Int32 intValue;
2366 bool boolValue;
2367 RectanglePoint pointValue;
2369 if (value >>= strValue)
2370 SAL_INFO("sd.eppt", name << " = \"" << strValue << "\"");
2371 else if (value >>= intValue)
2372 SAL_INFO("sd.eppt", name << " = " << intValue << "(hex : " << std::hex << intValue << ")");
2373 else if (value >>= boolValue)
2374 SAL_INFO("sd.eppt", name << " = " << boolValue << " (bool)");
2375 else if (value >>= pointValue)
2376 SAL_INFO("sd.eppt", name << " = " << static_cast<int>(pointValue) << " (RectanglePoint)");
2377 else
2378 SAL_INFO("sd.eppt", "??? <unhandled type>");
2381 #endif
2383 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */