bump product version to 6.4.0.3
[LibreOffice.git] / sd / source / filter / eppt / pptx-epptooxml.cxx
blob8a7db7302ff03e5b32528e3f67134cd5f1f4ffc1
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 <sax/fshelper.hxx>
32 #include <rtl/ustrbuf.hxx>
33 #include <sal/log.hxx>
34 #include <com/sun/star/animations/TransitionType.hpp>
35 #include <com/sun/star/animations/TransitionSubType.hpp>
36 #include <com/sun/star/beans/XPropertySetInfo.hpp>
37 #include <com/sun/star/drawing/FillStyle.hpp>
38 #include <com/sun/star/drawing/XDrawPages.hpp>
39 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
40 #include <com/sun/star/embed/ElementModes.hpp>
41 #include <com/sun/star/geometry/RealPoint2D.hpp>
42 #include <com/sun/star/office/XAnnotationEnumeration.hpp>
43 #include <com/sun/star/office/XAnnotationAccess.hpp>
44 #include <com/sun/star/presentation/AnimationSpeed.hpp>
45 #include <com/sun/star/util/DateTime.hpp>
46 #include <com/sun/star/task/XStatusIndicator.hpp>
47 #include <com/sun/star/frame/XModel.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <oox/export/utils.hxx>
52 #include "pptx-animations.hxx"
53 #include "../ppt/pptanimations.hxx"
55 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
56 #include <com/sun/star/document/XStorageBasedDocument.hpp>
57 #include <utility>
58 #if OSL_DEBUG_LEVEL > 1
59 #include <com/sun/star/drawing/RectanglePoint.hpp>
60 #endif
62 // presentation namespaces
63 #define PNMSS FSNS(XML_xmlns, XML_a), OUStringToOString(this->getNamespaceURL(OOX_NS(dml)), RTL_TEXTENCODING_UTF8).getStr(), \
64 FSNS(XML_xmlns, XML_p), OUStringToOString(this->getNamespaceURL(OOX_NS(ppt)), RTL_TEXTENCODING_UTF8).getStr(), \
65 FSNS(XML_xmlns, XML_r), OUStringToOString(this->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr(), \
66 FSNS(XML_xmlns, XML_p14), OUStringToOString(this->getNamespaceURL(OOX_NS(p14)), RTL_TEXTENCODING_UTF8).getStr(), \
67 FSNS(XML_xmlns, XML_p15), OUStringToOString(this->getNamespaceURL(OOX_NS(p15)), RTL_TEXTENCODING_UTF8).getStr(), \
68 FSNS(XML_xmlns, XML_mc), OUStringToOString(this->getNamespaceURL(OOX_NS(mce)), RTL_TEXTENCODING_UTF8).getStr()
71 using namespace ::com::sun::star;
72 using namespace ::com::sun::star::animations;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::container;
75 using namespace ::com::sun::star::drawing;
76 using namespace ::com::sun::star::geometry;
77 using namespace ::com::sun::star::presentation;
78 using namespace ::com::sun::star::office;
79 using namespace ::com::sun::star::text;
80 using namespace ::com::sun::star::uno;
81 using namespace ::com::sun::star::util;
82 using namespace ::ppt;
83 using ::com::sun::star::beans::XPropertySet;
84 using ::com::sun::star::beans::XPropertySetInfo;
85 using ::com::sun::star::container::XIndexAccess;
86 using ::sax_fastparser::FSHelperPtr;
87 using namespace oox::drawingml;
88 using namespace oox::core;
90 #if OSL_DEBUG_LEVEL > 1
91 void dump_pset(Reference< XPropertySet > const& rXPropSet);
92 #endif
94 namespace oox
96 namespace core
99 class PowerPointShapeExport : public ShapeExport
101 PowerPointExport& mrExport;
102 PageType mePageType;
103 bool mbMaster;
104 public:
105 PowerPointShapeExport(FSHelperPtr pFS, ShapeHashMap* pShapeMap, PowerPointExport* pFB);
106 void SetMaster(bool bMaster);
107 void SetPageType(PageType ePageType);
108 ShapeExport& WriteNonVisualProperties(const Reference< XShape >& xShape) override;
109 ShapeExport& WriteTextShape(const Reference< XShape >& xShape) override;
110 ShapeExport& WriteUnknownShape(const Reference< XShape >& xShape) override;
111 ShapeExport& WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder);
112 ShapeExport& WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj);
114 // helper parts
115 bool WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster);
119 namespace
121 void WriteSndAc(const FSHelperPtr& pFS, const OUString& sSoundRelId, const OUString& sSoundName)
123 pFS->startElementNS(XML_p, XML_sndAc);
124 pFS->startElementNS(XML_p, XML_stSnd);
125 pFS->singleElementNS(XML_p, XML_snd,
126 FSNS(XML_r, XML_embed), sSoundRelId.isEmpty() ? nullptr : sSoundRelId.toUtf8().getStr(),
127 XML_name, sSoundName.isEmpty() ? nullptr : sSoundName.toUtf8().getStr());
128 pFS->endElement(FSNS(XML_p, XML_stSnd));
129 pFS->endElement(FSNS(XML_p, XML_sndAc));
136 enum PPTXLayout
138 LAYOUT_BLANK,
139 LAYOUT_TITLE_SLIDE,
140 LAYOUT_TITLE_CONTENT,
141 LAYOUT_TITLE_2CONTENT,
142 LAYOUT_TITLE,
143 LAYOUT_CENTERED_TEXT,
144 LAYOUT_TITLE_2CONTENT_CONTENT,
145 LAYOUT_TITLE_CONTENT_2CONTENT,
146 LAYOUT_TITLE_2CONTENT_OVER_CONTENT,
147 LAYOUT_TITLE_CONTENT_OVER_CONTENT,
148 LAYOUT_TITLE_4CONTENT,
149 LAYOUT_TITLE_6CONTENT,
150 LAYOUT_SIZE
153 struct PPTXLayoutInfo
155 int const nType;
156 const char* sName;
157 const char* sType;
160 static const PPTXLayoutInfo aLayoutInfo[LAYOUT_SIZE] =
162 { 20, "Blank Slide", "blank" },
163 { 0, "Title Slide", "tx" },
164 { 1, "Title, Content", "obj" },
165 { 3, "Title, 2 Content", "twoObj" },
166 { 19, "Title Only", "titleOnly" },
167 { 32, "Centered Text", "objOnly" }, // not exactly, but close
168 { 15, "Title, 2 Content and Content", "twoObjAndObj" },
169 { 12, "Title Content and 2 Content", "objAndTwoObj" },
170 { 16, "Title, 2 Content over Content", "twoObjOverTx" }, // not exactly, but close
171 { 14, "Title, Content over Content", "objOverTx" }, // not exactly, but close
172 { 18, "Title, 4 Content", "fourObj" },
173 { 34, "Title, 6 Content", "blank" } // not defined => blank
176 int PowerPointExport::GetPPTXLayoutId(int nOffset)
178 int nId = LAYOUT_BLANK;
180 SAL_INFO("sd.eppt", "GetPPTXLayoutId " << nOffset);
182 switch (nOffset)
184 case 0:
185 nId = LAYOUT_TITLE_SLIDE;
186 break;
187 case 1:
188 nId = LAYOUT_TITLE_CONTENT;
189 break;
190 case 3:
191 nId = LAYOUT_TITLE_2CONTENT;
192 break;
193 case 19:
194 nId = LAYOUT_TITLE;
195 break;
196 case 15:
197 nId = LAYOUT_TITLE_2CONTENT_CONTENT;
198 break;
199 case 12:
200 nId = LAYOUT_TITLE_CONTENT_2CONTENT;
201 break;
202 case 16:
203 nId = LAYOUT_TITLE_2CONTENT_OVER_CONTENT;
204 break;
205 case 14:
206 nId = LAYOUT_TITLE_CONTENT_OVER_CONTENT;
207 break;
208 case 18:
209 nId = LAYOUT_TITLE_4CONTENT;
210 break;
211 case 32:
212 nId = LAYOUT_CENTERED_TEXT;
213 break;
214 case 34:
215 nId = LAYOUT_TITLE_6CONTENT;
216 break;
217 case 20:
218 default:
219 nId = LAYOUT_BLANK;
220 break;
223 return nId;
226 PowerPointShapeExport::PowerPointShapeExport(FSHelperPtr pFS, ShapeHashMap* pShapeMap,
227 PowerPointExport* pFB)
228 : ShapeExport(XML_p, std::move(pFS), pShapeMap, pFB)
229 , mrExport(*pFB)
230 , mePageType(UNDEFINED)
231 , mbMaster(false)
235 void PowerPointShapeExport::SetMaster(bool bMaster)
237 mbMaster = bMaster;
240 void PowerPointShapeExport::SetPageType(PageType ePageType)
242 mePageType = ePageType;
245 ShapeExport& PowerPointShapeExport::WriteNonVisualProperties(const Reference< XShape >&)
247 GetFS()->singleElementNS(XML_p, XML_nvPr);
249 return *this;
252 ShapeExport& PowerPointShapeExport::WriteTextShape(const Reference< XShape >& xShape)
254 OUString sShapeType = xShape->getShapeType();
256 SAL_INFO("sd.eppt", "shape(text) : " << sShapeType.toUtf8());
258 if (sShapeType == "com.sun.star.drawing.TextShape" || sShapeType == "com.sun.star.drawing.GraphicObjectShape")
260 ShapeExport::WriteTextShape(xShape);
262 else if (sShapeType == "com.sun.star.presentation.DateTimeShape")
264 if (!WritePlaceholder(xShape, DateAndTime, mbMaster))
265 ShapeExport::WriteTextShape(xShape);
267 else if (sShapeType == "com.sun.star.presentation.FooterShape")
269 if (!WritePlaceholder(xShape, Footer, mbMaster))
270 ShapeExport::WriteTextShape(xShape);
272 else if (sShapeType == "com.sun.star.presentation.HeaderShape")
274 if (!WritePlaceholder(xShape, Header, mbMaster))
275 ShapeExport::WriteTextShape(xShape);
277 else if (sShapeType == "com.sun.star.presentation.NotesShape")
279 if (mePageType == NOTICE && mrExport.GetPresObj())
280 WritePlaceholderShape(xShape, Notes);
281 else
282 ShapeExport::WriteTextShape(xShape);
284 else if (sShapeType == "com.sun.star.presentation.OutlinerShape")
286 if (!WritePlaceholder(xShape, Outliner, mbMaster))
287 ShapeExport::WriteTextShape(xShape);
289 else if (sShapeType == "com.sun.star.presentation.SlideNumberShape")
291 if (!WritePlaceholder(xShape, SlideNumber, mbMaster))
292 ShapeExport::WriteTextShape(xShape);
294 else if (sShapeType == "com.sun.star.presentation.TitleTextShape")
296 if (!WritePlaceholder(xShape, Title, mbMaster))
297 ShapeExport::WriteTextShape(xShape);
299 else
300 SAL_WARN("sd.eppt", "PowerPointShapeExport::WriteTextShape: shape of type '" << sShapeType << "' is ignored");
302 return *this;
305 ShapeExport& PowerPointShapeExport::WriteUnknownShape(const Reference< XShape >& xShape)
307 OUString sShapeType = xShape->getShapeType();
309 SAL_INFO("sd.eppt", "shape(unknown): " << sShapeType.toUtf8());
311 if (sShapeType == "com.sun.star.presentation.PageShape")
313 WritePageShape(xShape, mePageType, mrExport.GetPresObj());
315 else if (sShapeType == "com.sun.star.presentation.SubtitleShape")
317 if(mePageType != MASTER)
319 if (!WritePlaceholder(xShape, Subtitle, mbMaster))
320 ShapeExport::WriteTextShape(xShape);
323 else
324 SAL_WARN("sd.eppt", "unknown shape not handled: " << sShapeType.toUtf8());
326 return *this;
329 PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContext, const uno::Sequence<uno::Any>& rArguments)
330 : XmlFilterBase(rContext)
331 , PPTWriterBase()
332 , mnLayoutFileIdMax(1)
333 , mnSlideIdMax(1 << 8)
334 , mnSlideMasterIdMax(1U << 31)
335 , mnAnimationNodeIdMax(1)
336 , mnDiagramId(1)
337 , mbCreateNotes(false)
339 comphelper::SequenceAsHashMap aArgumentsMap(rArguments);
340 mbPptm = aArgumentsMap.getUnpackedValueOrDefault("IsPPTM", false);
341 mbExportTemplate = aArgumentsMap.getUnpackedValueOrDefault("IsTemplate", false);
344 PowerPointExport::~PowerPointExport()
348 void PowerPointExport::writeDocumentProperties()
350 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(mXModel, uno::UNO_QUERY);
351 uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
353 if (xDocProps.is())
355 bool bSecurityOptOpenReadOnly = false;
356 uno::Reference< lang::XMultiServiceFactory > xFactory(mXModel, uno::UNO_QUERY);
357 uno::Reference< beans::XPropertySet > xSettings(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
360 xSettings->getPropertyValue("LoadReadonly") >>= bSecurityOptOpenReadOnly;
362 catch( Exception& )
365 exportDocumentProperties(xDocProps, bSecurityOptOpenReadOnly);
368 exportCustomFragments();
371 bool PowerPointExport::importDocument() throw()
373 return false;
376 bool PowerPointExport::exportDocument()
378 DrawingML::ResetCounters();
379 maShapeMap.clear();
381 mXModel = getModel();
383 //write document properties
384 writeDocumentProperties();
386 addRelation(oox::getRelationship(Relationship::OFFICEDOCUMENT), "ppt/presentation.xml");
388 OUString aMediaType;
389 if (mbPptm)
391 if (mbExportTemplate)
393 aMediaType = "application/vnd.ms-powerpoint.template.macroEnabled.main+xml";
395 else
397 aMediaType = "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml";
400 else
402 if (mbExportTemplate)
404 aMediaType = "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml";
406 else
408 aMediaType = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
412 mPresentationFS = openFragmentStreamWithSerializer("ppt/presentation.xml", aMediaType);
414 addRelation(mPresentationFS->getOutputStream(),
415 oox::getRelationship(Relationship::THEME),
416 "theme/theme1.xml");
418 mPresentationFS->startElementNS(XML_p, XML_presentation, PNMSS);
420 mXStatusIndicator = getStatusIndicator();
422 std::vector< PropertyValue > aProperties;
423 PropertyValue aProperty;
424 aProperty.Name = "BaseURI";
425 aProperty.Value <<= getFileUrl();
426 aProperties.push_back(aProperty);
428 exportPPT(aProperties);
430 mPresentationFS->singleElementNS(XML_p, XML_sldSz,
431 XML_cx, OString::number(PPTtoEMU(maDestPageSize.Width)),
432 XML_cy, OString::number(PPTtoEMU(maDestPageSize.Height)));
433 // for some reason if added before slides list it will not load the slides (alas with error reports) in mso
434 mPresentationFS->singleElementNS(XML_p, XML_notesSz,
435 XML_cx, OString::number(PPTtoEMU(maNotesPageSize.Width)),
436 XML_cy, OString::number(PPTtoEMU(maNotesPageSize.Height)));
438 WriteAuthors();
440 WriteVBA();
442 mPresentationFS->endElementNS(XML_p, XML_presentation);
443 mPresentationFS.reset();
444 // Free all FSHelperPtr, to flush data before committing storage
445 mpSlidesFSArray.clear();
447 commitStorage();
449 maShapeMap.clear();
450 maAuthors.clear();
452 return true;
455 ::oox::ole::VbaProject* PowerPointExport::implCreateVbaProject() const
457 return new ::oox::ole::VbaProject(getComponentContext(), getModel(), "Impress");
460 void PowerPointExport::ImplWriteBackground(const FSHelperPtr& pFS, const Reference< XPropertySet >& rXPropSet)
462 FillStyle aFillStyle(FillStyle_NONE);
463 if (ImplGetPropertyValue(rXPropSet, "FillStyle"))
464 mAny >>= aFillStyle;
466 if (aFillStyle == FillStyle_NONE ||
467 aFillStyle == FillStyle_HATCH)
468 return;
470 pFS->startElementNS(XML_p, XML_bg);
471 pFS->startElementNS(XML_p, XML_bgPr);
473 PowerPointShapeExport aDML(pFS, &maShapeMap, this);
474 aDML.SetBackgroundDark(mbIsBackgroundDark);
475 aDML.WriteFill(rXPropSet);
477 pFS->endElementNS(XML_p, XML_bgPr);
478 pFS->endElementNS(XML_p, XML_bg);
481 #define MAIN_GROUP \
482 "<p:nvGrpSpPr>\
483 <p:cNvPr id=\"1\" name=\"\"/>\
484 <p:cNvGrpSpPr/>\
485 <p:nvPr/>\
486 </p:nvGrpSpPr>\
487 <p:grpSpPr>\
488 <a:xfrm>\
489 <a:off x=\"0\" y=\"0\"/>\
490 <a:ext cx=\"0\" cy=\"0\"/>\
491 <a:chOff x=\"0\" y=\"0\"/>\
492 <a:chExt cx=\"0\" cy=\"0\"/>\
493 </a:xfrm>\
494 </p:grpSpPr>"
496 const char* PowerPointExport::GetSideDirection(sal_uInt8 nDirection)
498 const char* pDirection = nullptr;
500 switch (nDirection)
502 case 0:
503 pDirection = "l";
504 break;
505 case 1:
506 pDirection = "u";
507 break;
508 case 2:
509 pDirection = "r";
510 break;
511 case 3:
512 pDirection = "d";
513 break;
516 return pDirection;
519 const char* PowerPointExport::GetCornerDirection(sal_uInt8 nDirection)
521 const char* pDirection = nullptr;
523 switch (nDirection)
525 case 4:
526 pDirection = "lu";
527 break;
528 case 5:
529 pDirection = "ru";
530 break;
531 case 6:
532 pDirection = "ld";
533 break;
534 case 7:
535 pDirection = "rd";
536 break;
539 return pDirection;
542 const char* PowerPointExport::Get8Direction(sal_uInt8 nDirection)
544 const char* pDirection = GetSideDirection(nDirection);
546 if (!pDirection)
547 pDirection = GetCornerDirection(nDirection);
549 return pDirection;
552 void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
554 FadeEffect eFadeEffect = FadeEffect_NONE;
555 if (ImplGetPropertyValue(mXPagePropSet, "Effect"))
556 mAny >>= eFadeEffect;
558 sal_Int16 nTransitionType = 0, nTransitionSubtype = 0;
559 sal_Int8 nPPTTransitionType = 0;
560 sal_uInt8 nDirection = 0;
562 OUString sSoundUrl;
563 OUString sSoundRelId;
564 OUString sSoundName;
566 if (ImplGetPropertyValue(mXPagePropSet, "TransitionType") && (mAny >>= nTransitionType) &&
567 ImplGetPropertyValue(mXPagePropSet, "TransitionSubtype") && (mAny >>= nTransitionSubtype))
568 nPPTTransitionType = GetTransition(nTransitionType, nTransitionSubtype, eFadeEffect, nDirection);
570 if (!nPPTTransitionType && eFadeEffect != FadeEffect_NONE)
571 nPPTTransitionType = GetTransition(eFadeEffect, nDirection);
573 if (ImplGetPropertyValue(mXPagePropSet, "Sound") && (mAny >>= sSoundUrl))
574 embedEffectAudio(pFS, sSoundUrl, sSoundRelId, sSoundName);
576 bool bOOXmlSpecificTransition = false;
578 sal_Int32 nTransition = 0;
579 const char* pDirection = nullptr;
580 const char* pOrientation = nullptr;
581 const char* pThruBlk = nullptr;
582 const char* pSpokes = nullptr;
584 char pSpokesTmp[2] = "0";
586 // p14
587 sal_Int32 nTransition14 = 0;
588 const char* pDirection14 = nullptr;
589 const char* pInverted = nullptr;
590 const char* pPattern = nullptr; // diamond or hexagon
592 //p15
593 const char* pPresetTransition = nullptr;
595 if (!nPPTTransitionType)
597 switch (nTransitionType)
599 case animations::TransitionType::BARWIPE:
601 if (nTransitionSubtype == animations::TransitionSubType::FADEOVERCOLOR)
603 nTransition = XML_cut;
604 pThruBlk = "true";
605 bOOXmlSpecificTransition = true;
607 break;
609 case animations::TransitionType::MISCSHAPEWIPE:
611 switch (nTransitionSubtype)
613 case animations::TransitionSubType::TOPTOBOTTOM: // Turn around
614 nTransition = XML_fade;
615 nTransition14 = XML_flip;
616 pDirection14 = "l";
617 bOOXmlSpecificTransition = true;
618 break;
619 case animations::TransitionSubType::BOTTOMRIGHT: // Rochade
620 nTransition = XML_fade;
621 nTransition14 = XML_switch;
622 pDirection14 = "r";
623 bOOXmlSpecificTransition = true;
624 break;
625 case animations::TransitionSubType::VERTICAL: // Vortex
626 nTransition = XML_fade;
627 nTransition14 = XML_vortex;
628 bOOXmlSpecificTransition = true;
629 break;
630 case animations::TransitionSubType::HORIZONTAL: // Ripple
631 nTransition = XML_fade;
632 nTransition14 = XML_ripple;
633 bOOXmlSpecificTransition = true;
634 break;
635 case animations::TransitionSubType::LEFTTORIGHT: // Fall
636 nTransition = XML_fade;
637 pPresetTransition = "fallOver";
638 bOOXmlSpecificTransition = true;
639 break;
640 case animations::TransitionSubType::CORNERSIN: // Inside turning cube
641 pInverted = "true";
642 [[fallthrough]];
643 case animations::TransitionSubType::CORNERSOUT: // Outside turning cube
644 nTransition = XML_fade;
645 nTransition14 = XML_prism;
646 bOOXmlSpecificTransition = true;
647 break;
648 case animations::TransitionSubType::DIAMOND: // Glitter
649 nTransition = XML_fade;
650 nTransition14 = XML_glitter;
651 pDirection14 = "l";
652 pPattern = "hexagon";
653 bOOXmlSpecificTransition = true;
654 break;
655 case animations::TransitionSubType::HEART: // Honeycomb
656 nTransition = XML_fade;
657 nTransition14 = XML_honeycomb;
658 bOOXmlSpecificTransition = true;
659 break;
661 break;
666 AnimationSpeed animationSpeed = AnimationSpeed_MEDIUM;
667 const char* speed = nullptr;
668 sal_Int32 advanceTiming = -1;
669 sal_Int32 changeType = 0;
671 sal_Int32 nTransitionDuration = -1;
672 bool isTransitionDurationSet = false;
674 // try to use TransitionDuration instead of old Speed property
675 if (ImplGetPropertyValue(mXPagePropSet, "TransitionDuration"))
677 double fTransitionDuration = -1.0;
678 mAny >>= fTransitionDuration;
679 if (fTransitionDuration >= 0)
681 nTransitionDuration = fTransitionDuration * 1000.0;
683 // override values because in MS formats meaning of fast/medium/slow is different
684 if (nTransitionDuration <= 500)
686 // fast is default
687 speed = nullptr;
689 else if (nTransitionDuration >= 1000)
691 speed = "slow";
693 else
695 speed = "med";
698 bool isStandardValue = nTransitionDuration == 500
699 || nTransitionDuration == 750
700 || nTransitionDuration == 1000;
702 if(!isStandardValue)
703 isTransitionDurationSet = true;
706 else if (ImplGetPropertyValue(mXPagePropSet, "Speed"))
708 mAny >>= animationSpeed;
710 switch (animationSpeed)
712 default:
713 case AnimationSpeed_MEDIUM:
714 speed = "med";
715 break;
716 case AnimationSpeed_SLOW:
717 speed = "slow";
718 break;
719 case AnimationSpeed_FAST:
720 break;
724 // check if we resolved what transition to export or time is set
725 if (!nPPTTransitionType && !bOOXmlSpecificTransition && !isTransitionDurationSet)
726 return;
728 if (ImplGetPropertyValue(mXPagePropSet, "Change"))
729 mAny >>= changeType;
731 // 1 means automatic, 2 half automatic - not sure what it means - at least I don't see it in UI
732 if (changeType == 1 && ImplGetPropertyValue(mXPagePropSet, "Duration"))
733 mAny >>= advanceTiming;
735 if (!bOOXmlSpecificTransition)
737 switch (nPPTTransitionType)
739 case PPT_TRANSITION_TYPE_BLINDS:
740 nTransition = XML_blinds;
741 pDirection = (nDirection == 0) ? "vert" : "horz";
742 break;
743 case PPT_TRANSITION_TYPE_CHECKER:
744 nTransition = XML_checker;
745 pDirection = (nDirection == 1) ? "vert" : "horz";
746 break;
747 case PPT_TRANSITION_TYPE_CIRCLE:
748 nTransition = XML_circle;
749 break;
750 case PPT_TRANSITION_TYPE_COMB:
751 nTransition = XML_comb;
752 pDirection = (nDirection == 1) ? "vert" : "horz";
753 break;
754 case PPT_TRANSITION_TYPE_COVER:
755 nTransition = XML_cover;
756 pDirection = Get8Direction(nDirection);
757 break;
758 case PPT_TRANSITION_TYPE_DIAMOND:
759 nTransition = XML_diamond;
760 break;
761 case PPT_TRANSITION_TYPE_DISSOLVE:
762 nTransition = XML_dissolve;
763 break;
764 case PPT_TRANSITION_TYPE_FADE:
765 nTransition = XML_fade;
766 pThruBlk = "true";
767 break;
768 case PPT_TRANSITION_TYPE_SMOOTHFADE:
769 nTransition = XML_fade;
770 break;
771 case PPT_TRANSITION_TYPE_NEWSFLASH:
772 nTransition = XML_newsflash;
773 break;
774 case PPT_TRANSITION_TYPE_PLUS:
775 nTransition = XML_plus;
776 break;
777 case PPT_TRANSITION_TYPE_PULL:
778 nTransition = XML_pull;
779 pDirection = Get8Direction(nDirection);
780 break;
781 case PPT_TRANSITION_TYPE_PUSH:
782 nTransition = XML_push;
783 pDirection = GetSideDirection(nDirection);
784 break;
785 case PPT_TRANSITION_TYPE_RANDOM:
786 nTransition = XML_random;
787 break;
788 case PPT_TRANSITION_TYPE_RANDOM_BARS:
789 nTransition = XML_randomBar;
790 pDirection = (nDirection == 1) ? "vert" : "horz";
791 break;
792 case PPT_TRANSITION_TYPE_SPLIT:
793 nTransition = XML_split;
794 pDirection = (nDirection & 1) ? "in" : "out";
795 pOrientation = (nDirection < 2) ? "horz" : "vert";
796 break;
797 case PPT_TRANSITION_TYPE_STRIPS:
798 nTransition = XML_strips;
799 pDirection = GetCornerDirection(nDirection);
800 break;
801 case PPT_TRANSITION_TYPE_WEDGE:
802 nTransition = XML_wedge;
803 break;
804 case PPT_TRANSITION_TYPE_WHEEL:
805 nTransition = XML_wheel;
806 if (nDirection != 4 && nDirection <= 9)
808 pSpokesTmp[0] = '0' + nDirection;
809 pSpokes = pSpokesTmp;
811 break;
812 case PPT_TRANSITION_TYPE_WIPE:
813 nTransition = XML_wipe;
814 pDirection = GetSideDirection(nDirection);
815 break;
816 case PPT_TRANSITION_TYPE_ZOOM:
817 nTransition = XML_zoom;
818 pDirection = (nDirection == 1) ? "in" : "out";
819 break;
820 // coverity[dead_error_line] - following conditions exist to avoid compiler warning
821 case PPT_TRANSITION_TYPE_NONE:
822 default:
823 nTransition = 0;
824 break;
828 bool isAdvanceTimingSet = advanceTiming != -1;
829 if (nTransition14 || pPresetTransition || isTransitionDurationSet)
831 const char* pRequiresNS = (nTransition14 || isTransitionDurationSet) ? "p14" : "p15";
833 pFS->startElement(FSNS(XML_mc, XML_AlternateContent));
834 pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS);
836 if(isTransitionDurationSet && isAdvanceTimingSet)
838 pFS->startElementNS(XML_p, XML_transition,
839 XML_spd, speed,
840 XML_advTm, OString::number(advanceTiming * 1000),
841 FSNS(XML_p14, XML_dur), OString::number(nTransitionDuration));
843 else if(isTransitionDurationSet)
845 pFS->startElementNS(XML_p, XML_transition,
846 XML_spd, speed,
847 FSNS(XML_p14, XML_dur), OString::number(nTransitionDuration));
849 else if(isAdvanceTimingSet)
851 pFS->startElementNS(XML_p, XML_transition,
852 XML_spd, speed,
853 XML_advTm, OString::number(advanceTiming * 1000));
855 else
857 pFS->startElementNS(XML_p, XML_transition, XML_spd, speed);
860 if (nTransition14)
862 pFS->singleElementNS(XML_p14, nTransition14,
863 XML_isInverted, pInverted,
864 XML_dir, pDirection14,
865 XML_pattern, pPattern);
867 else if (pPresetTransition)
869 pFS->singleElementNS(XML_p15, XML_prstTrans,
870 XML_prst, pPresetTransition);
872 else if (isTransitionDurationSet && nTransition)
874 pFS->singleElementNS(XML_p, nTransition,
875 XML_dir, pDirection,
876 XML_orient, pOrientation,
877 XML_spokes, pSpokes,
878 XML_thruBlk, pThruBlk);
881 if (!sSoundRelId.isEmpty())
882 WriteSndAc(pFS, sSoundRelId, sSoundName);
884 pFS->endElement(FSNS(XML_p, XML_transition));
886 pFS->endElement(FSNS(XML_mc, XML_Choice));
887 pFS->startElement(FSNS(XML_mc, XML_Fallback));
890 pFS->startElementNS(XML_p, XML_transition,
891 XML_spd, speed,
892 XML_advTm, isAdvanceTimingSet ? OString::number(advanceTiming * 1000).getStr() : nullptr);
894 if (nTransition)
896 pFS->singleElementNS(XML_p, nTransition,
897 XML_dir, pDirection,
898 XML_orient, pOrientation,
899 XML_spokes, pSpokes,
900 XML_thruBlk, pThruBlk);
903 if (!sSoundRelId.isEmpty())
904 WriteSndAc(pFS, sSoundRelId, sSoundName);
906 pFS->endElementNS(XML_p, XML_transition);
908 if (nTransition14 || pPresetTransition || isTransitionDurationSet)
910 pFS->endElement(FSNS(XML_mc, XML_Fallback));
911 pFS->endElement(FSNS(XML_mc, XML_AlternateContent));
915 static OUString lcl_GetInitials(const OUString& sName)
917 OUStringBuffer sRet;
919 if (!sName.isEmpty())
921 sRet.append(sName[0]);
922 sal_Int32 nStart = 0, nOffset;
924 while ((nOffset = sName.indexOf(' ', nStart)) != -1)
926 if (nOffset + 1 < sName.getLength())
927 sRet.append(sName[ nOffset + 1 ]);
928 nStart = nOffset + 1;
932 return sRet.makeStringAndClear();
935 void PowerPointExport::WriteAuthors()
937 if (maAuthors.empty())
938 return;
940 FSHelperPtr pFS = openFragmentStreamWithSerializer("ppt/commentAuthors.xml",
941 "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml");
942 addRelation(mPresentationFS->getOutputStream(),
943 oox::getRelationship(Relationship::COMMENTAUTHORS),
944 "commentAuthors.xml");
946 pFS->startElementNS(XML_p, XML_cmAuthorLst,
947 FSNS(XML_xmlns, XML_p), this->getNamespaceURL(OOX_NS(ppt)).toUtf8());
949 for (const AuthorsMap::value_type& i : maAuthors)
951 pFS->singleElementNS(XML_p, XML_cmAuthor,
952 XML_id, OString::number(i.second.nId),
953 XML_name, i.first.toUtf8(),
954 XML_initials, lcl_GetInitials(i.first).toUtf8(),
955 XML_lastIdx, OString::number(i.second.nLastIndex),
956 XML_clrIdx, OString::number(i.second.nId));
959 pFS->endElementNS(XML_p, XML_cmAuthorLst);
962 sal_Int32 PowerPointExport::GetAuthorIdAndLastIndex(const OUString& sAuthor, sal_Int32& nLastIndex)
964 if (maAuthors.count(sAuthor) <= 0)
966 struct AuthorComments aAuthorComments;
968 aAuthorComments.nId = maAuthors.size();
969 aAuthorComments.nLastIndex = 0;
971 maAuthors[ sAuthor ] = aAuthorComments;
974 nLastIndex = ++maAuthors[ sAuthor ].nLastIndex;
976 return maAuthors[ sAuthor ].nId;
979 bool PowerPointExport::WriteComments(sal_uInt32 nPageNum)
981 Reference< XAnnotationAccess > xAnnotationAccess(mXDrawPage, uno::UNO_QUERY);
982 if (xAnnotationAccess.is())
984 Reference< XAnnotationEnumeration > xAnnotationEnumeration(xAnnotationAccess->createAnnotationEnumeration());
986 if (xAnnotationEnumeration->hasMoreElements())
988 FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
989 .append("ppt/comments/comment")
990 .append(static_cast<sal_Int32>(nPageNum) + 1)
991 .append(".xml")
992 .makeStringAndClear(),
993 "application/vnd.openxmlformats-officedocument.presentationml.comments+xml");
995 pFS->startElementNS(XML_p, XML_cmLst,
996 FSNS(XML_xmlns, XML_p), this->getNamespaceURL(OOX_NS(ppt)).toUtf8());
1000 Reference< XAnnotation > xAnnotation(xAnnotationEnumeration->nextElement());
1001 DateTime aDateTime(xAnnotation->getDateTime());
1002 RealPoint2D aRealPoint2D(xAnnotation->getPosition());
1003 Reference< XText > xText(xAnnotation->getTextRange());
1004 sal_Int32 nLastIndex;
1005 sal_Int32 nId = GetAuthorIdAndLastIndex(xAnnotation->getAuthor(), nLastIndex);
1006 char cDateTime[sizeof("-32768-65535-65535T65535:65535:65535.4294967295")];
1007 // reserve enough space for hypothetical max length
1009 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);
1011 pFS->startElementNS(XML_p, XML_cm,
1012 XML_authorId, OString::number(nId),
1013 XML_dt, cDateTime,
1014 XML_idx, OString::number(nLastIndex));
1016 pFS->singleElementNS(XML_p, XML_pos,
1017 XML_x, OString::number(static_cast<sal_Int64>((57600*aRealPoint2D.X + 1270)/2540.0)),
1018 XML_y, OString::number(static_cast<sal_Int64>((57600*aRealPoint2D.Y + 1270)/2540.0)));
1020 pFS->startElementNS(XML_p, XML_text);
1021 pFS->write(xText->getString());
1022 pFS->endElementNS(XML_p, XML_text);
1024 pFS->endElementNS(XML_p, XML_cm);
1027 while (xAnnotationEnumeration->hasMoreElements());
1029 pFS->endElementNS(XML_p, XML_cmLst);
1031 return true;
1035 return false;
1038 void PowerPointExport::WriteVBA()
1040 if (!mbPptm)
1041 return;
1043 uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
1044 if (!xStorageBasedDocument.is())
1045 return;
1047 uno::Reference<embed::XStorage> xDocumentStorage = xStorageBasedDocument->getDocumentStorage();
1048 OUString aMacrosName("_MS_VBA_Macros");
1049 if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aMacrosName))
1050 return;
1052 const sal_Int32 nOpenMode = embed::ElementModes::READ;
1053 uno::Reference<io::XInputStream> xMacrosStream(xDocumentStorage->openStreamElement(aMacrosName, nOpenMode), uno::UNO_QUERY);
1054 if (!xMacrosStream.is())
1055 return;
1057 uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream("ppt/vbaProject.bin", "application/vnd.ms-office.vbaProject");
1058 comphelper::OStorageHelper::CopyInputToOutput(xMacrosStream, xOutputStream);
1060 // Write the relationship.
1061 addRelation(mPresentationFS->getOutputStream(), oox::getRelationship(Relationship::VBAPROJECT), "vbaProject.bin");
1064 void PowerPointExport::ImplWriteSlide(sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_uInt16 /* nMode */,
1065 bool bHasBackground, Reference< XPropertySet > const& aXBackgroundPropSet)
1067 SAL_INFO("sd.eppt", "write slide: " << nPageNum << "\n----------------");
1069 // slides list
1070 if (nPageNum == 0)
1071 mPresentationFS->startElementNS(XML_p, XML_sldIdLst);
1073 // add explicit relation of presentation to this slide
1074 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1075 oox::getRelationship(Relationship::SLIDE),
1076 OUStringBuffer()
1077 .append("slides/slide")
1078 .append(static_cast<sal_Int32>(nPageNum) + 1)
1079 .append(".xml")
1080 .makeStringAndClear());
1082 mPresentationFS->singleElementNS(XML_p, XML_sldId,
1083 XML_id, OString::number(GetNewSlideId()),
1084 FSNS(XML_r, XML_id), sRelId.toUtf8());
1086 if (nPageNum == mnPages - 1)
1087 mPresentationFS->endElementNS(XML_p, XML_sldIdLst);
1089 FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
1090 .append("ppt/slides/slide")
1091 .append(static_cast<sal_Int32>(nPageNum) + 1)
1092 .append(".xml")
1093 .makeStringAndClear(),
1094 "application/vnd.openxmlformats-officedocument.presentationml.slide+xml");
1096 if (mpSlidesFSArray.size() < mnPages)
1097 mpSlidesFSArray.resize(mnPages);
1098 mpSlidesFSArray[ nPageNum ] = pFS;
1100 const char* pShow = nullptr;
1102 if (ImplGetPropertyValue(mXPagePropSet, "Visible"))
1104 bool bShow(false);
1105 if ((mAny >>= bShow) && !bShow)
1106 pShow = "0";
1109 pFS->startElementNS(XML_p, XML_sld, PNMSS, XML_show, pShow);
1111 pFS->startElementNS(XML_p, XML_cSld);
1113 // background
1114 if (bHasBackground)
1116 ImplWriteBackground(pFS, aXBackgroundPropSet);
1119 WriteShapeTree(pFS, NORMAL, false);
1121 pFS->endElementNS(XML_p, XML_cSld);
1123 WriteTransition(pFS);
1124 WriteAnimations(pFS, mXDrawPage, *this);
1126 pFS->endElementNS(XML_p, XML_sld);
1128 // add implicit relation to slide layout
1129 addRelation(pFS->getOutputStream(),
1130 oox::getRelationship(Relationship::SLIDELAYOUT),
1131 OUStringBuffer()
1132 .append("../slideLayouts/slideLayout")
1133 .append(GetLayoutFileId(GetPPTXLayoutId(GetLayoutOffset(mXPagePropSet)), nMasterNum))
1134 .append(".xml")
1135 .makeStringAndClear());
1137 if (WriteComments(nPageNum))
1138 // add implicit relation to slide comments
1139 addRelation(pFS->getOutputStream(),
1140 oox::getRelationship(Relationship::COMMENTS),
1141 OUStringBuffer()
1142 .append("../comments/comment")
1143 .append(static_cast<sal_Int32>(nPageNum) + 1)
1144 .append(".xml")
1145 .makeStringAndClear());
1147 SAL_INFO("sd.eppt", "----------------");
1150 void PowerPointExport::ImplWriteNotes(sal_uInt32 nPageNum)
1152 if (!mbCreateNotes || !ContainsOtherShapeThanPlaceholders())
1153 return;
1155 SAL_INFO("sd.eppt", "write Notes " << nPageNum << "\n----------------");
1157 FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
1158 .append("ppt/notesSlides/notesSlide")
1159 .append(static_cast<sal_Int32>(nPageNum) + 1)
1160 .append(".xml")
1161 .makeStringAndClear(),
1162 "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml");
1164 pFS->startElementNS(XML_p, XML_notes, PNMSS);
1166 pFS->startElementNS(XML_p, XML_cSld);
1168 WriteShapeTree(pFS, NOTICE, false);
1170 pFS->endElementNS(XML_p, XML_cSld);
1172 pFS->endElementNS(XML_p, XML_notes);
1174 // add implicit relation to slide
1175 addRelation(pFS->getOutputStream(),
1176 oox::getRelationship(Relationship::SLIDE),
1177 OUStringBuffer()
1178 .append("../slides/slide")
1179 .append(static_cast<sal_Int32>(nPageNum) + 1)
1180 .append(".xml")
1181 .makeStringAndClear());
1183 // add slide implicit relation to notes
1184 if (nPageNum < mpSlidesFSArray.size())
1185 addRelation(mpSlidesFSArray[ nPageNum ]->getOutputStream(),
1186 oox::getRelationship(Relationship::NOTESSLIDE),
1187 OUStringBuffer()
1188 .append("../notesSlides/notesSlide")
1189 .append(static_cast<sal_Int32>(nPageNum) + 1)
1190 .append(".xml")
1191 .makeStringAndClear());
1193 // add implicit relation to notes master
1194 addRelation(pFS->getOutputStream(),
1195 oox::getRelationship(Relationship::NOTESMASTER),
1196 "../notesMasters/notesMaster1.xml");
1198 SAL_INFO("sd.eppt", "-----------------");
1201 void PowerPointExport::AddLayoutIdAndRelation(const FSHelperPtr& pFS, sal_Int32 nLayoutFileId)
1203 // add implicit relation of slide master to slide layout
1204 OUString sRelId = addRelation(pFS->getOutputStream(),
1205 oox::getRelationship(Relationship::SLIDELAYOUT),
1206 OUStringBuffer()
1207 .append("../slideLayouts/slideLayout")
1208 .append(nLayoutFileId)
1209 .append(".xml")
1210 .makeStringAndClear());
1212 pFS->singleElementNS(XML_p, XML_sldLayoutId,
1213 XML_id, OString::number(GetNewSlideMasterId()),
1214 FSNS(XML_r, XML_id), sRelId.toUtf8());
1217 void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPropertySet > const& aXBackgroundPropSet)
1219 SAL_INFO("sd.eppt", "write master slide: " << nPageNum << "\n--------------");
1221 // slides list
1222 if (nPageNum == 0)
1223 mPresentationFS->startElementNS(XML_p, XML_sldMasterIdLst);
1225 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1226 oox::getRelationship(Relationship::SLIDEMASTER),
1227 OUStringBuffer()
1228 .append("slideMasters/slideMaster")
1229 .append(static_cast<sal_Int32>(nPageNum) + 1)
1230 .append(".xml")
1231 .makeStringAndClear());
1233 mPresentationFS->singleElementNS(XML_p, XML_sldMasterId,
1234 XML_id, OString::number(GetNewSlideMasterId()),
1235 FSNS(XML_r, XML_id), sRelId.toUtf8());
1237 if (nPageNum == mnMasterPages - 1)
1238 mPresentationFS->endElementNS(XML_p, XML_sldMasterIdLst);
1240 FSHelperPtr pFS =
1241 openFragmentStreamWithSerializer(OUStringBuffer()
1242 .append("ppt/slideMasters/slideMaster")
1243 .append(static_cast<sal_Int32>(nPageNum) + 1)
1244 .append(".xml")
1245 .makeStringAndClear(),
1246 "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml");
1248 // write theme per master
1249 WriteTheme(nPageNum);
1251 // add implicit relation to the presentation theme
1252 addRelation(pFS->getOutputStream(),
1253 oox::getRelationship(Relationship::THEME),
1254 OUStringBuffer()
1255 .append("../theme/theme")
1256 .append(static_cast<sal_Int32>(nPageNum) + 1)
1257 .append(".xml")
1258 .makeStringAndClear());
1260 pFS->startElementNS(XML_p, XML_sldMaster, PNMSS);
1262 pFS->startElementNS(XML_p, XML_cSld);
1264 ImplWriteBackground(pFS, aXBackgroundPropSet);
1265 WriteShapeTree(pFS, MASTER, true);
1267 pFS->endElementNS(XML_p, XML_cSld);
1269 // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
1270 pFS->singleElementNS(XML_p, XML_clrMap,
1271 XML_bg1, "lt1",
1272 XML_bg2, "lt2",
1273 XML_tx1, "dk1",
1274 XML_tx2, "dk2",
1275 XML_accent1, "accent1",
1276 XML_accent2, "accent2",
1277 XML_accent3, "accent3",
1278 XML_accent4, "accent4",
1279 XML_accent5, "accent5",
1280 XML_accent6, "accent6",
1281 XML_hlink, "hlink",
1282 XML_folHlink, "folHlink");
1284 // use master's id type as they have same range, mso does that as well
1285 pFS->startElementNS(XML_p, XML_sldLayoutIdLst);
1287 for (int i = 0; i < LAYOUT_SIZE; i++)
1289 sal_Int32 nLayoutFileId = GetLayoutFileId(i, nPageNum);
1290 if (nLayoutFileId > 0)
1292 AddLayoutIdAndRelation(pFS, nLayoutFileId);
1294 else
1296 ImplWritePPTXLayout(i, nPageNum);
1297 AddLayoutIdAndRelation(pFS, GetLayoutFileId(i, nPageNum));
1301 pFS->endElementNS(XML_p, XML_sldLayoutIdLst);
1303 pFS->endElementNS(XML_p, XML_sldMaster);
1305 SAL_INFO("sd.eppt", "----------------");
1308 sal_Int32 PowerPointExport::GetLayoutFileId(sal_Int32 nOffset, sal_uInt32 nMasterNum)
1310 SAL_INFO("sd.eppt", "GetLayoutFileId offset: " << nOffset << " master: " << nMasterNum);
1311 if (mLayoutInfo[ nOffset ].mnFileIdArray.size() <= nMasterNum)
1312 return 0;
1314 return mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ];
1317 void PowerPointExport::ImplWritePPTXLayout(sal_Int32 nOffset, sal_uInt32 nMasterNum)
1319 SAL_INFO("sd.eppt", "write layout: " << nOffset);
1321 Reference< drawing::XDrawPagesSupplier > xDPS(getModel(), uno::UNO_QUERY);
1322 Reference< drawing::XDrawPages > xDrawPages = xDPS->getDrawPages();
1323 Reference< drawing::XDrawPage > xSlide = xDrawPages->insertNewByIndex(xDrawPages->getCount());
1325 #ifdef DEBUG
1326 if (xSlide.is())
1327 printf("new page created\n");
1328 #endif
1330 Reference< beans::XPropertySet > xPropSet(xSlide, uno::UNO_QUERY);
1331 xPropSet->setPropertyValue("Layout", makeAny(short(aLayoutInfo[ nOffset ].nType)));
1332 #if OSL_DEBUG_LEVEL > 1
1333 dump_pset(xPropSet);
1334 #endif
1335 mXPagePropSet.set(xSlide, UNO_QUERY);
1336 mXShapes = xSlide;
1338 if (mLayoutInfo[ nOffset ].mnFileIdArray.size() < mnMasterPages)
1340 mLayoutInfo[ nOffset ].mnFileIdArray.resize(mnMasterPages);
1343 if (mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] != 0)
1344 return;
1346 FSHelperPtr pFS
1347 = openFragmentStreamWithSerializer(OUStringBuffer()
1348 .append("ppt/slideLayouts/slideLayout")
1349 .append(mnLayoutFileIdMax)
1350 .append(".xml")
1351 .makeStringAndClear(),
1352 "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml");
1354 // add implicit relation of slide layout to slide master
1355 addRelation(pFS->getOutputStream(),
1356 oox::getRelationship(Relationship::SLIDEMASTER),
1357 OUStringBuffer()
1358 .append("../slideMasters/slideMaster")
1359 .append(static_cast<sal_Int32>(nMasterNum) + 1)
1360 .append(".xml")
1361 .makeStringAndClear());
1363 pFS->startElementNS(XML_p, XML_sldLayout,
1364 PNMSS,
1365 XML_type, aLayoutInfo[ nOffset ].sType,
1366 XML_preserve, "1");
1368 pFS->startElementNS(XML_p, XML_cSld,
1369 XML_name, aLayoutInfo[ nOffset ].sName);
1370 //pFS->write( MINIMAL_SPTREE ); // TODO: write actual shape tree
1371 WriteShapeTree(pFS, LAYOUT, true);
1373 pFS->endElementNS(XML_p, XML_cSld);
1375 pFS->endElementNS(XML_p, XML_sldLayout);
1377 mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] = mnLayoutFileIdMax;
1379 mnLayoutFileIdMax ++;
1381 xDrawPages->remove(xSlide);
1384 void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType, bool bMaster)
1386 PowerPointShapeExport aDML(pFS, &maShapeMap, this);
1387 aDML.SetMaster(bMaster);
1388 aDML.SetPageType(ePageType);
1389 aDML.SetBackgroundDark(mbIsBackgroundDark);
1391 pFS->startElementNS(XML_p, XML_spTree);
1392 pFS->write(MAIN_GROUP);
1394 ResetGroupTable(mXShapes->getCount());
1396 while (GetNextGroupEntry())
1399 sal_uInt32 nGroups = GetGroupsClosed();
1400 for (sal_uInt32 i = 0; i < nGroups; i++)
1402 SAL_INFO("sd.eppt", "leave group");
1405 if (GetShapeByIndex(GetCurrentGroupIndex(), true))
1407 SAL_INFO("sd.eppt", "mType: " << mType);
1408 if (DrawingML::IsDiagram(mXShape))
1409 WriteDiagram(pFS, aDML, mXShape, mnDiagramId++);
1410 else
1411 aDML.WriteShape(mXShape);
1415 pFS->endElementNS(XML_p, XML_spTree);
1418 ShapeExport& PowerPointShapeExport::WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj)
1420 if ((ePageType == NOTICE && bPresObj) || ePageType == LAYOUT || ePageType == MASTER)
1421 return WritePlaceholderShape(xShape, SlideImage);
1423 return WriteTextShape(xShape);
1426 bool PowerPointShapeExport::WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster)
1428 SAL_INFO("sd.eppt", "WritePlaceholder " << bMaster << " " << ShapeExport::NonEmptyText(xShape));
1429 if (bMaster && ShapeExport::NonEmptyText(xShape))
1431 WritePlaceholderShape(xShape, ePlaceholder);
1433 return true;
1436 return false;
1439 ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder)
1441 mpFS->startElementNS(XML_p, XML_sp);
1443 // non visual shape properties
1444 mpFS->startElementNS(XML_p, XML_nvSpPr);
1445 const OString aPlaceholderID("PlaceHolder " + OString::number(mnShapeIdMax++));
1446 WriteNonVisualDrawingProperties(xShape, aPlaceholderID.getStr());
1447 mpFS->startElementNS(XML_p, XML_cNvSpPr);
1448 mpFS->singleElementNS(XML_a, XML_spLocks, XML_noGrp, "1");
1449 mpFS->endElementNS(XML_p, XML_cNvSpPr);
1450 mpFS->startElementNS(XML_p, XML_nvPr);
1452 const char* pType = nullptr;
1453 switch (ePlaceholder)
1455 case SlideImage:
1456 pType = "sldImg";
1457 break;
1458 case Notes:
1459 pType = "body";
1460 break;
1461 case Header:
1462 pType = "hdr";
1463 break;
1464 case Footer:
1465 pType = "ftr";
1466 break;
1467 case SlideNumber:
1468 pType = "sldNum";
1469 break;
1470 case DateAndTime:
1471 pType = "dt";
1472 break;
1473 case Outliner:
1474 pType = "body";
1475 break;
1476 case Title:
1477 pType = "title";
1478 break;
1479 case Subtitle:
1480 pType = "subTitle";
1481 break;
1482 default:
1483 SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
1485 SAL_INFO("sd.eppt", "write placeholder " << pType);
1486 mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
1487 mpFS->endElementNS(XML_p, XML_nvPr);
1488 mpFS->endElementNS(XML_p, XML_nvSpPr);
1490 // visual shape properties
1491 mpFS->startElementNS(XML_p, XML_spPr);
1492 WriteShapeTransformation(xShape, XML_a);
1493 WritePresetShape("rect");
1494 Reference< XPropertySet > xProps(xShape, UNO_QUERY);
1495 if (xProps.is())
1496 WriteBlipFill(xProps, "Graphic");
1497 mpFS->endElementNS(XML_p, XML_spPr);
1499 WriteTextBox(xShape, XML_p);
1501 mpFS->endElementNS(XML_p, XML_sp);
1503 return *this;
1506 #define SYS_COLOR_SCHEMES " <a:dk1>\
1507 <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
1508 </a:dk1>\
1509 <a:lt1>\
1510 <a:sysClr val=\"window\" lastClr=\"FFFFFF\"/>\
1511 </a:lt1>"
1513 #define MINIMAL_THEME " <a:fontScheme name=\"Office\">\
1514 <a:majorFont>\
1515 <a:latin typeface=\"Arial\"/>\
1516 <a:ea typeface=\"DejaVu Sans\"/>\
1517 <a:cs typeface=\"DejaVu Sans\"/>\
1518 </a:majorFont>\
1519 <a:minorFont>\
1520 <a:latin typeface=\"Arial\"/>\
1521 <a:ea typeface=\"DejaVu Sans\"/>\
1522 <a:cs typeface=\"DejaVu Sans\"/>\
1523 </a:minorFont>\
1524 </a:fontScheme>\
1525 <a:fmtScheme name=\"Office\">\
1526 <a:fillStyleLst>\
1527 <a:solidFill>\
1528 <a:schemeClr val=\"phClr\"/>\
1529 </a:solidFill>\
1530 <a:gradFill rotWithShape=\"1\">\
1531 <a:gsLst>\
1532 <a:gs pos=\"0\">\
1533 <a:schemeClr val=\"phClr\">\
1534 <a:tint val=\"50000\"/>\
1535 <a:satMod val=\"300000\"/>\
1536 </a:schemeClr>\
1537 </a:gs>\
1538 <a:gs pos=\"35000\">\
1539 <a:schemeClr val=\"phClr\">\
1540 <a:tint val=\"37000\"/>\
1541 <a:satMod val=\"300000\"/>\
1542 </a:schemeClr>\
1543 </a:gs>\
1544 <a:gs pos=\"100000\">\
1545 <a:schemeClr val=\"phClr\">\
1546 <a:tint val=\"15000\"/>\
1547 <a:satMod val=\"350000\"/>\
1548 </a:schemeClr>\
1549 </a:gs>\
1550 </a:gsLst>\
1551 <a:lin ang=\"16200000\" scaled=\"1\"/>\
1552 </a:gradFill>\
1553 <a:gradFill rotWithShape=\"1\">\
1554 <a:gsLst>\
1555 <a:gs pos=\"0\">\
1556 <a:schemeClr val=\"phClr\">\
1557 <a:shade val=\"51000\"/>\
1558 <a:satMod val=\"130000\"/>\
1559 </a:schemeClr>\
1560 </a:gs>\
1561 <a:gs pos=\"80000\">\
1562 <a:schemeClr val=\"phClr\">\
1563 <a:shade val=\"93000\"/>\
1564 <a:satMod val=\"130000\"/>\
1565 </a:schemeClr>\
1566 </a:gs>\
1567 <a:gs pos=\"100000\">\
1568 <a:schemeClr val=\"phClr\">\
1569 <a:shade val=\"94000\"/>\
1570 <a:satMod val=\"135000\"/>\
1571 </a:schemeClr>\
1572 </a:gs>\
1573 </a:gsLst>\
1574 <a:lin ang=\"16200000\" scaled=\"0\"/>\
1575 </a:gradFill>\
1576 </a:fillStyleLst>\
1577 <a:lnStyleLst>\
1578 <a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1579 <a:solidFill>\
1580 <a:schemeClr val=\"phClr\">\
1581 <a:shade val=\"95000\"/>\
1582 <a:satMod val=\"105000\"/>\
1583 </a:schemeClr>\
1584 </a:solidFill>\
1585 <a:prstDash val=\"solid\"/>\
1586 <a:miter/>\
1587 </a:ln>\
1588 <a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1589 <a:solidFill>\
1590 <a:schemeClr val=\"phClr\"/>\
1591 </a:solidFill>\
1592 <a:prstDash val=\"solid\"/>\
1593 <a:miter/>\
1594 </a:ln>\
1595 <a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1596 <a:solidFill>\
1597 <a:schemeClr val=\"phClr\"/>\
1598 </a:solidFill>\
1599 <a:prstDash val=\"solid\"/>\
1600 <a:miter/>\
1601 </a:ln>\
1602 </a:lnStyleLst>\
1603 <a:effectStyleLst>\
1604 <a:effectStyle>\
1605 <a:effectLst>\
1606 <a:outerShdw blurRad=\"40000\" dist=\"20000\" dir=\"5400000\" rotWithShape=\"0\">\
1607 <a:srgbClr val=\"000000\">\
1608 <a:alpha val=\"38000\"/>\
1609 </a:srgbClr>\
1610 </a:outerShdw>\
1611 </a:effectLst>\
1612 </a:effectStyle>\
1613 <a:effectStyle>\
1614 <a:effectLst>\
1615 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1616 <a:srgbClr val=\"000000\">\
1617 <a:alpha val=\"35000\"/>\
1618 </a:srgbClr>\
1619 </a:outerShdw>\
1620 </a:effectLst>\
1621 </a:effectStyle>\
1622 <a:effectStyle>\
1623 <a:effectLst>\
1624 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1625 <a:srgbClr val=\"000000\">\
1626 <a:alpha val=\"35000\"/>\
1627 </a:srgbClr>\
1628 </a:outerShdw>\
1629 </a:effectLst>\
1630 <a:scene3d>\
1631 <a:camera prst=\"orthographicFront\">\
1632 <a:rot lat=\"0\" lon=\"0\" rev=\"0\"/>\
1633 </a:camera>\
1634 <a:lightRig rig=\"threePt\" dir=\"t\">\
1635 <a:rot lat=\"0\" lon=\"0\" rev=\"1200000\"/>\
1636 </a:lightRig>\
1637 </a:scene3d>\
1638 <a:sp3d>\
1639 <a:bevelT w=\"63500\" h=\"25400\"/>\
1640 </a:sp3d>\
1641 </a:effectStyle>\
1642 </a:effectStyleLst>\
1643 <a:bgFillStyleLst>\
1644 <a:solidFill>\
1645 <a:schemeClr val=\"phClr\"/>\
1646 </a:solidFill>\
1647 <a:gradFill rotWithShape=\"1\">\
1648 <a:gsLst>\
1649 <a:gs pos=\"0\">\
1650 <a:schemeClr val=\"phClr\">\
1651 <a:tint val=\"40000\"/>\
1652 <a:satMod val=\"350000\"/>\
1653 </a:schemeClr>\
1654 </a:gs>\
1655 <a:gs pos=\"40000\">\
1656 <a:schemeClr val=\"phClr\">\
1657 <a:tint val=\"45000\"/>\
1658 <a:shade val=\"99000\"/>\
1659 <a:satMod val=\"350000\"/>\
1660 </a:schemeClr>\
1661 </a:gs>\
1662 <a:gs pos=\"100000\">\
1663 <a:schemeClr val=\"phClr\">\
1664 <a:shade val=\"20000\"/>\
1665 <a:satMod val=\"255000\"/>\
1666 </a:schemeClr>\
1667 </a:gs>\
1668 </a:gsLst>\
1669 <a:path path=\"circle\">\
1670 <a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/>\
1671 </a:path>\
1672 </a:gradFill>\
1673 <a:gradFill rotWithShape=\"1\">\
1674 <a:gsLst>\
1675 <a:gs pos=\"0\">\
1676 <a:schemeClr val=\"phClr\">\
1677 <a:tint val=\"80000\"/>\
1678 <a:satMod val=\"300000\"/>\
1679 </a:schemeClr>\
1680 </a:gs>\
1681 <a:gs pos=\"100000\">\
1682 <a:schemeClr val=\"phClr\">\
1683 <a:shade val=\"30000\"/>\
1684 <a:satMod val=\"200000\"/>\
1685 </a:schemeClr>\
1686 </a:gs>\
1687 </a:gsLst>\
1688 <a:path path=\"circle\">\
1689 <a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/>\
1690 </a:path>\
1691 </a:gradFill>\
1692 </a:bgFillStyleLst>\
1693 </a:fmtScheme>"
1695 void PowerPointExport::WriteDefaultColorSchemes(const FSHelperPtr& pFS)
1697 for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
1699 OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
1700 sal_Int32 nColor = 0;
1702 switch (nId)
1704 case PredefinedClrSchemeId::dk2:
1705 nColor = 0x1F497D;
1706 break;
1707 case PredefinedClrSchemeId::lt2:
1708 nColor = 0xEEECE1;
1709 break;
1710 case PredefinedClrSchemeId::accent1:
1711 nColor = 0x4F81BD;
1712 break;
1713 case PredefinedClrSchemeId::accent2:
1714 nColor = 0xC0504D;
1715 break;
1716 case PredefinedClrSchemeId::accent3:
1717 nColor = 0x9BBB59;
1718 break;
1719 case PredefinedClrSchemeId::accent4:
1720 nColor = 0x8064A2;
1721 break;
1722 case PredefinedClrSchemeId::accent5:
1723 nColor = 0x4BACC6;
1724 break;
1725 case PredefinedClrSchemeId::accent6:
1726 nColor = 0xF79646;
1727 break;
1728 case PredefinedClrSchemeId::hlink:
1729 nColor = 0x0000FF;
1730 break;
1731 case PredefinedClrSchemeId::folHlink:
1732 nColor = 0x800080;
1733 break;
1736 OUString sOpenColorScheme = OUStringBuffer()
1737 .append("<a:")
1738 .append(sName)
1739 .append(">")
1740 .makeStringAndClear();
1741 pFS->write(sOpenColorScheme);
1743 pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor));
1745 OUString sCloseColorScheme = OUStringBuffer()
1746 .append("</a:")
1747 .append(sName)
1748 .append(">")
1749 .makeStringAndClear();
1750 pFS->write(sCloseColorScheme);
1754 bool PowerPointExport::WriteColorSchemes(const FSHelperPtr& pFS, const OUString& rThemePath)
1758 uno::Reference<beans::XPropertySet> xDocProps(getModel(), uno::UNO_QUERY);
1759 if (xDocProps.is())
1761 uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
1763 const OUString aGrabBagPropName = "InteropGrabBag";
1764 if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
1766 comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
1767 uno::Sequence<beans::PropertyValue> aCurrentTheme;
1769 aGrabBag.getValue(rThemePath) >>= aCurrentTheme;
1771 if (!aCurrentTheme.hasElements())
1772 return false;
1774 // Order is important
1775 for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
1777 OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
1778 sal_Int32 nColor = 0;
1780 for (auto aIt = aCurrentTheme.begin(); aIt != aCurrentTheme.end(); aIt++)
1782 if (aIt->Name == sName)
1784 aIt->Value >>= nColor;
1785 break;
1789 OUString sOpenColorScheme = OUStringBuffer()
1790 .append("<a:")
1791 .append(sName)
1792 .append(">")
1793 .makeStringAndClear();
1794 pFS->write(sOpenColorScheme);
1796 pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor));
1798 OUString sCloseColorScheme = OUStringBuffer()
1799 .append("</a:")
1800 .append(sName)
1801 .append(">")
1802 .makeStringAndClear();
1803 pFS->write(sCloseColorScheme);
1806 // TODO: write complete color schemes & only if successful, protection against partial export
1807 return true;
1811 catch (const uno::Exception&)
1813 SAL_WARN("writerfilter", "Failed to save documents grab bag");
1816 return false;
1819 void PowerPointExport::WriteTheme(sal_Int32 nThemeNum)
1821 OUString sThemePath = OUStringBuffer()
1822 .append("ppt/theme/theme")
1823 .append(nThemeNum + 1)
1824 .append(".xml")
1825 .makeStringAndClear();
1827 FSHelperPtr pFS = openFragmentStreamWithSerializer(sThemePath,
1828 "application/vnd.openxmlformats-officedocument.theme+xml");
1830 pFS->startElementNS(XML_a, XML_theme,
1831 FSNS(XML_xmlns, XML_a), this->getNamespaceURL(OOX_NS(dml)).toUtf8(),
1832 XML_name, "Office Theme");
1834 pFS->startElementNS(XML_a, XML_themeElements);
1835 pFS->startElementNS(XML_a, XML_clrScheme, XML_name, "Office");
1837 pFS->write(SYS_COLOR_SCHEMES);
1839 if (!WriteColorSchemes(pFS, sThemePath))
1841 // if style is not defined, try to use first one
1842 if (!WriteColorSchemes(pFS, "ppt/theme/theme1.xml"))
1844 // color schemes are required - use default values
1845 WriteDefaultColorSchemes(pFS);
1849 pFS->endElementNS(XML_a, XML_clrScheme);
1851 // export remaining part
1852 pFS->write(MINIMAL_THEME);
1854 pFS->endElementNS(XML_a, XML_themeElements);
1855 pFS->endElementNS(XML_a, XML_theme);
1858 bool PowerPointExport::ImplCreateDocument()
1860 mbCreateNotes = false;
1862 for (sal_uInt32 i = 0; i < mnPages; i++)
1864 if (!GetPageByIndex(i, NOTICE))
1865 return false;
1867 if (ContainsOtherShapeThanPlaceholders())
1869 mbCreateNotes = true;
1870 break;
1874 return true;
1877 void PowerPointExport::WriteNotesMaster()
1879 SAL_INFO("sd.eppt", "write Notes master\n---------------");
1881 mPresentationFS->startElementNS(XML_p, XML_notesMasterIdLst);
1883 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1884 oox::getRelationship(Relationship::NOTESMASTER),
1885 "notesMasters/notesMaster1.xml");
1887 mPresentationFS->singleElementNS(XML_p, XML_notesMasterId,
1888 FSNS(XML_r, XML_id), sRelId.toUtf8());
1890 mPresentationFS->endElementNS(XML_p, XML_notesMasterIdLst);
1892 FSHelperPtr pFS =
1893 openFragmentStreamWithSerializer("ppt/notesMasters/notesMaster1.xml",
1894 "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml");
1895 // write theme per master
1896 WriteTheme(mnMasterPages);
1898 // add implicit relation to the presentation theme
1899 addRelation(pFS->getOutputStream(),
1900 oox::getRelationship(Relationship::THEME),
1901 OUStringBuffer()
1902 .append("../theme/theme")
1903 .append(static_cast<sal_Int32>(mnMasterPages) + 1)
1904 .append(".xml")
1905 .makeStringAndClear());
1907 pFS->startElementNS(XML_p, XML_notesMaster, PNMSS);
1909 pFS->startElementNS(XML_p, XML_cSld);
1911 Reference< XPropertySet > aXBackgroundPropSet;
1912 if (ImplGetPropertyValue(mXPagePropSet, "Background") &&
1913 (mAny >>= aXBackgroundPropSet))
1914 ImplWriteBackground(pFS, aXBackgroundPropSet);
1916 WriteShapeTree(pFS, NOTICE, true);
1918 pFS->endElementNS(XML_p, XML_cSld);
1920 // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
1921 pFS->singleElementNS(XML_p, XML_clrMap,
1922 XML_bg1, "lt1",
1923 XML_bg2, "lt2",
1924 XML_tx1, "dk1",
1925 XML_tx2, "dk2",
1926 XML_accent1, "accent1",
1927 XML_accent2, "accent2",
1928 XML_accent3, "accent3",
1929 XML_accent4, "accent4",
1930 XML_accent5, "accent5",
1931 XML_accent6, "accent6",
1932 XML_hlink, "hlink",
1933 XML_folHlink, "folHlink");
1935 pFS->endElementNS(XML_p, XML_notesMaster);
1937 SAL_INFO("sd.eppt", "----------------");
1940 void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& sUrl, OUString& sRelId, OUString& sName)
1942 comphelper::LifecycleProxy aProxy;
1944 if (!sUrl.endsWithIgnoreAsciiCase(".wav"))
1945 return;
1947 uno::Reference<io::XInputStream> xAudioStream;
1948 if (sUrl.startsWith("vnd.sun.star.Package:"))
1950 uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
1951 if (!xStorageBasedDocument.is())
1952 return;
1954 uno::Reference<embed::XStorage> xDocumentStorage = xStorageBasedDocument->getDocumentStorage();
1955 if (!xDocumentStorage.is())
1956 return;
1958 uno::Reference<io::XStream> xStream = comphelper::OStorageHelper::GetStreamAtPackageURL(xDocumentStorage, sUrl,
1959 css::embed::ElementModes::READ, aProxy);
1961 if (xStream.is())
1962 xAudioStream = xStream->getInputStream();
1964 else
1965 xAudioStream = comphelper::OStorageHelper::GetInputStreamFromURL(sUrl, getComponentContext());
1967 if (!xAudioStream.is())
1968 return;
1970 int nLastSlash = sUrl.lastIndexOf('/');
1971 sName = sUrl.copy(nLastSlash >= 0 ? nLastSlash + 1 : 0);
1973 OUString sPath = "../media/" + sName;
1974 sRelId = addRelation(pFS->getOutputStream(),
1975 oox::getRelationship(Relationship::AUDIO), sPath);
1977 uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream(sPath.replaceAt(0, 2, "/ppt"),
1978 "audio/x-wav");
1980 comphelper::OStorageHelper::CopyInputToOutput(xAudioStream, xOutputStream);
1983 sal_Int32 PowerPointExport::GetShapeID(const Reference<XShape>& rXShape)
1985 return ShapeExport::GetShapeID(rXShape, &maShapeMap);
1988 sal_Int32 PowerPointExport::GetNextAnimationNodeID()
1990 return mnAnimationNodeIdMax++;
1993 bool PowerPointExport::ImplCreateMainNotes()
1995 if (mbCreateNotes)
1996 WriteNotesMaster();
1998 return true;
2001 OUString PowerPointExport::getImplementationName()
2003 return "com.sun.star.comp.Impress.oox.PowerPointExport";
2006 void PowerPointExport::WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId)
2008 SAL_INFO("sd.eppt", "writing Diagram " + OUString::number(nDiagramId));
2009 pFS->startElementNS(XML_p, XML_graphicFrame);
2010 rDML.WriteDiagram(rXShape, nDiagramId);
2011 pFS->endElementNS(XML_p, XML_graphicFrame);
2014 // UNO component
2015 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
2016 css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,
2017 uno::Sequence<css::uno::Any> const& rArguments)
2019 return cppu::acquire(new PowerPointExport(rxCtxt, rArguments));
2022 #if OSL_DEBUG_LEVEL > 1
2023 void dump_pset(Reference< XPropertySet > const& rXPropSet)
2025 Reference< XPropertySetInfo > info = rXPropSet->getPropertySetInfo();
2026 Sequence< beans::Property > props = info->getProperties();
2028 for (int i=0; i < props.getLength(); i++)
2030 OString name = OUStringToOString(props [i].Name, RTL_TEXTENCODING_UTF8);
2032 Any value = rXPropSet->getPropertyValue(props [i].Name);
2034 OUString strValue;
2035 sal_Int32 intValue;
2036 bool boolValue;
2037 RectanglePoint pointValue;
2039 if (value >>= strValue)
2040 SAL_INFO("sd.eppt", name << " = \"" << strValue << "\"");
2041 else if (value >>= intValue)
2042 SAL_INFO("sd.eppt", name << " = " << intValue << "(hex : " << std::hex << intValue << ")");
2043 else if (value >>= boolValue)
2044 SAL_INFO("sd.eppt", name << " = " << boolValue << " (bool)");
2045 else if (value >>= pointValue)
2046 SAL_INFO("sd.eppt", name << " = " << pointValue << " (RectanglePoint)");
2047 else
2048 SAL_INFO("sd.eppt", "??? <unhandled type>");
2051 #endif
2053 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */