1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
58 #if OSL_DEBUG_LEVEL > 1
59 #include <com/sun/star/drawing/RectanglePoint.hpp>
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
);
99 class PowerPointShapeExport
: public ShapeExport
101 PowerPointExport
& mrExport
;
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
);
115 bool WritePlaceholder(const Reference
< XShape
>& xShape
, PlaceholderType ePlaceholder
, bool bMaster
);
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
));
140 LAYOUT_TITLE_CONTENT
,
141 LAYOUT_TITLE_2CONTENT
,
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
,
153 struct PPTXLayoutInfo
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
);
185 nId
= LAYOUT_TITLE_SLIDE
;
188 nId
= LAYOUT_TITLE_CONTENT
;
191 nId
= LAYOUT_TITLE_2CONTENT
;
197 nId
= LAYOUT_TITLE_2CONTENT_CONTENT
;
200 nId
= LAYOUT_TITLE_CONTENT_2CONTENT
;
203 nId
= LAYOUT_TITLE_2CONTENT_OVER_CONTENT
;
206 nId
= LAYOUT_TITLE_CONTENT_OVER_CONTENT
;
209 nId
= LAYOUT_TITLE_4CONTENT
;
212 nId
= LAYOUT_CENTERED_TEXT
;
215 nId
= LAYOUT_TITLE_6CONTENT
;
226 PowerPointShapeExport::PowerPointShapeExport(FSHelperPtr pFS
, ShapeHashMap
* pShapeMap
,
227 PowerPointExport
* pFB
)
228 : ShapeExport(XML_p
, std::move(pFS
), pShapeMap
, pFB
)
230 , mePageType(UNDEFINED
)
235 void PowerPointShapeExport::SetMaster(bool bMaster
)
240 void PowerPointShapeExport::SetPageType(PageType ePageType
)
242 mePageType
= ePageType
;
245 ShapeExport
& PowerPointShapeExport::WriteNonVisualProperties(const Reference
< XShape
>&)
247 GetFS()->singleElementNS(XML_p
, XML_nvPr
);
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
);
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
);
300 SAL_WARN("sd.eppt", "PowerPointShapeExport::WriteTextShape: shape of type '" << sShapeType
<< "' is ignored");
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
);
324 SAL_WARN("sd.eppt", "unknown shape not handled: " << sShapeType
.toUtf8());
329 PowerPointExport::PowerPointExport(const Reference
< XComponentContext
>& rContext
, const uno::Sequence
<uno::Any
>& rArguments
)
330 : XmlFilterBase(rContext
)
332 , mnLayoutFileIdMax(1)
333 , mnSlideIdMax(1 << 8)
334 , mnSlideMasterIdMax(1U << 31)
335 , mnAnimationNodeIdMax(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();
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
;
365 exportDocumentProperties(xDocProps
, bSecurityOptOpenReadOnly
);
368 exportCustomFragments();
371 bool PowerPointExport::importDocument() throw()
376 bool PowerPointExport::exportDocument()
378 DrawingML::ResetCounters();
381 mXModel
.set(getModel(), UNO_QUERY
);
383 //write document properties
384 writeDocumentProperties();
386 addRelation(oox::getRelationship(Relationship::OFFICEDOCUMENT
), "ppt/presentation.xml");
391 if (mbExportTemplate
)
393 aMediaType
= "application/vnd.ms-powerpoint.template.macroEnabled.main+xml";
397 aMediaType
= "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml";
402 if (mbExportTemplate
)
404 aMediaType
= "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml";
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
),
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
)));
442 mPresentationFS
->endElementNS(XML_p
, XML_presentation
);
443 mPresentationFS
.reset();
444 // Free all FSHelperPtr, to flush data before committing storage
445 mpSlidesFSArray
.clear();
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"))
466 if (aFillStyle
== FillStyle_NONE
||
467 aFillStyle
== FillStyle_GRADIENT
||
468 aFillStyle
== FillStyle_HATCH
)
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
);
484 <p:cNvPr id=\"1\" name=\"\"/>\
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\"/>\
497 const char* PowerPointExport::GetSideDirection(sal_uInt8 nDirection
)
499 const char* pDirection
= nullptr;
520 const char* PowerPointExport::GetCornerDirection(sal_uInt8 nDirection
)
522 const char* pDirection
= nullptr;
543 const char* PowerPointExport::Get8Direction(sal_uInt8 nDirection
)
545 const char* pDirection
= GetSideDirection(nDirection
);
548 pDirection
= GetCornerDirection(nDirection
);
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;
564 OUString sSoundRelId
;
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";
588 sal_Int32 nTransition14
= 0;
589 const char* pDirection14
= nullptr;
590 const char* pInverted
= nullptr;
591 const char* pPattern
= nullptr; // diamond or hexagon
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
;
606 bOOXmlSpecificTransition
= true;
610 case animations::TransitionType::MISCSHAPEWIPE
:
612 switch (nTransitionSubtype
)
614 case animations::TransitionSubType::TOPTOBOTTOM
: // Turn around
615 nTransition
= XML_fade
;
616 nTransition14
= XML_flip
;
618 bOOXmlSpecificTransition
= true;
620 case animations::TransitionSubType::BOTTOMRIGHT
: // Rochade
621 nTransition
= XML_fade
;
622 nTransition14
= XML_switch
;
624 bOOXmlSpecificTransition
= true;
626 case animations::TransitionSubType::VERTICAL
: // Vortex
627 nTransition
= XML_fade
;
628 nTransition14
= XML_vortex
;
629 bOOXmlSpecificTransition
= true;
631 case animations::TransitionSubType::HORIZONTAL
: // Ripple
632 nTransition
= XML_fade
;
633 nTransition14
= XML_ripple
;
634 bOOXmlSpecificTransition
= true;
636 case animations::TransitionSubType::LEFTTORIGHT
: // Fall
637 nTransition
= XML_fade
;
638 pPresetTransition
= "fallOver";
639 bOOXmlSpecificTransition
= true;
641 case animations::TransitionSubType::CORNERSIN
: // Inside turning cube
644 case animations::TransitionSubType::CORNERSOUT
: // Outside turning cube
645 nTransition
= XML_fade
;
646 nTransition14
= XML_prism
;
647 bOOXmlSpecificTransition
= true;
649 case animations::TransitionSubType::DIAMOND
: // Glitter
650 nTransition
= XML_fade
;
651 nTransition14
= XML_glitter
;
653 pPattern
= "hexagon";
654 bOOXmlSpecificTransition
= true;
656 case animations::TransitionSubType::HEART
: // Honeycomb
657 nTransition
= XML_fade
;
658 nTransition14
= XML_honeycomb
;
659 bOOXmlSpecificTransition
= true;
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)
690 else if (nTransitionDuration
>= 1000)
699 bool isStandardValue
= nTransitionDuration
== 500
700 || nTransitionDuration
== 750
701 || nTransitionDuration
== 1000;
704 isTransitionDurationSet
= true;
707 else if (ImplGetPropertyValue(mXPagePropSet
, "Speed"))
709 mAny
>>= animationSpeed
;
711 switch (animationSpeed
)
714 case AnimationSpeed_MEDIUM
:
717 case AnimationSpeed_SLOW
:
720 case AnimationSpeed_FAST
:
725 // check if we resolved what transition to export or time is set
726 if (!nPPTTransitionType
&& !bOOXmlSpecificTransition
&& !isTransitionDurationSet
)
729 if (ImplGetPropertyValue(mXPagePropSet
, "Change"))
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";
744 case PPT_TRANSITION_TYPE_CHECKER
:
745 nTransition
= XML_checker
;
746 pDirection
= (nDirection
== 1) ? "vert" : "horz";
748 case PPT_TRANSITION_TYPE_CIRCLE
:
749 nTransition
= XML_circle
;
751 case PPT_TRANSITION_TYPE_COMB
:
752 nTransition
= XML_comb
;
753 pDirection
= (nDirection
== 1) ? "vert" : "horz";
755 case PPT_TRANSITION_TYPE_COVER
:
756 nTransition
= XML_cover
;
757 pDirection
= Get8Direction(nDirection
);
759 case PPT_TRANSITION_TYPE_DIAMOND
:
760 nTransition
= XML_diamond
;
762 case PPT_TRANSITION_TYPE_DISSOLVE
:
763 nTransition
= XML_dissolve
;
765 case PPT_TRANSITION_TYPE_FADE
:
766 nTransition
= XML_fade
;
769 case PPT_TRANSITION_TYPE_SMOOTHFADE
:
770 nTransition
= XML_fade
;
772 case PPT_TRANSITION_TYPE_NEWSFLASH
:
773 nTransition
= XML_newsflash
;
775 case PPT_TRANSITION_TYPE_PLUS
:
776 nTransition
= XML_plus
;
778 case PPT_TRANSITION_TYPE_PULL
:
779 nTransition
= XML_pull
;
780 pDirection
= Get8Direction(nDirection
);
782 case PPT_TRANSITION_TYPE_PUSH
:
783 nTransition
= XML_push
;
784 pDirection
= GetSideDirection(nDirection
);
786 case PPT_TRANSITION_TYPE_RANDOM
:
787 nTransition
= XML_random
;
789 case PPT_TRANSITION_TYPE_RANDOM_BARS
:
790 nTransition
= XML_randomBar
;
791 pDirection
= (nDirection
== 1) ? "vert" : "horz";
793 case PPT_TRANSITION_TYPE_SPLIT
:
794 nTransition
= XML_split
;
795 pDirection
= (nDirection
& 1) ? "in" : "out";
796 pOrientation
= (nDirection
< 2) ? "horz" : "vert";
798 case PPT_TRANSITION_TYPE_STRIPS
:
799 nTransition
= XML_strips
;
800 pDirection
= GetCornerDirection(nDirection
);
802 case PPT_TRANSITION_TYPE_WEDGE
:
803 nTransition
= XML_wedge
;
805 case PPT_TRANSITION_TYPE_WHEEL
:
806 nTransition
= XML_wheel
;
807 if (nDirection
!= 4 && nDirection
<= 9)
809 pSpokesTmp
[0] = '0' + nDirection
;
810 pSpokes
= pSpokesTmp
;
813 case PPT_TRANSITION_TYPE_WIPE
:
814 nTransition
= XML_wipe
;
815 pDirection
= GetSideDirection(nDirection
);
817 case PPT_TRANSITION_TYPE_ZOOM
:
818 nTransition
= XML_zoom
;
819 pDirection
= (nDirection
== 1) ? "in" : "out";
821 // coverity[dead_error_line] - following conditions exist to avoid compiler warning
822 case PPT_TRANSITION_TYPE_NONE
:
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
,
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
,
848 FSNS(XML_p14
, XML_dur
), OString::number(nTransitionDuration
));
850 else if(isAdvanceTimingSet
)
852 pFS
->startElementNS(XML_p
, XML_transition
,
854 XML_advTm
, OString::number(advanceTiming
* 1000));
858 pFS
->startElementNS(XML_p
, XML_transition
, XML_spd
, speed
);
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
,
877 XML_orient
, pOrientation
,
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
,
893 XML_advTm
, isAdvanceTimingSet
? OString::number(advanceTiming
* 1000).getStr() : nullptr);
897 pFS
->singleElementNS(XML_p
, nTransition
,
899 XML_orient
, pOrientation
,
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
)
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())
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)
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
),
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
);
1039 void PowerPointExport::WriteVBA()
1044 uno::Reference
<document::XStorageBasedDocument
> xStorageBasedDocument(getModel(), uno::UNO_QUERY
);
1045 if (!xStorageBasedDocument
.is())
1048 uno::Reference
<embed::XStorage
> xDocumentStorage(xStorageBasedDocument
->getDocumentStorage(), uno::UNO_QUERY
);
1049 OUString
aMacrosName("_MS_VBA_Macros");
1050 if (!xDocumentStorage
.is() || !xDocumentStorage
->hasByName(aMacrosName
))
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())
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----------------");
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
),
1078 .append("slides/slide")
1079 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
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)
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"))
1106 if ((mAny
>>= bShow
) && !bShow
)
1110 pFS
->startElementNS(XML_p
, XML_sld
, PNMSS
, XML_show
, pShow
);
1112 pFS
->startElementNS(XML_p
, XML_cSld
);
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
),
1133 .append("../slideLayouts/slideLayout")
1134 .append(GetLayoutFileId(GetPPTXLayoutId(GetLayoutOffset(mXPagePropSet
)), nMasterNum
))
1136 .makeStringAndClear());
1138 if (WriteComments(nPageNum
))
1139 // add implicit relation to slide comments
1140 addRelation(pFS
->getOutputStream(),
1141 oox::getRelationship(Relationship::COMMENTS
),
1143 .append("../comments/comment")
1144 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1146 .makeStringAndClear());
1148 SAL_INFO("sd.eppt", "----------------");
1151 void PowerPointExport::ImplWriteNotes(sal_uInt32 nPageNum
)
1153 if (!mbCreateNotes
|| !ContainsOtherShapeThanPlaceholders())
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)
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
),
1179 .append("../slides/slide")
1180 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1182 .makeStringAndClear());
1184 // add slide implicit relation to notes
1185 if (nPageNum
< mpSlidesFSArray
.size())
1186 addRelation(mpSlidesFSArray
[ nPageNum
]->getOutputStream(),
1187 oox::getRelationship(Relationship::NOTESSLIDE
),
1189 .append("../notesSlides/notesSlide")
1190 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
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
),
1208 .append("../slideLayouts/slideLayout")
1209 .append(nLayoutFileId
)
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--------------");
1224 mPresentationFS
->startElementNS(XML_p
, XML_sldMasterIdLst
);
1226 OUString sRelId
= addRelation(mPresentationFS
->getOutputStream(),
1227 oox::getRelationship(Relationship::SLIDEMASTER
),
1229 .append("slideMasters/slideMaster")
1230 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
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
);
1242 openFragmentStreamWithSerializer(OUStringBuffer()
1243 .append("ppt/slideMasters/slideMaster")
1244 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
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
),
1256 .append("../theme/theme")
1257 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
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
,
1276 XML_accent1
, "accent1",
1277 XML_accent2
, "accent2",
1278 XML_accent3
, "accent3",
1279 XML_accent4
, "accent4",
1280 XML_accent5
, "accent5",
1281 XML_accent6
, "accent6",
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
);
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
)
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());
1331 printf("new page created\n");
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
);
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)
1351 = openFragmentStreamWithSerializer(OUStringBuffer()
1352 .append("ppt/slideLayouts/slideLayout")
1353 .append(mnLayoutFileIdMax
)
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
),
1362 .append("../slideMasters/slideMaster")
1363 .append(static_cast<sal_Int32
>(nMasterNum
) + 1)
1365 .makeStringAndClear());
1367 pFS
->startElementNS(XML_p
, XML_sldLayout
,
1369 XML_type
, aLayoutInfo
[ nOffset
].sType
,
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
++);
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
);
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
)
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
);
1500 WriteBlipFill(xProps
, "Graphic");
1501 mpFS
->endElementNS(XML_p
, XML_spPr
);
1503 WriteTextBox(xShape
, XML_p
);
1505 mpFS
->endElementNS(XML_p
, XML_sp
);
1510 #define SYS_COLOR_SCHEMES " <a:dk1>\
1511 <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
1514 <a:sysClr val=\"window\" lastClr=\"FFFFFF\"/>\
1517 #define MINIMAL_THEME " <a:fontScheme name=\"Office\">\
1519 <a:latin typeface=\"Arial\"/>\
1520 <a:ea typeface=\"DejaVu Sans\"/>\
1521 <a:cs typeface=\"DejaVu Sans\"/>\
1524 <a:latin typeface=\"Arial\"/>\
1525 <a:ea typeface=\"DejaVu Sans\"/>\
1526 <a:cs typeface=\"DejaVu Sans\"/>\
1529 <a:fmtScheme name=\"Office\">\
1532 <a:schemeClr val=\"phClr\"/>\
1534 <a:gradFill rotWithShape=\"1\">\
1537 <a:schemeClr val=\"phClr\">\
1538 <a:tint val=\"50000\"/>\
1539 <a:satMod val=\"300000\"/>\
1542 <a:gs pos=\"35000\">\
1543 <a:schemeClr val=\"phClr\">\
1544 <a:tint val=\"37000\"/>\
1545 <a:satMod val=\"300000\"/>\
1548 <a:gs pos=\"100000\">\
1549 <a:schemeClr val=\"phClr\">\
1550 <a:tint val=\"15000\"/>\
1551 <a:satMod val=\"350000\"/>\
1555 <a:lin ang=\"16200000\" scaled=\"1\"/>\
1557 <a:gradFill rotWithShape=\"1\">\
1560 <a:schemeClr val=\"phClr\">\
1561 <a:shade val=\"51000\"/>\
1562 <a:satMod val=\"130000\"/>\
1565 <a:gs pos=\"80000\">\
1566 <a:schemeClr val=\"phClr\">\
1567 <a:shade val=\"93000\"/>\
1568 <a:satMod val=\"130000\"/>\
1571 <a:gs pos=\"100000\">\
1572 <a:schemeClr val=\"phClr\">\
1573 <a:shade val=\"94000\"/>\
1574 <a:satMod val=\"135000\"/>\
1578 <a:lin ang=\"16200000\" scaled=\"0\"/>\
1582 <a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1584 <a:schemeClr val=\"phClr\">\
1585 <a:shade val=\"95000\"/>\
1586 <a:satMod val=\"105000\"/>\
1589 <a:prstDash val=\"solid\"/>\
1591 <a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1593 <a:schemeClr val=\"phClr\"/>\
1595 <a:prstDash val=\"solid\"/>\
1597 <a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1599 <a:schemeClr val=\"phClr\"/>\
1601 <a:prstDash val=\"solid\"/>\
1607 <a:outerShdw blurRad=\"40000\" dist=\"20000\" dir=\"5400000\" rotWithShape=\"0\">\
1608 <a:srgbClr val=\"000000\">\
1609 <a:alpha val=\"38000\"/>\
1616 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1617 <a:srgbClr val=\"000000\">\
1618 <a:alpha val=\"35000\"/>\
1625 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1626 <a:srgbClr val=\"000000\">\
1627 <a:alpha val=\"35000\"/>\
1632 <a:camera prst=\"orthographicFront\">\
1633 <a:rot lat=\"0\" lon=\"0\" rev=\"0\"/>\
1635 <a:lightRig rig=\"threePt\" dir=\"t\">\
1636 <a:rot lat=\"0\" lon=\"0\" rev=\"1200000\"/>\
1640 <a:bevelT w=\"63500\" h=\"25400\"/>\
1643 </a:effectStyleLst>\
1646 <a:schemeClr val=\"phClr\"/>\
1648 <a:gradFill rotWithShape=\"1\">\
1651 <a:schemeClr val=\"phClr\">\
1652 <a:tint val=\"40000\"/>\
1653 <a:satMod val=\"350000\"/>\
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\"/>\
1663 <a:gs pos=\"100000\">\
1664 <a:schemeClr val=\"phClr\">\
1665 <a:shade val=\"20000\"/>\
1666 <a:satMod val=\"255000\"/>\
1670 <a:path path=\"circle\">\
1671 <a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/>\
1674 <a:gradFill rotWithShape=\"1\">\
1677 <a:schemeClr val=\"phClr\">\
1678 <a:tint val=\"80000\"/>\
1679 <a:satMod val=\"300000\"/>\
1682 <a:gs pos=\"100000\">\
1683 <a:schemeClr val=\"phClr\">\
1684 <a:shade val=\"30000\"/>\
1685 <a:satMod val=\"200000\"/>\
1689 <a:path path=\"circle\">\
1690 <a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/>\
1693 </a:bgFillStyleLst>\
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;
1705 case PredefinedClrSchemeId::dk2
:
1708 case PredefinedClrSchemeId::lt2
:
1711 case PredefinedClrSchemeId::accent1
:
1714 case PredefinedClrSchemeId::accent2
:
1717 case PredefinedClrSchemeId::accent3
:
1720 case PredefinedClrSchemeId::accent4
:
1723 case PredefinedClrSchemeId::accent5
:
1726 case PredefinedClrSchemeId::accent6
:
1729 case PredefinedClrSchemeId::hlink
:
1732 case PredefinedClrSchemeId::folHlink
:
1737 OUString sOpenColorScheme
= OUStringBuffer()
1741 .makeStringAndClear();
1742 pFS
->write(sOpenColorScheme
);
1744 pFS
->singleElementNS(XML_a
, XML_srgbClr
, XML_val
, I32SHEX(nColor
));
1746 OUString sCloseColorScheme
= OUStringBuffer()
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
);
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())
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
;
1790 OUString sOpenColorScheme
= OUStringBuffer()
1794 .makeStringAndClear();
1795 pFS
->write(sOpenColorScheme
);
1797 pFS
->singleElementNS(XML_a
, XML_srgbClr
, XML_val
, I32SHEX(nColor
));
1799 OUString sCloseColorScheme
= OUStringBuffer()
1803 .makeStringAndClear();
1804 pFS
->write(sCloseColorScheme
);
1807 // TODO: write complete color schemes & only if successful, protection against partial export
1812 catch (const uno::Exception
&)
1814 SAL_WARN("writerfilter", "Failed to save documents grab bag");
1820 void PowerPointExport::WriteTheme(sal_Int32 nThemeNum
)
1822 OUString sThemePath
= OUStringBuffer()
1823 .append("ppt/theme/theme")
1824 .append(nThemeNum
+ 1)
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
))
1868 if (ContainsOtherShapeThanPlaceholders())
1870 mbCreateNotes
= 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
);
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
),
1903 .append("../theme/theme")
1904 .append(static_cast<sal_Int32
>(mnMasterPages
) + 1)
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
,
1927 XML_accent1
, "accent1",
1928 XML_accent2
, "accent2",
1929 XML_accent3
, "accent3",
1930 XML_accent4
, "accent4",
1931 XML_accent5
, "accent5",
1932 XML_accent6
, "accent6",
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"))
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())
1955 uno::Reference
<embed::XStorage
> xDocumentStorage(xStorageBasedDocument
->getDocumentStorage(), uno::UNO_QUERY
);
1956 if (!xDocumentStorage
.is())
1959 uno::Reference
<io::XStream
> xStream
= comphelper::OStorageHelper::GetStreamAtPackageURL(xDocumentStorage
, sUrl
,
1960 css::embed::ElementModes::READ
, aProxy
);
1963 xAudioStream
= xStream
->getInputStream();
1966 xAudioStream
= comphelper::OStorageHelper::GetInputStreamFromURL(sUrl
, getComponentContext());
1968 if (!xAudioStream
.is())
1971 int nLastSlash
= sUrl
.lastIndexOf('/');
1972 sName
= sUrl
.copy(nLastSlash
>= 0 ? nLastSlash
+ 1 : 0);
1974 OUString sPath
= OUStringBuffer().append("../media/")
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"),
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()
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
);
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
);
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)");
2052 SAL_INFO("sd.eppt", "??? <unhandled type>");
2057 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */