bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / filter / eppt / pptx-epptooxml.cxx
blobe6a1495ee4a51ab79127357502ffb17737825329
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.set(getModel(), UNO_QUERY);
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.set(getStatusIndicator(), UNO_QUERY);
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_GRADIENT ||
468 aFillStyle == FillStyle_HATCH)
469 return;
471 pFS->startElementNS(XML_p, XML_bg);
472 pFS->startElementNS(XML_p, XML_bgPr);
474 PowerPointShapeExport aDML(pFS, &maShapeMap, this);
475 aDML.SetBackgroundDark(mbIsBackgroundDark);
476 aDML.WriteFill(rXPropSet);
478 pFS->endElementNS(XML_p, XML_bgPr);
479 pFS->endElementNS(XML_p, XML_bg);
482 #define MAIN_GROUP \
483 "<p:nvGrpSpPr>\
484 <p:cNvPr id=\"1\" name=\"\"/>\
485 <p:cNvGrpSpPr/>\
486 <p:nvPr/>\
487 </p:nvGrpSpPr>\
488 <p:grpSpPr>\
489 <a:xfrm>\
490 <a:off x=\"0\" y=\"0\"/>\
491 <a:ext cx=\"0\" cy=\"0\"/>\
492 <a:chOff x=\"0\" y=\"0\"/>\
493 <a:chExt cx=\"0\" cy=\"0\"/>\
494 </a:xfrm>\
495 </p:grpSpPr>"
497 const char* PowerPointExport::GetSideDirection(sal_uInt8 nDirection)
499 const char* pDirection = nullptr;
501 switch (nDirection)
503 case 0:
504 pDirection = "l";
505 break;
506 case 1:
507 pDirection = "u";
508 break;
509 case 2:
510 pDirection = "r";
511 break;
512 case 3:
513 pDirection = "d";
514 break;
517 return pDirection;
520 const char* PowerPointExport::GetCornerDirection(sal_uInt8 nDirection)
522 const char* pDirection = nullptr;
524 switch (nDirection)
526 case 4:
527 pDirection = "lu";
528 break;
529 case 5:
530 pDirection = "ru";
531 break;
532 case 6:
533 pDirection = "ld";
534 break;
535 case 7:
536 pDirection = "rd";
537 break;
540 return pDirection;
543 const char* PowerPointExport::Get8Direction(sal_uInt8 nDirection)
545 const char* pDirection = GetSideDirection(nDirection);
547 if (!pDirection)
548 pDirection = GetCornerDirection(nDirection);
550 return pDirection;
553 void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
555 FadeEffect eFadeEffect = FadeEffect_NONE;
556 if (ImplGetPropertyValue(mXPagePropSet, "Effect"))
557 mAny >>= eFadeEffect;
559 sal_Int16 nTransitionType = 0, nTransitionSubtype = 0;
560 sal_Int8 nPPTTransitionType = 0;
561 sal_uInt8 nDirection = 0;
563 OUString sSoundUrl;
564 OUString sSoundRelId;
565 OUString sSoundName;
567 if (ImplGetPropertyValue(mXPagePropSet, "TransitionType") && (mAny >>= nTransitionType) &&
568 ImplGetPropertyValue(mXPagePropSet, "TransitionSubtype") && (mAny >>= nTransitionSubtype))
569 nPPTTransitionType = GetTransition(nTransitionType, nTransitionSubtype, eFadeEffect, nDirection);
571 if (!nPPTTransitionType && eFadeEffect != FadeEffect_NONE)
572 nPPTTransitionType = GetTransition(eFadeEffect, nDirection);
574 if (ImplGetPropertyValue(mXPagePropSet, "Sound") && (mAny >>= sSoundUrl))
575 embedEffectAudio(pFS, sSoundUrl, sSoundRelId, sSoundName);
577 bool bOOXmlSpecificTransition = false;
579 sal_Int32 nTransition = 0;
580 const char* pDirection = nullptr;
581 const char* pOrientation = nullptr;
582 const char* pThruBlk = nullptr;
583 const char* pSpokes = nullptr;
585 char pSpokesTmp[2] = "0";
587 // p14
588 sal_Int32 nTransition14 = 0;
589 const char* pDirection14 = nullptr;
590 const char* pInverted = nullptr;
591 const char* pPattern = nullptr; // diamond or hexagon
593 //p15
594 const char* pPresetTransition = nullptr;
596 if (!nPPTTransitionType)
598 switch (nTransitionType)
600 case animations::TransitionType::BARWIPE:
602 if (nTransitionSubtype == animations::TransitionSubType::FADEOVERCOLOR)
604 nTransition = XML_cut;
605 pThruBlk = "true";
606 bOOXmlSpecificTransition = true;
608 break;
610 case animations::TransitionType::MISCSHAPEWIPE:
612 switch (nTransitionSubtype)
614 case animations::TransitionSubType::TOPTOBOTTOM: // Turn around
615 nTransition = XML_fade;
616 nTransition14 = XML_flip;
617 pDirection14 = "l";
618 bOOXmlSpecificTransition = true;
619 break;
620 case animations::TransitionSubType::BOTTOMRIGHT: // Rochade
621 nTransition = XML_fade;
622 nTransition14 = XML_switch;
623 pDirection14 = "r";
624 bOOXmlSpecificTransition = true;
625 break;
626 case animations::TransitionSubType::VERTICAL: // Vortex
627 nTransition = XML_fade;
628 nTransition14 = XML_vortex;
629 bOOXmlSpecificTransition = true;
630 break;
631 case animations::TransitionSubType::HORIZONTAL: // Ripple
632 nTransition = XML_fade;
633 nTransition14 = XML_ripple;
634 bOOXmlSpecificTransition = true;
635 break;
636 case animations::TransitionSubType::LEFTTORIGHT: // Fall
637 nTransition = XML_fade;
638 pPresetTransition = "fallOver";
639 bOOXmlSpecificTransition = true;
640 break;
641 case animations::TransitionSubType::CORNERSIN: // Inside turning cube
642 pInverted = "true";
643 [[fallthrough]];
644 case animations::TransitionSubType::CORNERSOUT: // Outside turning cube
645 nTransition = XML_fade;
646 nTransition14 = XML_prism;
647 bOOXmlSpecificTransition = true;
648 break;
649 case animations::TransitionSubType::DIAMOND: // Glitter
650 nTransition = XML_fade;
651 nTransition14 = XML_glitter;
652 pDirection14 = "l";
653 pPattern = "hexagon";
654 bOOXmlSpecificTransition = true;
655 break;
656 case animations::TransitionSubType::HEART: // Honeycomb
657 nTransition = XML_fade;
658 nTransition14 = XML_honeycomb;
659 bOOXmlSpecificTransition = true;
660 break;
662 break;
667 AnimationSpeed animationSpeed = AnimationSpeed_MEDIUM;
668 const char* speed = nullptr;
669 sal_Int32 advanceTiming = -1;
670 sal_Int32 changeType = 0;
672 sal_Int32 nTransitionDuration = -1;
673 bool isTransitionDurationSet = false;
675 // try to use TransitionDuration instead of old Speed property
676 if (ImplGetPropertyValue(mXPagePropSet, "TransitionDuration"))
678 double fTransitionDuration = -1.0;
679 mAny >>= fTransitionDuration;
680 if (fTransitionDuration >= 0)
682 nTransitionDuration = fTransitionDuration * 1000.0;
684 // override values because in MS formats meaning of fast/medium/slow is different
685 if (nTransitionDuration <= 500)
687 // fast is default
688 speed = nullptr;
690 else if (nTransitionDuration >= 1000)
692 speed = "slow";
694 else
696 speed = "med";
699 bool isStandardValue = nTransitionDuration == 500
700 || nTransitionDuration == 750
701 || nTransitionDuration == 1000;
703 if(!isStandardValue)
704 isTransitionDurationSet = true;
707 else if (ImplGetPropertyValue(mXPagePropSet, "Speed"))
709 mAny >>= animationSpeed;
711 switch (animationSpeed)
713 default:
714 case AnimationSpeed_MEDIUM:
715 speed = "med";
716 break;
717 case AnimationSpeed_SLOW:
718 speed = "slow";
719 break;
720 case AnimationSpeed_FAST:
721 break;
725 // check if we resolved what transition to export or time is set
726 if (!nPPTTransitionType && !bOOXmlSpecificTransition && !isTransitionDurationSet)
727 return;
729 if (ImplGetPropertyValue(mXPagePropSet, "Change"))
730 mAny >>= changeType;
732 // 1 means automatic, 2 half automatic - not sure what it means - at least I don't see it in UI
733 if (changeType == 1 && ImplGetPropertyValue(mXPagePropSet, "Duration"))
734 mAny >>= advanceTiming;
736 if (!bOOXmlSpecificTransition)
738 switch (nPPTTransitionType)
740 case PPT_TRANSITION_TYPE_BLINDS:
741 nTransition = XML_blinds;
742 pDirection = (nDirection == 0) ? "vert" : "horz";
743 break;
744 case PPT_TRANSITION_TYPE_CHECKER:
745 nTransition = XML_checker;
746 pDirection = (nDirection == 1) ? "vert" : "horz";
747 break;
748 case PPT_TRANSITION_TYPE_CIRCLE:
749 nTransition = XML_circle;
750 break;
751 case PPT_TRANSITION_TYPE_COMB:
752 nTransition = XML_comb;
753 pDirection = (nDirection == 1) ? "vert" : "horz";
754 break;
755 case PPT_TRANSITION_TYPE_COVER:
756 nTransition = XML_cover;
757 pDirection = Get8Direction(nDirection);
758 break;
759 case PPT_TRANSITION_TYPE_DIAMOND:
760 nTransition = XML_diamond;
761 break;
762 case PPT_TRANSITION_TYPE_DISSOLVE:
763 nTransition = XML_dissolve;
764 break;
765 case PPT_TRANSITION_TYPE_FADE:
766 nTransition = XML_fade;
767 pThruBlk = "true";
768 break;
769 case PPT_TRANSITION_TYPE_SMOOTHFADE:
770 nTransition = XML_fade;
771 break;
772 case PPT_TRANSITION_TYPE_NEWSFLASH:
773 nTransition = XML_newsflash;
774 break;
775 case PPT_TRANSITION_TYPE_PLUS:
776 nTransition = XML_plus;
777 break;
778 case PPT_TRANSITION_TYPE_PULL:
779 nTransition = XML_pull;
780 pDirection = Get8Direction(nDirection);
781 break;
782 case PPT_TRANSITION_TYPE_PUSH:
783 nTransition = XML_push;
784 pDirection = GetSideDirection(nDirection);
785 break;
786 case PPT_TRANSITION_TYPE_RANDOM:
787 nTransition = XML_random;
788 break;
789 case PPT_TRANSITION_TYPE_RANDOM_BARS:
790 nTransition = XML_randomBar;
791 pDirection = (nDirection == 1) ? "vert" : "horz";
792 break;
793 case PPT_TRANSITION_TYPE_SPLIT:
794 nTransition = XML_split;
795 pDirection = (nDirection & 1) ? "in" : "out";
796 pOrientation = (nDirection < 2) ? "horz" : "vert";
797 break;
798 case PPT_TRANSITION_TYPE_STRIPS:
799 nTransition = XML_strips;
800 pDirection = GetCornerDirection(nDirection);
801 break;
802 case PPT_TRANSITION_TYPE_WEDGE:
803 nTransition = XML_wedge;
804 break;
805 case PPT_TRANSITION_TYPE_WHEEL:
806 nTransition = XML_wheel;
807 if (nDirection != 4 && nDirection <= 9)
809 pSpokesTmp[0] = '0' + nDirection;
810 pSpokes = pSpokesTmp;
812 break;
813 case PPT_TRANSITION_TYPE_WIPE:
814 nTransition = XML_wipe;
815 pDirection = GetSideDirection(nDirection);
816 break;
817 case PPT_TRANSITION_TYPE_ZOOM:
818 nTransition = XML_zoom;
819 pDirection = (nDirection == 1) ? "in" : "out";
820 break;
821 // coverity[dead_error_line] - following conditions exist to avoid compiler warning
822 case PPT_TRANSITION_TYPE_NONE:
823 default:
824 nTransition = 0;
825 break;
829 bool isAdvanceTimingSet = advanceTiming != -1;
830 if (nTransition14 || pPresetTransition || isTransitionDurationSet)
832 const char* pRequiresNS = (nTransition14 || isTransitionDurationSet) ? "p14" : "p15";
834 pFS->startElement(FSNS(XML_mc, XML_AlternateContent));
835 pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS);
837 if(isTransitionDurationSet && isAdvanceTimingSet)
839 pFS->startElementNS(XML_p, XML_transition,
840 XML_spd, speed,
841 XML_advTm, OString::number(advanceTiming * 1000),
842 FSNS(XML_p14, XML_dur), OString::number(nTransitionDuration));
844 else if(isTransitionDurationSet)
846 pFS->startElementNS(XML_p, XML_transition,
847 XML_spd, speed,
848 FSNS(XML_p14, XML_dur), OString::number(nTransitionDuration));
850 else if(isAdvanceTimingSet)
852 pFS->startElementNS(XML_p, XML_transition,
853 XML_spd, speed,
854 XML_advTm, OString::number(advanceTiming * 1000));
856 else
858 pFS->startElementNS(XML_p, XML_transition, XML_spd, speed);
861 if (nTransition14)
863 pFS->singleElementNS(XML_p14, nTransition14,
864 XML_isInverted, pInverted,
865 XML_dir, pDirection14,
866 XML_pattern, pPattern);
868 else if (pPresetTransition)
870 pFS->singleElementNS(XML_p15, XML_prstTrans,
871 XML_prst, pPresetTransition);
873 else if (isTransitionDurationSet && nTransition)
875 pFS->singleElementNS(XML_p, nTransition,
876 XML_dir, pDirection,
877 XML_orient, pOrientation,
878 XML_spokes, pSpokes,
879 XML_thruBlk, pThruBlk);
882 if (!sSoundRelId.isEmpty())
883 WriteSndAc(pFS, sSoundRelId, sSoundName);
885 pFS->endElement(FSNS(XML_p, XML_transition));
887 pFS->endElement(FSNS(XML_mc, XML_Choice));
888 pFS->startElement(FSNS(XML_mc, XML_Fallback));
891 pFS->startElementNS(XML_p, XML_transition,
892 XML_spd, speed,
893 XML_advTm, isAdvanceTimingSet ? OString::number(advanceTiming * 1000).getStr() : nullptr);
895 if (nTransition)
897 pFS->singleElementNS(XML_p, nTransition,
898 XML_dir, pDirection,
899 XML_orient, pOrientation,
900 XML_spokes, pSpokes,
901 XML_thruBlk, pThruBlk);
904 if (!sSoundRelId.isEmpty())
905 WriteSndAc(pFS, sSoundRelId, sSoundName);
907 pFS->endElementNS(XML_p, XML_transition);
909 if (nTransition14 || pPresetTransition || isTransitionDurationSet)
911 pFS->endElement(FSNS(XML_mc, XML_Fallback));
912 pFS->endElement(FSNS(XML_mc, XML_AlternateContent));
916 static OUString lcl_GetInitials(const OUString& sName)
918 OUStringBuffer sRet;
920 if (!sName.isEmpty())
922 sRet.append(sName[0]);
923 sal_Int32 nStart = 0, nOffset;
925 while ((nOffset = sName.indexOf(' ', nStart)) != -1)
927 if (nOffset + 1 < sName.getLength())
928 sRet.append(sName[ nOffset + 1 ]);
929 nStart = nOffset + 1;
933 return sRet.makeStringAndClear();
936 void PowerPointExport::WriteAuthors()
938 if (maAuthors.empty())
939 return;
941 FSHelperPtr pFS = openFragmentStreamWithSerializer("ppt/commentAuthors.xml",
942 "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml");
943 addRelation(mPresentationFS->getOutputStream(),
944 oox::getRelationship(Relationship::COMMENTAUTHORS),
945 "commentAuthors.xml");
947 pFS->startElementNS(XML_p, XML_cmAuthorLst,
948 FSNS(XML_xmlns, XML_p), this->getNamespaceURL(OOX_NS(ppt)).toUtf8());
950 for (const AuthorsMap::value_type& i : maAuthors)
952 pFS->singleElementNS(XML_p, XML_cmAuthor,
953 XML_id, OString::number(i.second.nId),
954 XML_name, i.first.toUtf8(),
955 XML_initials, lcl_GetInitials(i.first).toUtf8(),
956 XML_lastIdx, OString::number(i.second.nLastIndex),
957 XML_clrIdx, OString::number(i.second.nId));
960 pFS->endElementNS(XML_p, XML_cmAuthorLst);
963 sal_Int32 PowerPointExport::GetAuthorIdAndLastIndex(const OUString& sAuthor, sal_Int32& nLastIndex)
965 if (maAuthors.count(sAuthor) <= 0)
967 struct AuthorComments aAuthorComments;
969 aAuthorComments.nId = maAuthors.size();
970 aAuthorComments.nLastIndex = 0;
972 maAuthors[ sAuthor ] = aAuthorComments;
975 nLastIndex = ++maAuthors[ sAuthor ].nLastIndex;
977 return maAuthors[ sAuthor ].nId;
980 bool PowerPointExport::WriteComments(sal_uInt32 nPageNum)
982 Reference< XAnnotationAccess > xAnnotationAccess(mXDrawPage, uno::UNO_QUERY);
983 if (xAnnotationAccess.is())
985 Reference< XAnnotationEnumeration > xAnnotationEnumeration(xAnnotationAccess->createAnnotationEnumeration());
987 if (xAnnotationEnumeration->hasMoreElements())
989 FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
990 .append("ppt/comments/comment")
991 .append(static_cast<sal_Int32>(nPageNum) + 1)
992 .append(".xml")
993 .makeStringAndClear(),
994 "application/vnd.openxmlformats-officedocument.presentationml.comments+xml");
996 pFS->startElementNS(XML_p, XML_cmLst,
997 FSNS(XML_xmlns, XML_p), this->getNamespaceURL(OOX_NS(ppt)).toUtf8());
1001 Reference< XAnnotation > xAnnotation(xAnnotationEnumeration->nextElement());
1002 DateTime aDateTime(xAnnotation->getDateTime());
1003 RealPoint2D aRealPoint2D(xAnnotation->getPosition());
1004 Reference< XText > xText(xAnnotation->getTextRange());
1005 sal_Int32 nLastIndex;
1006 sal_Int32 nId = GetAuthorIdAndLastIndex(xAnnotation->getAuthor(), nLastIndex);
1007 char cDateTime[sizeof("-32768-65535-65535T65535:65535:65535.4294967295")];
1008 // reserve enough space for hypothetical max length
1010 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);
1012 pFS->startElementNS(XML_p, XML_cm,
1013 XML_authorId, OString::number(nId),
1014 XML_dt, cDateTime,
1015 XML_idx, OString::number(nLastIndex));
1017 pFS->singleElementNS(XML_p, XML_pos,
1018 XML_x, OString::number(static_cast<sal_Int64>((57600*aRealPoint2D.X + 1270)/2540.0)),
1019 XML_y, OString::number(static_cast<sal_Int64>((57600*aRealPoint2D.Y + 1270)/2540.0)));
1021 pFS->startElementNS(XML_p, XML_text);
1022 pFS->write(xText->getString());
1023 pFS->endElementNS(XML_p, XML_text);
1025 pFS->endElementNS(XML_p, XML_cm);
1028 while (xAnnotationEnumeration->hasMoreElements());
1030 pFS->endElementNS(XML_p, XML_cmLst);
1032 return true;
1036 return false;
1039 void PowerPointExport::WriteVBA()
1041 if (!mbPptm)
1042 return;
1044 uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
1045 if (!xStorageBasedDocument.is())
1046 return;
1048 uno::Reference<embed::XStorage> xDocumentStorage(xStorageBasedDocument->getDocumentStorage(), uno::UNO_QUERY);
1049 OUString aMacrosName("_MS_VBA_Macros");
1050 if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aMacrosName))
1051 return;
1053 const sal_Int32 nOpenMode = embed::ElementModes::READ;
1054 uno::Reference<io::XInputStream> xMacrosStream(xDocumentStorage->openStreamElement(aMacrosName, nOpenMode), uno::UNO_QUERY);
1055 if (!xMacrosStream.is())
1056 return;
1058 uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream("ppt/vbaProject.bin", "application/vnd.ms-office.vbaProject");
1059 comphelper::OStorageHelper::CopyInputToOutput(xMacrosStream, xOutputStream);
1061 // Write the relationship.
1062 addRelation(mPresentationFS->getOutputStream(), oox::getRelationship(Relationship::VBAPROJECT), "vbaProject.bin");
1065 void PowerPointExport::ImplWriteSlide(sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_uInt16 /* nMode */,
1066 bool bHasBackground, Reference< XPropertySet > const& aXBackgroundPropSet)
1068 SAL_INFO("sd.eppt", "write slide: " << nPageNum << "\n----------------");
1070 // slides list
1071 if (nPageNum == 0)
1072 mPresentationFS->startElementNS(XML_p, XML_sldIdLst);
1074 // add explicit relation of presentation to this slide
1075 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1076 oox::getRelationship(Relationship::SLIDE),
1077 OUStringBuffer()
1078 .append("slides/slide")
1079 .append(static_cast<sal_Int32>(nPageNum) + 1)
1080 .append(".xml")
1081 .makeStringAndClear());
1083 mPresentationFS->singleElementNS(XML_p, XML_sldId,
1084 XML_id, OString::number(GetNewSlideId()),
1085 FSNS(XML_r, XML_id), sRelId.toUtf8());
1087 if (nPageNum == mnPages - 1)
1088 mPresentationFS->endElementNS(XML_p, XML_sldIdLst);
1090 FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
1091 .append("ppt/slides/slide")
1092 .append(static_cast<sal_Int32>(nPageNum) + 1)
1093 .append(".xml")
1094 .makeStringAndClear(),
1095 "application/vnd.openxmlformats-officedocument.presentationml.slide+xml");
1097 if (mpSlidesFSArray.size() < mnPages)
1098 mpSlidesFSArray.resize(mnPages);
1099 mpSlidesFSArray[ nPageNum ] = pFS;
1101 const char* pShow = nullptr;
1103 if (ImplGetPropertyValue(mXPagePropSet, "Visible"))
1105 bool bShow(false);
1106 if ((mAny >>= bShow) && !bShow)
1107 pShow = "0";
1110 pFS->startElementNS(XML_p, XML_sld, PNMSS, XML_show, pShow);
1112 pFS->startElementNS(XML_p, XML_cSld);
1114 // background
1115 if (bHasBackground)
1117 ImplWriteBackground(pFS, aXBackgroundPropSet);
1120 WriteShapeTree(pFS, NORMAL, false);
1122 pFS->endElementNS(XML_p, XML_cSld);
1124 WriteTransition(pFS);
1125 WriteAnimations(pFS, mXDrawPage, *this);
1127 pFS->endElementNS(XML_p, XML_sld);
1129 // add implicit relation to slide layout
1130 addRelation(pFS->getOutputStream(),
1131 oox::getRelationship(Relationship::SLIDELAYOUT),
1132 OUStringBuffer()
1133 .append("../slideLayouts/slideLayout")
1134 .append(GetLayoutFileId(GetPPTXLayoutId(GetLayoutOffset(mXPagePropSet)), nMasterNum))
1135 .append(".xml")
1136 .makeStringAndClear());
1138 if (WriteComments(nPageNum))
1139 // add implicit relation to slide comments
1140 addRelation(pFS->getOutputStream(),
1141 oox::getRelationship(Relationship::COMMENTS),
1142 OUStringBuffer()
1143 .append("../comments/comment")
1144 .append(static_cast<sal_Int32>(nPageNum) + 1)
1145 .append(".xml")
1146 .makeStringAndClear());
1148 SAL_INFO("sd.eppt", "----------------");
1151 void PowerPointExport::ImplWriteNotes(sal_uInt32 nPageNum)
1153 if (!mbCreateNotes || !ContainsOtherShapeThanPlaceholders())
1154 return;
1156 SAL_INFO("sd.eppt", "write Notes " << nPageNum << "\n----------------");
1158 FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
1159 .append("ppt/notesSlides/notesSlide")
1160 .append(static_cast<sal_Int32>(nPageNum) + 1)
1161 .append(".xml")
1162 .makeStringAndClear(),
1163 "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml");
1165 pFS->startElementNS(XML_p, XML_notes, PNMSS);
1167 pFS->startElementNS(XML_p, XML_cSld);
1169 WriteShapeTree(pFS, NOTICE, false);
1171 pFS->endElementNS(XML_p, XML_cSld);
1173 pFS->endElementNS(XML_p, XML_notes);
1175 // add implicit relation to slide
1176 addRelation(pFS->getOutputStream(),
1177 oox::getRelationship(Relationship::SLIDE),
1178 OUStringBuffer()
1179 .append("../slides/slide")
1180 .append(static_cast<sal_Int32>(nPageNum) + 1)
1181 .append(".xml")
1182 .makeStringAndClear());
1184 // add slide implicit relation to notes
1185 if (nPageNum < mpSlidesFSArray.size())
1186 addRelation(mpSlidesFSArray[ nPageNum ]->getOutputStream(),
1187 oox::getRelationship(Relationship::NOTESSLIDE),
1188 OUStringBuffer()
1189 .append("../notesSlides/notesSlide")
1190 .append(static_cast<sal_Int32>(nPageNum) + 1)
1191 .append(".xml")
1192 .makeStringAndClear());
1194 // add implicit relation to notes master
1195 addRelation(pFS->getOutputStream(),
1196 oox::getRelationship(Relationship::NOTESMASTER),
1197 "../notesMasters/notesMaster1.xml");
1199 SAL_INFO("sd.eppt", "-----------------");
1202 void PowerPointExport::AddLayoutIdAndRelation(const FSHelperPtr& pFS, sal_Int32 nLayoutFileId)
1204 // add implicit relation of slide master to slide layout
1205 OUString sRelId = addRelation(pFS->getOutputStream(),
1206 oox::getRelationship(Relationship::SLIDELAYOUT),
1207 OUStringBuffer()
1208 .append("../slideLayouts/slideLayout")
1209 .append(nLayoutFileId)
1210 .append(".xml")
1211 .makeStringAndClear());
1213 pFS->singleElementNS(XML_p, XML_sldLayoutId,
1214 XML_id, OString::number(GetNewSlideMasterId()),
1215 FSNS(XML_r, XML_id), sRelId.toUtf8());
1218 void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPropertySet > const& aXBackgroundPropSet)
1220 SAL_INFO("sd.eppt", "write master slide: " << nPageNum << "\n--------------");
1222 // slides list
1223 if (nPageNum == 0)
1224 mPresentationFS->startElementNS(XML_p, XML_sldMasterIdLst);
1226 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1227 oox::getRelationship(Relationship::SLIDEMASTER),
1228 OUStringBuffer()
1229 .append("slideMasters/slideMaster")
1230 .append(static_cast<sal_Int32>(nPageNum) + 1)
1231 .append(".xml")
1232 .makeStringAndClear());
1234 mPresentationFS->singleElementNS(XML_p, XML_sldMasterId,
1235 XML_id, OString::number(GetNewSlideMasterId()),
1236 FSNS(XML_r, XML_id), sRelId.toUtf8());
1238 if (nPageNum == mnMasterPages - 1)
1239 mPresentationFS->endElementNS(XML_p, XML_sldMasterIdLst);
1241 FSHelperPtr pFS =
1242 openFragmentStreamWithSerializer(OUStringBuffer()
1243 .append("ppt/slideMasters/slideMaster")
1244 .append(static_cast<sal_Int32>(nPageNum) + 1)
1245 .append(".xml")
1246 .makeStringAndClear(),
1247 "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml");
1249 // write theme per master
1250 WriteTheme(nPageNum);
1252 // add implicit relation to the presentation theme
1253 addRelation(pFS->getOutputStream(),
1254 oox::getRelationship(Relationship::THEME),
1255 OUStringBuffer()
1256 .append("../theme/theme")
1257 .append(static_cast<sal_Int32>(nPageNum) + 1)
1258 .append(".xml")
1259 .makeStringAndClear());
1261 pFS->startElementNS(XML_p, XML_sldMaster, PNMSS);
1263 pFS->startElementNS(XML_p, XML_cSld);
1265 ImplWriteBackground(pFS, aXBackgroundPropSet);
1266 WriteShapeTree(pFS, MASTER, true);
1268 pFS->endElementNS(XML_p, XML_cSld);
1270 // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
1271 pFS->singleElementNS(XML_p, XML_clrMap,
1272 XML_bg1, "lt1",
1273 XML_bg2, "lt2",
1274 XML_tx1, "dk1",
1275 XML_tx2, "dk2",
1276 XML_accent1, "accent1",
1277 XML_accent2, "accent2",
1278 XML_accent3, "accent3",
1279 XML_accent4, "accent4",
1280 XML_accent5, "accent5",
1281 XML_accent6, "accent6",
1282 XML_hlink, "hlink",
1283 XML_folHlink, "folHlink");
1285 // use master's id type as they have same range, mso does that as well
1286 pFS->startElementNS(XML_p, XML_sldLayoutIdLst);
1288 for (int i = 0; i < LAYOUT_SIZE; i++)
1290 sal_Int32 nLayoutFileId = GetLayoutFileId(i, nPageNum);
1291 if (nLayoutFileId > 0)
1293 AddLayoutIdAndRelation(pFS, nLayoutFileId);
1295 else
1297 ImplWritePPTXLayout(i, nPageNum);
1298 AddLayoutIdAndRelation(pFS, GetLayoutFileId(i, nPageNum));
1302 pFS->endElementNS(XML_p, XML_sldLayoutIdLst);
1304 pFS->endElementNS(XML_p, XML_sldMaster);
1306 SAL_INFO("sd.eppt", "----------------");
1309 sal_Int32 PowerPointExport::GetLayoutFileId(sal_Int32 nOffset, sal_uInt32 nMasterNum)
1311 SAL_INFO("sd.eppt", "GetLayoutFileId offset: " << nOffset << " master: " << nMasterNum);
1312 if (mLayoutInfo[ nOffset ].mnFileIdArray.size() <= nMasterNum)
1313 return 0;
1315 return mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ];
1318 void PowerPointExport::ImplWritePPTXLayout(sal_Int32 nOffset, sal_uInt32 nMasterNum)
1320 SAL_INFO("sd.eppt", "write layout: " << nOffset);
1322 Reference< drawing::XDrawPagesSupplier > xDPS(getModel(), uno::UNO_QUERY);
1323 Reference< drawing::XDrawPages > xDrawPages(xDPS->getDrawPages(), uno::UNO_QUERY);
1324 Reference< drawing::XDrawPage > xSlide;
1325 Reference< container::XIndexAccess > xIndexAccess(xDrawPages, uno::UNO_QUERY);
1327 xSlide = xDrawPages->insertNewByIndex(xIndexAccess->getCount());
1329 #ifdef DEBUG
1330 if (xSlide.is())
1331 printf("new page created\n");
1332 #endif
1334 Reference< beans::XPropertySet > xPropSet(xSlide, uno::UNO_QUERY);
1335 xPropSet->setPropertyValue("Layout", makeAny(short(aLayoutInfo[ nOffset ].nType)));
1336 #if OSL_DEBUG_LEVEL > 1
1337 dump_pset(xPropSet);
1338 #endif
1339 mXPagePropSet.set(xSlide, UNO_QUERY);
1340 mXShapes.set(xSlide, UNO_QUERY);
1342 if (mLayoutInfo[ nOffset ].mnFileIdArray.size() < mnMasterPages)
1344 mLayoutInfo[ nOffset ].mnFileIdArray.resize(mnMasterPages);
1347 if (mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] != 0)
1348 return;
1350 FSHelperPtr pFS
1351 = openFragmentStreamWithSerializer(OUStringBuffer()
1352 .append("ppt/slideLayouts/slideLayout")
1353 .append(mnLayoutFileIdMax)
1354 .append(".xml")
1355 .makeStringAndClear(),
1356 "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml");
1358 // add implicit relation of slide layout to slide master
1359 addRelation(pFS->getOutputStream(),
1360 oox::getRelationship(Relationship::SLIDEMASTER),
1361 OUStringBuffer()
1362 .append("../slideMasters/slideMaster")
1363 .append(static_cast<sal_Int32>(nMasterNum) + 1)
1364 .append(".xml")
1365 .makeStringAndClear());
1367 pFS->startElementNS(XML_p, XML_sldLayout,
1368 PNMSS,
1369 XML_type, aLayoutInfo[ nOffset ].sType,
1370 XML_preserve, "1");
1372 pFS->startElementNS(XML_p, XML_cSld,
1373 XML_name, aLayoutInfo[ nOffset ].sName);
1374 //pFS->write( MINIMAL_SPTREE ); // TODO: write actual shape tree
1375 WriteShapeTree(pFS, LAYOUT, true);
1377 pFS->endElementNS(XML_p, XML_cSld);
1379 pFS->endElementNS(XML_p, XML_sldLayout);
1381 mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] = mnLayoutFileIdMax;
1383 mnLayoutFileIdMax ++;
1385 xDrawPages->remove(xSlide);
1388 void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType, bool bMaster)
1390 PowerPointShapeExport aDML(pFS, &maShapeMap, this);
1391 aDML.SetMaster(bMaster);
1392 aDML.SetPageType(ePageType);
1393 aDML.SetBackgroundDark(mbIsBackgroundDark);
1395 pFS->startElementNS(XML_p, XML_spTree);
1396 pFS->write(MAIN_GROUP);
1398 ResetGroupTable(mXShapes->getCount());
1400 while (GetNextGroupEntry())
1403 sal_uInt32 nGroups = GetGroupsClosed();
1404 for (sal_uInt32 i = 0; i < nGroups; i++)
1406 SAL_INFO("sd.eppt", "leave group");
1409 if (GetShapeByIndex(GetCurrentGroupIndex(), true))
1411 SAL_INFO("sd.eppt", "mType: " << mType);
1412 if (DrawingML::IsDiagram(mXShape))
1413 WriteDiagram(pFS, aDML, mXShape, mnDiagramId++);
1414 else
1415 aDML.WriteShape(mXShape);
1419 pFS->endElementNS(XML_p, XML_spTree);
1422 ShapeExport& PowerPointShapeExport::WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj)
1424 if ((ePageType == NOTICE && bPresObj) || ePageType == LAYOUT || ePageType == MASTER)
1425 return WritePlaceholderShape(xShape, SlideImage);
1427 return WriteTextShape(xShape);
1430 bool PowerPointShapeExport::WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster)
1432 SAL_INFO("sd.eppt", "WritePlaceholder " << bMaster << " " << ShapeExport::NonEmptyText(xShape));
1433 if (bMaster && ShapeExport::NonEmptyText(xShape))
1435 WritePlaceholderShape(xShape, ePlaceholder);
1437 return true;
1440 return false;
1443 ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder)
1445 mpFS->startElementNS(XML_p, XML_sp);
1447 // non visual shape properties
1448 mpFS->startElementNS(XML_p, XML_nvSpPr);
1449 const OString aPlaceholderID("PlaceHolder " + OString::number(mnShapeIdMax++));
1450 WriteNonVisualDrawingProperties(xShape, aPlaceholderID.getStr());
1451 mpFS->startElementNS(XML_p, XML_cNvSpPr);
1452 mpFS->singleElementNS(XML_a, XML_spLocks, XML_noGrp, "1");
1453 mpFS->endElementNS(XML_p, XML_cNvSpPr);
1454 mpFS->startElementNS(XML_p, XML_nvPr);
1456 const char* pType = nullptr;
1457 switch (ePlaceholder)
1459 case SlideImage:
1460 pType = "sldImg";
1461 break;
1462 case Notes:
1463 pType = "body";
1464 break;
1465 case Header:
1466 pType = "hdr";
1467 break;
1468 case Footer:
1469 pType = "ftr";
1470 break;
1471 case SlideNumber:
1472 pType = "sldNum";
1473 break;
1474 case DateAndTime:
1475 pType = "dt";
1476 break;
1477 case Outliner:
1478 pType = "body";
1479 break;
1480 case Title:
1481 pType = "title";
1482 break;
1483 case Subtitle:
1484 pType = "subTitle";
1485 break;
1486 default:
1487 SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
1489 SAL_INFO("sd.eppt", "write placeholder " << pType);
1490 mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
1491 mpFS->endElementNS(XML_p, XML_nvPr);
1492 mpFS->endElementNS(XML_p, XML_nvSpPr);
1494 // visual shape properties
1495 mpFS->startElementNS(XML_p, XML_spPr);
1496 WriteShapeTransformation(xShape, XML_a);
1497 WritePresetShape("rect");
1498 Reference< XPropertySet > xProps(xShape, UNO_QUERY);
1499 if (xProps.is())
1500 WriteBlipFill(xProps, "Graphic");
1501 mpFS->endElementNS(XML_p, XML_spPr);
1503 WriteTextBox(xShape, XML_p);
1505 mpFS->endElementNS(XML_p, XML_sp);
1507 return *this;
1510 #define SYS_COLOR_SCHEMES " <a:dk1>\
1511 <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
1512 </a:dk1>\
1513 <a:lt1>\
1514 <a:sysClr val=\"window\" lastClr=\"FFFFFF\"/>\
1515 </a:lt1>"
1517 #define MINIMAL_THEME " <a:fontScheme name=\"Office\">\
1518 <a:majorFont>\
1519 <a:latin typeface=\"Arial\"/>\
1520 <a:ea typeface=\"DejaVu Sans\"/>\
1521 <a:cs typeface=\"DejaVu Sans\"/>\
1522 </a:majorFont>\
1523 <a:minorFont>\
1524 <a:latin typeface=\"Arial\"/>\
1525 <a:ea typeface=\"DejaVu Sans\"/>\
1526 <a:cs typeface=\"DejaVu Sans\"/>\
1527 </a:minorFont>\
1528 </a:fontScheme>\
1529 <a:fmtScheme name=\"Office\">\
1530 <a:fillStyleLst>\
1531 <a:solidFill>\
1532 <a:schemeClr val=\"phClr\"/>\
1533 </a:solidFill>\
1534 <a:gradFill rotWithShape=\"1\">\
1535 <a:gsLst>\
1536 <a:gs pos=\"0\">\
1537 <a:schemeClr val=\"phClr\">\
1538 <a:tint val=\"50000\"/>\
1539 <a:satMod val=\"300000\"/>\
1540 </a:schemeClr>\
1541 </a:gs>\
1542 <a:gs pos=\"35000\">\
1543 <a:schemeClr val=\"phClr\">\
1544 <a:tint val=\"37000\"/>\
1545 <a:satMod val=\"300000\"/>\
1546 </a:schemeClr>\
1547 </a:gs>\
1548 <a:gs pos=\"100000\">\
1549 <a:schemeClr val=\"phClr\">\
1550 <a:tint val=\"15000\"/>\
1551 <a:satMod val=\"350000\"/>\
1552 </a:schemeClr>\
1553 </a:gs>\
1554 </a:gsLst>\
1555 <a:lin ang=\"16200000\" scaled=\"1\"/>\
1556 </a:gradFill>\
1557 <a:gradFill rotWithShape=\"1\">\
1558 <a:gsLst>\
1559 <a:gs pos=\"0\">\
1560 <a:schemeClr val=\"phClr\">\
1561 <a:shade val=\"51000\"/>\
1562 <a:satMod val=\"130000\"/>\
1563 </a:schemeClr>\
1564 </a:gs>\
1565 <a:gs pos=\"80000\">\
1566 <a:schemeClr val=\"phClr\">\
1567 <a:shade val=\"93000\"/>\
1568 <a:satMod val=\"130000\"/>\
1569 </a:schemeClr>\
1570 </a:gs>\
1571 <a:gs pos=\"100000\">\
1572 <a:schemeClr val=\"phClr\">\
1573 <a:shade val=\"94000\"/>\
1574 <a:satMod val=\"135000\"/>\
1575 </a:schemeClr>\
1576 </a:gs>\
1577 </a:gsLst>\
1578 <a:lin ang=\"16200000\" scaled=\"0\"/>\
1579 </a:gradFill>\
1580 </a:fillStyleLst>\
1581 <a:lnStyleLst>\
1582 <a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1583 <a:solidFill>\
1584 <a:schemeClr val=\"phClr\">\
1585 <a:shade val=\"95000\"/>\
1586 <a:satMod val=\"105000\"/>\
1587 </a:schemeClr>\
1588 </a:solidFill>\
1589 <a:prstDash val=\"solid\"/>\
1590 </a:ln>\
1591 <a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1592 <a:solidFill>\
1593 <a:schemeClr val=\"phClr\"/>\
1594 </a:solidFill>\
1595 <a:prstDash val=\"solid\"/>\
1596 </a:ln>\
1597 <a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1598 <a:solidFill>\
1599 <a:schemeClr val=\"phClr\"/>\
1600 </a:solidFill>\
1601 <a:prstDash val=\"solid\"/>\
1602 </a:ln>\
1603 </a:lnStyleLst>\
1604 <a:effectStyleLst>\
1605 <a:effectStyle>\
1606 <a:effectLst>\
1607 <a:outerShdw blurRad=\"40000\" dist=\"20000\" dir=\"5400000\" rotWithShape=\"0\">\
1608 <a:srgbClr val=\"000000\">\
1609 <a:alpha val=\"38000\"/>\
1610 </a:srgbClr>\
1611 </a:outerShdw>\
1612 </a:effectLst>\
1613 </a:effectStyle>\
1614 <a:effectStyle>\
1615 <a:effectLst>\
1616 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1617 <a:srgbClr val=\"000000\">\
1618 <a:alpha val=\"35000\"/>\
1619 </a:srgbClr>\
1620 </a:outerShdw>\
1621 </a:effectLst>\
1622 </a:effectStyle>\
1623 <a:effectStyle>\
1624 <a:effectLst>\
1625 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1626 <a:srgbClr val=\"000000\">\
1627 <a:alpha val=\"35000\"/>\
1628 </a:srgbClr>\
1629 </a:outerShdw>\
1630 </a:effectLst>\
1631 <a:scene3d>\
1632 <a:camera prst=\"orthographicFront\">\
1633 <a:rot lat=\"0\" lon=\"0\" rev=\"0\"/>\
1634 </a:camera>\
1635 <a:lightRig rig=\"threePt\" dir=\"t\">\
1636 <a:rot lat=\"0\" lon=\"0\" rev=\"1200000\"/>\
1637 </a:lightRig>\
1638 </a:scene3d>\
1639 <a:sp3d>\
1640 <a:bevelT w=\"63500\" h=\"25400\"/>\
1641 </a:sp3d>\
1642 </a:effectStyle>\
1643 </a:effectStyleLst>\
1644 <a:bgFillStyleLst>\
1645 <a:solidFill>\
1646 <a:schemeClr val=\"phClr\"/>\
1647 </a:solidFill>\
1648 <a:gradFill rotWithShape=\"1\">\
1649 <a:gsLst>\
1650 <a:gs pos=\"0\">\
1651 <a:schemeClr val=\"phClr\">\
1652 <a:tint val=\"40000\"/>\
1653 <a:satMod val=\"350000\"/>\
1654 </a:schemeClr>\
1655 </a:gs>\
1656 <a:gs pos=\"40000\">\
1657 <a:schemeClr val=\"phClr\">\
1658 <a:tint val=\"45000\"/>\
1659 <a:shade val=\"99000\"/>\
1660 <a:satMod val=\"350000\"/>\
1661 </a:schemeClr>\
1662 </a:gs>\
1663 <a:gs pos=\"100000\">\
1664 <a:schemeClr val=\"phClr\">\
1665 <a:shade val=\"20000\"/>\
1666 <a:satMod val=\"255000\"/>\
1667 </a:schemeClr>\
1668 </a:gs>\
1669 </a:gsLst>\
1670 <a:path path=\"circle\">\
1671 <a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/>\
1672 </a:path>\
1673 </a:gradFill>\
1674 <a:gradFill rotWithShape=\"1\">\
1675 <a:gsLst>\
1676 <a:gs pos=\"0\">\
1677 <a:schemeClr val=\"phClr\">\
1678 <a:tint val=\"80000\"/>\
1679 <a:satMod val=\"300000\"/>\
1680 </a:schemeClr>\
1681 </a:gs>\
1682 <a:gs pos=\"100000\">\
1683 <a:schemeClr val=\"phClr\">\
1684 <a:shade val=\"30000\"/>\
1685 <a:satMod val=\"200000\"/>\
1686 </a:schemeClr>\
1687 </a:gs>\
1688 </a:gsLst>\
1689 <a:path path=\"circle\">\
1690 <a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/>\
1691 </a:path>\
1692 </a:gradFill>\
1693 </a:bgFillStyleLst>\
1694 </a:fmtScheme>"
1696 void PowerPointExport::WriteDefaultColorSchemes(const FSHelperPtr& pFS)
1698 for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
1700 OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
1701 sal_Int32 nColor = 0;
1703 switch (nId)
1705 case PredefinedClrSchemeId::dk2:
1706 nColor = 0x1F497D;
1707 break;
1708 case PredefinedClrSchemeId::lt2:
1709 nColor = 0xEEECE1;
1710 break;
1711 case PredefinedClrSchemeId::accent1:
1712 nColor = 0x4F81BD;
1713 break;
1714 case PredefinedClrSchemeId::accent2:
1715 nColor = 0xC0504D;
1716 break;
1717 case PredefinedClrSchemeId::accent3:
1718 nColor = 0x9BBB59;
1719 break;
1720 case PredefinedClrSchemeId::accent4:
1721 nColor = 0x8064A2;
1722 break;
1723 case PredefinedClrSchemeId::accent5:
1724 nColor = 0x4BACC6;
1725 break;
1726 case PredefinedClrSchemeId::accent6:
1727 nColor = 0xF79646;
1728 break;
1729 case PredefinedClrSchemeId::hlink:
1730 nColor = 0x0000FF;
1731 break;
1732 case PredefinedClrSchemeId::folHlink:
1733 nColor = 0x800080;
1734 break;
1737 OUString sOpenColorScheme = OUStringBuffer()
1738 .append("<a:")
1739 .append(sName)
1740 .append(">")
1741 .makeStringAndClear();
1742 pFS->write(sOpenColorScheme);
1744 pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor));
1746 OUString sCloseColorScheme = OUStringBuffer()
1747 .append("</a:")
1748 .append(sName)
1749 .append(">")
1750 .makeStringAndClear();
1751 pFS->write(sCloseColorScheme);
1755 bool PowerPointExport::WriteColorSchemes(const FSHelperPtr& pFS, const OUString& rThemePath)
1759 uno::Reference<beans::XPropertySet> xDocProps(getModel(), uno::UNO_QUERY);
1760 if (xDocProps.is())
1762 uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
1764 const OUString aGrabBagPropName = "InteropGrabBag";
1765 if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
1767 comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
1768 uno::Sequence<beans::PropertyValue> aCurrentTheme;
1770 aGrabBag.getValue(rThemePath) >>= aCurrentTheme;
1772 if (!aCurrentTheme.hasElements())
1773 return false;
1775 // Order is important
1776 for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
1778 OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
1779 sal_Int32 nColor = 0;
1781 for (auto aIt = aCurrentTheme.begin(); aIt != aCurrentTheme.end(); aIt++)
1783 if (aIt->Name == sName)
1785 aIt->Value >>= nColor;
1786 break;
1790 OUString sOpenColorScheme = OUStringBuffer()
1791 .append("<a:")
1792 .append(sName)
1793 .append(">")
1794 .makeStringAndClear();
1795 pFS->write(sOpenColorScheme);
1797 pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor));
1799 OUString sCloseColorScheme = OUStringBuffer()
1800 .append("</a:")
1801 .append(sName)
1802 .append(">")
1803 .makeStringAndClear();
1804 pFS->write(sCloseColorScheme);
1807 // TODO: write complete color schemes & only if successful, protection against partial export
1808 return true;
1812 catch (const uno::Exception&)
1814 SAL_WARN("writerfilter", "Failed to save documents grab bag");
1817 return false;
1820 void PowerPointExport::WriteTheme(sal_Int32 nThemeNum)
1822 OUString sThemePath = OUStringBuffer()
1823 .append("ppt/theme/theme")
1824 .append(nThemeNum + 1)
1825 .append(".xml")
1826 .makeStringAndClear();
1828 FSHelperPtr pFS = openFragmentStreamWithSerializer(sThemePath,
1829 "application/vnd.openxmlformats-officedocument.theme+xml");
1831 pFS->startElementNS(XML_a, XML_theme,
1832 FSNS(XML_xmlns, XML_a), this->getNamespaceURL(OOX_NS(dml)).toUtf8(),
1833 XML_name, "Office Theme");
1835 pFS->startElementNS(XML_a, XML_themeElements);
1836 pFS->startElementNS(XML_a, XML_clrScheme, XML_name, "Office");
1838 pFS->write(SYS_COLOR_SCHEMES);
1840 if (!WriteColorSchemes(pFS, sThemePath))
1842 // if style is not defined, try to use first one
1843 if (!WriteColorSchemes(pFS, "ppt/theme/theme1.xml"))
1845 // color schemes are required - use default values
1846 WriteDefaultColorSchemes(pFS);
1850 pFS->endElementNS(XML_a, XML_clrScheme);
1852 // export remaining part
1853 pFS->write(MINIMAL_THEME);
1855 pFS->endElementNS(XML_a, XML_themeElements);
1856 pFS->endElementNS(XML_a, XML_theme);
1859 bool PowerPointExport::ImplCreateDocument()
1861 mbCreateNotes = false;
1863 for (sal_uInt32 i = 0; i < mnPages; i++)
1865 if (!GetPageByIndex(i, NOTICE))
1866 return false;
1868 if (ContainsOtherShapeThanPlaceholders())
1870 mbCreateNotes = true;
1871 break;
1875 return true;
1878 void PowerPointExport::WriteNotesMaster()
1880 SAL_INFO("sd.eppt", "write Notes master\n---------------");
1882 mPresentationFS->startElementNS(XML_p, XML_notesMasterIdLst);
1884 OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
1885 oox::getRelationship(Relationship::NOTESMASTER),
1886 "notesMasters/notesMaster1.xml");
1888 mPresentationFS->singleElementNS(XML_p, XML_notesMasterId,
1889 FSNS(XML_r, XML_id), sRelId.toUtf8());
1891 mPresentationFS->endElementNS(XML_p, XML_notesMasterIdLst);
1893 FSHelperPtr pFS =
1894 openFragmentStreamWithSerializer("ppt/notesMasters/notesMaster1.xml",
1895 "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml");
1896 // write theme per master
1897 WriteTheme(mnMasterPages);
1899 // add implicit relation to the presentation theme
1900 addRelation(pFS->getOutputStream(),
1901 oox::getRelationship(Relationship::THEME),
1902 OUStringBuffer()
1903 .append("../theme/theme")
1904 .append(static_cast<sal_Int32>(mnMasterPages) + 1)
1905 .append(".xml")
1906 .makeStringAndClear());
1908 pFS->startElementNS(XML_p, XML_notesMaster, PNMSS);
1910 pFS->startElementNS(XML_p, XML_cSld);
1912 Reference< XPropertySet > aXBackgroundPropSet;
1913 if (ImplGetPropertyValue(mXPagePropSet, "Background") &&
1914 (mAny >>= aXBackgroundPropSet))
1915 ImplWriteBackground(pFS, aXBackgroundPropSet);
1917 WriteShapeTree(pFS, NOTICE, true);
1919 pFS->endElementNS(XML_p, XML_cSld);
1921 // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
1922 pFS->singleElementNS(XML_p, XML_clrMap,
1923 XML_bg1, "lt1",
1924 XML_bg2, "lt2",
1925 XML_tx1, "dk1",
1926 XML_tx2, "dk2",
1927 XML_accent1, "accent1",
1928 XML_accent2, "accent2",
1929 XML_accent3, "accent3",
1930 XML_accent4, "accent4",
1931 XML_accent5, "accent5",
1932 XML_accent6, "accent6",
1933 XML_hlink, "hlink",
1934 XML_folHlink, "folHlink");
1936 pFS->endElementNS(XML_p, XML_notesMaster);
1938 SAL_INFO("sd.eppt", "----------------");
1941 void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& sUrl, OUString& sRelId, OUString& sName)
1943 comphelper::LifecycleProxy aProxy;
1945 if (!sUrl.endsWithIgnoreAsciiCase(".wav"))
1946 return;
1948 uno::Reference<io::XInputStream> xAudioStream;
1949 if (sUrl.startsWith("vnd.sun.star.Package:"))
1951 uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
1952 if (!xStorageBasedDocument.is())
1953 return;
1955 uno::Reference<embed::XStorage> xDocumentStorage(xStorageBasedDocument->getDocumentStorage(), uno::UNO_QUERY);
1956 if (!xDocumentStorage.is())
1957 return;
1959 uno::Reference<io::XStream> xStream = comphelper::OStorageHelper::GetStreamAtPackageURL(xDocumentStorage, sUrl,
1960 css::embed::ElementModes::READ, aProxy);
1962 if (xStream.is())
1963 xAudioStream = xStream->getInputStream();
1965 else
1966 xAudioStream = comphelper::OStorageHelper::GetInputStreamFromURL(sUrl, getComponentContext());
1968 if (!xAudioStream.is())
1969 return;
1971 int nLastSlash = sUrl.lastIndexOf('/');
1972 sName = sUrl.copy(nLastSlash >= 0 ? nLastSlash + 1 : 0);
1974 OUString sPath = OUStringBuffer().append("../media/")
1975 .append(sName)
1976 .makeStringAndClear();
1978 sRelId = addRelation(pFS->getOutputStream(),
1979 oox::getRelationship(Relationship::AUDIO), sPath);
1981 uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream(sPath.replaceAt(0, 2, "/ppt"),
1982 "audio/x-wav");
1984 comphelper::OStorageHelper::CopyInputToOutput(xAudioStream, xOutputStream);
1987 sal_Int32 PowerPointExport::GetShapeID(const Reference<XShape>& rXShape)
1989 return ShapeExport::GetShapeID(rXShape, &maShapeMap);
1992 sal_Int32 PowerPointExport::GetNextAnimationNodeID()
1994 return mnAnimationNodeIdMax++;
1997 bool PowerPointExport::ImplCreateMainNotes()
1999 if (mbCreateNotes)
2000 WriteNotesMaster();
2002 return true;
2005 OUString PowerPointExport::getImplementationName()
2007 return OUString("com.sun.star.comp.Impress.oox.PowerPointExport");
2010 void PowerPointExport::WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId)
2012 SAL_INFO("sd.eppt", "writing Diagram " + OUString::number(nDiagramId));
2013 pFS->startElementNS(XML_p, XML_graphicFrame);
2014 rDML.WriteDiagram(rXShape, nDiagramId);
2015 pFS->endElementNS(XML_p, XML_graphicFrame);
2018 // UNO component
2019 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
2020 css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,
2021 uno::Sequence<css::uno::Any> const& rArguments)
2023 return cppu::acquire(new PowerPointExport(rxCtxt, rArguments));
2026 #if OSL_DEBUG_LEVEL > 1
2027 void dump_pset(Reference< XPropertySet > const& rXPropSet)
2029 Reference< XPropertySetInfo > info = rXPropSet->getPropertySetInfo();
2030 Sequence< beans::Property > props = info->getProperties();
2032 for (int i=0; i < props.getLength(); i++)
2034 OString name = OUStringToOString(props [i].Name, RTL_TEXTENCODING_UTF8);
2036 Any value = rXPropSet->getPropertyValue(props [i].Name);
2038 OUString strValue;
2039 sal_Int32 intValue;
2040 bool boolValue;
2041 RectanglePoint pointValue;
2043 if (value >>= strValue)
2044 SAL_INFO("sd.eppt", name << " = \"" << strValue << "\"");
2045 else if (value >>= intValue)
2046 SAL_INFO("sd.eppt", name << " = " << intValue << "(hex : " << std::hex << intValue << ")");
2047 else if (value >>= boolValue)
2048 SAL_INFO("sd.eppt", name << " = " << boolValue << " (bool)");
2049 else if (value >>= pointValue)
2050 SAL_INFO("sd.eppt", name << " = " << pointValue << " (RectanglePoint)");
2051 else
2052 SAL_INFO("sd.eppt", "??? <unhandled type>");
2055 #endif
2057 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */