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 <o3tl/any.hxx>
22 #include <oox/drawingml/chart/chartconverter.hxx>
23 #include <oox/drawingml/clrscheme.hxx>
24 #include <oox/token/namespaces.hxx>
25 #include <oox/token/tokens.hxx>
26 #include <oox/token/relationship.hxx>
27 #include <oox/ole/vbaproject.hxx>
28 #include "epptooxml.hxx"
29 #include "epptdef.hxx"
30 #include <oox/export/shapes.hxx>
32 #include <comphelper/sequenceashashmap.hxx>
33 #include <comphelper/storagehelper.hxx>
34 #include <cppuhelper/implementationentry.hxx>
35 #include <cppuhelper/factory.hxx>
36 #include <sax/fshelper.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include <sal/log.hxx>
39 #include <filter/msfilter/escherex.hxx>
40 #include <tools/poly.hxx>
41 #include <com/sun/star/animations/TransitionType.hpp>
42 #include <com/sun/star/animations/TransitionSubType.hpp>
43 #include <com/sun/star/beans/Property.hpp>
44 #include <com/sun/star/beans/XPropertySetInfo.hpp>
45 #include <com/sun/star/container/XEnumerationAccess.hpp>
46 #include <com/sun/star/drawing/FillStyle.hpp>
47 #include <com/sun/star/drawing/RectanglePoint.hpp>
48 #include <com/sun/star/drawing/XDrawPages.hpp>
49 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
50 #include <com/sun/star/embed/ElementModes.hpp>
51 #include <com/sun/star/geometry/RealPoint2D.hpp>
52 #include <com/sun/star/office/XAnnotationEnumeration.hpp>
53 #include <com/sun/star/office/XAnnotationAccess.hpp>
54 #include <com/sun/star/presentation/AnimationSpeed.hpp>
55 #include <com/sun/star/util/DateTime.hpp>
56 #include <com/sun/star/task/XStatusIndicator.hpp>
57 #include <com/sun/star/frame/XModel.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
60 #include <oox/export/utils.hxx>
61 #include <oox/ppt/pptfilterhelpers.hxx>
62 #include <basegfx/polygon/b2dpolypolygontools.hxx>
64 #include "pptexanimations.hxx"
65 #include "pptx-animations.hxx"
66 #include "../ppt/pptanimations.hxx"
68 #include <com/sun/star/document/XDocumentProperties.hpp>
69 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
70 #include <com/sun/star/document/XStorageBasedDocument.hpp>
73 // presentation namespaces
74 #define PNMSS FSNS(XML_xmlns, XML_a), OUStringToOString(this->getNamespaceURL(OOX_NS(dml)), RTL_TEXTENCODING_UTF8).getStr(), \
75 FSNS(XML_xmlns, XML_p), OUStringToOString(this->getNamespaceURL(OOX_NS(ppt)), RTL_TEXTENCODING_UTF8).getStr(), \
76 FSNS(XML_xmlns, XML_r), OUStringToOString(this->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr(), \
77 FSNS(XML_xmlns, XML_p14), OUStringToOString(this->getNamespaceURL(OOX_NS(p14)), RTL_TEXTENCODING_UTF8).getStr(), \
78 FSNS(XML_xmlns, XML_p15), OUStringToOString(this->getNamespaceURL(OOX_NS(p15)), RTL_TEXTENCODING_UTF8).getStr(), \
79 FSNS(XML_xmlns, XML_mc), OUStringToOString(this->getNamespaceURL(OOX_NS(mce)), RTL_TEXTENCODING_UTF8).getStr()
82 using namespace ::com::sun::star
;
83 using namespace ::com::sun::star::animations
;
84 using namespace ::com::sun::star::beans
;
85 using namespace ::com::sun::star::container
;
86 using namespace ::com::sun::star::drawing
;
87 using namespace ::com::sun::star::geometry
;
88 using namespace ::com::sun::star::presentation
;
89 using namespace ::com::sun::star::office
;
90 using namespace ::com::sun::star::text
;
91 using namespace ::com::sun::star::uno
;
92 using namespace ::com::sun::star::util
;
93 using namespace ::ppt
;
94 using ::com::sun::star::beans::XPropertySet
;
95 using ::com::sun::star::beans::XPropertySetInfo
;
96 using ::com::sun::star::container::XIndexAccess
;
97 using ::sax_fastparser::FSHelperPtr
;
98 using namespace oox::drawingml
;
99 using namespace oox::core
;
101 #if OSL_DEBUG_LEVEL > 1
102 void dump_pset(Reference
< XPropertySet
> const& rXPropSet
);
110 class PowerPointShapeExport
: public ShapeExport
112 PowerPointExport
& mrExport
;
116 PowerPointShapeExport(FSHelperPtr pFS
, ShapeHashMap
* pShapeMap
, PowerPointExport
* pFB
);
117 void SetMaster(bool bMaster
);
118 void SetPageType(PageType ePageType
);
119 ShapeExport
& WriteNonVisualProperties(const Reference
< XShape
>& xShape
) override
;
120 ShapeExport
& WriteTextShape(const Reference
< XShape
>& xShape
) override
;
121 ShapeExport
& WriteUnknownShape(const Reference
< XShape
>& xShape
) override
;
122 ShapeExport
& WritePlaceholderShape(const Reference
< XShape
>& xShape
, PlaceholderType ePlaceholder
);
123 ShapeExport
& WritePageShape(const Reference
< XShape
>& xShape
, PageType ePageType
, bool bPresObj
);
126 bool WritePlaceholder(const Reference
< XShape
>& xShape
, PlaceholderType ePlaceholder
, bool bMaster
);
136 LAYOUT_TITLE_CONTENT
,
137 LAYOUT_TITLE_2CONTENT
,
139 LAYOUT_CENTERED_TEXT
,
140 LAYOUT_TITLE_2CONTENT_CONTENT
,
141 LAYOUT_TITLE_CONTENT_2CONTENT
,
142 LAYOUT_TITLE_2CONTENT_OVER_CONTENT
,
143 LAYOUT_TITLE_CONTENT_OVER_CONTENT
,
144 LAYOUT_TITLE_4CONTENT
,
145 LAYOUT_TITLE_6CONTENT
,
149 struct PPTXLayoutInfo
156 static const PPTXLayoutInfo aLayoutInfo
[LAYOUT_SIZE
] =
158 { 20, "Blank Slide", "blank" },
159 { 0, "Title Slide", "tx" },
160 { 1, "Title, Content", "obj" },
161 { 3, "Title, 2 Content", "twoObj" },
162 { 19, "Title Only", "titleOnly" },
163 { 32, "Centered Text", "objOnly" }, // not exactly, but close
164 { 15, "Title, 2 Content and Content", "twoObjAndObj" },
165 { 12, "Title Content and 2 Content", "objAndTwoObj" },
166 { 16, "Title, 2 Content over Content", "twoObjOverTx" }, // not exactly, but close
167 { 14, "Title, Content over Content", "objOverTx" }, // not exactly, but close
168 { 18, "Title, 4 Content", "fourObj" },
169 { 34, "Title, 6 Content", "blank" } // not defined => blank
172 int PowerPointExport::GetPPTXLayoutId(int nOffset
)
174 int nId
= LAYOUT_BLANK
;
176 SAL_INFO("sd.eppt", "GetPPTXLayoutId " << nOffset
);
181 nId
= LAYOUT_TITLE_SLIDE
;
184 nId
= LAYOUT_TITLE_CONTENT
;
187 nId
= LAYOUT_TITLE_2CONTENT
;
193 nId
= LAYOUT_TITLE_2CONTENT_CONTENT
;
196 nId
= LAYOUT_TITLE_CONTENT_2CONTENT
;
199 nId
= LAYOUT_TITLE_2CONTENT_OVER_CONTENT
;
202 nId
= LAYOUT_TITLE_CONTENT_OVER_CONTENT
;
205 nId
= LAYOUT_TITLE_4CONTENT
;
208 nId
= LAYOUT_CENTERED_TEXT
;
211 nId
= LAYOUT_TITLE_6CONTENT
;
222 PowerPointShapeExport::PowerPointShapeExport(FSHelperPtr pFS
, ShapeHashMap
* pShapeMap
,
223 PowerPointExport
* pFB
)
224 : ShapeExport(XML_p
, std::move(pFS
), pShapeMap
, pFB
)
226 , mePageType(UNDEFINED
)
231 void PowerPointShapeExport::SetMaster(bool bMaster
)
236 void PowerPointShapeExport::SetPageType(PageType ePageType
)
238 mePageType
= ePageType
;
241 ShapeExport
& PowerPointShapeExport::WriteNonVisualProperties(const Reference
< XShape
>&)
243 GetFS()->singleElementNS(XML_p
, XML_nvPr
, FSEND
);
248 ShapeExport
& PowerPointShapeExport::WriteTextShape(const Reference
< XShape
>& xShape
)
250 OUString sShapeType
= xShape
->getShapeType();
252 SAL_INFO("sd.eppt", "shape(text) : " << USS(sShapeType
));
254 if (sShapeType
== "com.sun.star.drawing.TextShape" || sShapeType
== "com.sun.star.drawing.GraphicObjectShape")
256 ShapeExport::WriteTextShape(xShape
);
258 else if (sShapeType
== "com.sun.star.presentation.DateTimeShape")
260 if (!WritePlaceholder(xShape
, DateAndTime
, mbMaster
))
261 ShapeExport::WriteTextShape(xShape
);
263 else if (sShapeType
== "com.sun.star.presentation.FooterShape")
265 if (!WritePlaceholder(xShape
, Footer
, mbMaster
))
266 ShapeExport::WriteTextShape(xShape
);
268 else if (sShapeType
== "com.sun.star.presentation.HeaderShape")
270 if (!WritePlaceholder(xShape
, Header
, mbMaster
))
271 ShapeExport::WriteTextShape(xShape
);
273 else if (sShapeType
== "com.sun.star.presentation.NotesShape")
275 if (mePageType
== NOTICE
&& mrExport
.GetPresObj())
276 WritePlaceholderShape(xShape
, Notes
);
278 ShapeExport::WriteTextShape(xShape
);
280 else if (sShapeType
== "com.sun.star.presentation.OutlinerShape")
282 if (!WritePlaceholder(xShape
, Outliner
, mbMaster
))
283 ShapeExport::WriteTextShape(xShape
);
285 else if (sShapeType
== "com.sun.star.presentation.SlideNumberShape")
287 if (!WritePlaceholder(xShape
, SlideNumber
, mbMaster
))
288 ShapeExport::WriteTextShape(xShape
);
290 else if (sShapeType
== "com.sun.star.presentation.TitleTextShape")
292 if (!WritePlaceholder(xShape
, Title
, mbMaster
))
293 ShapeExport::WriteTextShape(xShape
);
296 SAL_WARN("sd.eppt", "PowerPointShapeExport::WriteTextShape: shape of type '" << sShapeType
<< "' is ignored");
301 ShapeExport
& PowerPointShapeExport::WriteUnknownShape(const Reference
< XShape
>& xShape
)
303 OUString sShapeType
= xShape
->getShapeType();
305 SAL_INFO("sd.eppt", "shape(unknown): " << USS(sShapeType
));
307 if (sShapeType
== "com.sun.star.presentation.PageShape")
309 WritePageShape(xShape
, mePageType
, mrExport
.GetPresObj());
311 else if (sShapeType
== "com.sun.star.presentation.SubtitleShape")
313 if(mePageType
!= MASTER
)
315 if (!WritePlaceholder(xShape
, Subtitle
, mbMaster
))
316 ShapeExport::WriteTextShape(xShape
);
320 SAL_WARN("sd.eppt", "unknown shape not handled: " << USS(sShapeType
));
325 PowerPointExport::PowerPointExport(const Reference
< XComponentContext
>& rContext
, const uno::Sequence
<uno::Any
>& rArguments
)
326 : XmlFilterBase(rContext
)
328 , mnLayoutFileIdMax(1)
329 , mnSlideIdMax(1 << 8)
330 , mnSlideMasterIdMax(1U << 31)
331 , mnAnimationNodeIdMax(1)
332 , mbCreateNotes(false)
334 comphelper::SequenceAsHashMap
aArgumentsMap(rArguments
);
335 mbPptm
= aArgumentsMap
.getUnpackedValueOrDefault("IsPPTM", false);
336 mbExportTemplate
= aArgumentsMap
.getUnpackedValueOrDefault("IsTemplate", false);
339 PowerPointExport::~PowerPointExport()
343 void PowerPointExport::writeDocumentProperties()
345 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(mXModel
, uno::UNO_QUERY
);
346 uno::Reference
<document::XDocumentProperties
> xDocProps
= xDPS
->getDocumentProperties();
350 bool bSecurityOptOpenReadOnly
= false;
351 uno::Reference
< lang::XMultiServiceFactory
> xFactory(mXModel
, uno::UNO_QUERY
);
352 uno::Reference
< beans::XPropertySet
> xSettings(xFactory
->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY
);
355 xSettings
->getPropertyValue("LoadReadonly") >>= bSecurityOptOpenReadOnly
;
360 exportDocumentProperties(xDocProps
, bSecurityOptOpenReadOnly
);
363 exportCustomFragments();
366 bool PowerPointExport::importDocument() throw()
371 bool PowerPointExport::exportDocument()
373 DrawingML::ResetCounters();
376 mXModel
.set(getModel(), UNO_QUERY
);
378 //write document properties
379 writeDocumentProperties();
381 addRelation(oox::getRelationship(Relationship::OFFICEDOCUMENT
), "ppt/presentation.xml");
386 if (mbExportTemplate
)
388 aMediaType
= "application/vnd.ms-powerpoint.template.macroEnabled.main+xml";
392 aMediaType
= "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml";
397 if (mbExportTemplate
)
399 aMediaType
= "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml";
403 aMediaType
= "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
407 mPresentationFS
= openFragmentStreamWithSerializer("ppt/presentation.xml", aMediaType
);
409 addRelation(mPresentationFS
->getOutputStream(),
410 oox::getRelationship(Relationship::THEME
),
413 mPresentationFS
->startElementNS(XML_p
, XML_presentation
, PNMSS
, FSEND
);
415 mXStatusIndicator
.set(getStatusIndicator(), UNO_QUERY
);
417 std::vector
< PropertyValue
> aProperties
;
418 PropertyValue aProperty
;
419 aProperty
.Name
= "BaseURI";
420 aProperty
.Value
<<= getFileUrl();
421 aProperties
.push_back(aProperty
);
423 exportPPT(aProperties
);
425 mPresentationFS
->singleElementNS(XML_p
, XML_sldSz
,
426 XML_cx
, IS(PPTtoEMU(maDestPageSize
.Width
)),
427 XML_cy
, IS(PPTtoEMU(maDestPageSize
.Height
)),
429 // for some reason if added before slides list it will not load the slides (alas with error reports) in mso
430 mPresentationFS
->singleElementNS(XML_p
, XML_notesSz
,
431 XML_cx
, IS(PPTtoEMU(maNotesPageSize
.Width
)),
432 XML_cy
, IS(PPTtoEMU(maNotesPageSize
.Height
)),
439 mPresentationFS
->endElementNS(XML_p
, XML_presentation
);
440 mPresentationFS
.reset();
441 // Free all FSHelperPtr, to flush data before committing storage
442 mpSlidesFSArray
.clear();
452 ::oox::ole::VbaProject
* PowerPointExport::implCreateVbaProject() const
454 return new ::oox::ole::VbaProject(getComponentContext(), getModel(), "Impress");
457 void PowerPointExport::ImplWriteBackground(const FSHelperPtr
& pFS
, const Reference
< XPropertySet
>& rXPropSet
)
459 FillStyle
aFillStyle(FillStyle_NONE
);
460 if (ImplGetPropertyValue(rXPropSet
, "FillStyle"))
463 if (aFillStyle
== FillStyle_NONE
||
464 aFillStyle
== FillStyle_GRADIENT
||
465 aFillStyle
== FillStyle_HATCH
)
468 pFS
->startElementNS(XML_p
, XML_bg
, FSEND
);
469 pFS
->startElementNS(XML_p
, XML_bgPr
, FSEND
);
471 PowerPointShapeExport
aDML(pFS
, &maShapeMap
, this);
472 aDML
.SetBackgroundDark(mbIsBackgroundDark
);
473 aDML
.WriteFill(rXPropSet
);
475 pFS
->endElementNS(XML_p
, XML_bgPr
);
476 pFS
->endElementNS(XML_p
, XML_bg
);
481 <p:cNvPr id=\"1\" name=\"\"/>\
487 <a:off x=\"0\" y=\"0\"/>\
488 <a:ext cx=\"0\" cy=\"0\"/>\
489 <a:chOff x=\"0\" y=\"0\"/>\
490 <a:chExt cx=\"0\" cy=\"0\"/>\
494 const char* PowerPointExport::GetSideDirection(sal_uInt8 nDirection
)
496 const char* pDirection
= nullptr;
517 const char* PowerPointExport::GetCornerDirection(sal_uInt8 nDirection
)
519 const char* pDirection
= nullptr;
540 const char* PowerPointExport::Get8Direction(sal_uInt8 nDirection
)
542 const char* pDirection
= GetSideDirection(nDirection
);
545 pDirection
= GetCornerDirection(nDirection
);
550 void PowerPointExport::WriteTransition(const FSHelperPtr
& pFS
)
552 FadeEffect eFadeEffect
= FadeEffect_NONE
;
553 if (ImplGetPropertyValue(mXPagePropSet
, "Effect"))
554 mAny
>>= eFadeEffect
;
556 sal_Int16 nTransitionType
= 0, nTransitionSubtype
= 0;
557 sal_Int8 nPPTTransitionType
= 0;
558 sal_uInt8 nDirection
= 0;
560 if (ImplGetPropertyValue(mXPagePropSet
, "TransitionType") && (mAny
>>= nTransitionType
) &&
561 ImplGetPropertyValue(mXPagePropSet
, "TransitionSubtype") && (mAny
>>= nTransitionSubtype
))
562 nPPTTransitionType
= GetTransition(nTransitionType
, nTransitionSubtype
, eFadeEffect
, nDirection
);
564 if (!nPPTTransitionType
&& eFadeEffect
!= FadeEffect_NONE
)
565 nPPTTransitionType
= GetTransition(eFadeEffect
, nDirection
);
567 bool bOOXmlSpecificTransition
= false;
569 sal_Int32 nTransition
= 0;
570 const char* pDirection
= nullptr;
571 const char* pOrientation
= nullptr;
572 const char* pThruBlk
= nullptr;
573 const char* pSpokes
= nullptr;
575 char pSpokesTmp
[2] = "0";
578 sal_Int32 nTransition14
= 0;
579 const char* pDirection14
= nullptr;
580 const char* pInverted
= nullptr;
581 const char* pPattern
= nullptr; // diamond or hexagon
584 const char* pPresetTransition
= nullptr;
586 if (!nPPTTransitionType
)
588 switch (nTransitionType
)
590 case animations::TransitionType::BARWIPE
:
592 if (nTransitionSubtype
== animations::TransitionSubType::FADEOVERCOLOR
)
594 nTransition
= XML_cut
;
596 bOOXmlSpecificTransition
= true;
600 case animations::TransitionType::MISCSHAPEWIPE
:
602 switch (nTransitionSubtype
)
604 case animations::TransitionSubType::TOPTOBOTTOM
: // Turn around
605 nTransition
= XML_fade
;
606 nTransition14
= XML_flip
;
608 bOOXmlSpecificTransition
= true;
610 case animations::TransitionSubType::BOTTOMRIGHT
: // Rochade
611 nTransition
= XML_fade
;
612 nTransition14
= XML_switch
;
614 bOOXmlSpecificTransition
= true;
616 case animations::TransitionSubType::VERTICAL
: // Vortex
617 nTransition
= XML_fade
;
618 nTransition14
= XML_vortex
;
619 bOOXmlSpecificTransition
= true;
621 case animations::TransitionSubType::HORIZONTAL
: // Ripple
622 nTransition
= XML_fade
;
623 nTransition14
= XML_ripple
;
624 bOOXmlSpecificTransition
= true;
626 case animations::TransitionSubType::LEFTTORIGHT
: // Fall
627 nTransition
= XML_fade
;
628 pPresetTransition
= "fallOver";
629 bOOXmlSpecificTransition
= true;
631 case animations::TransitionSubType::CORNERSIN
: // Inside turning cube
634 case animations::TransitionSubType::CORNERSOUT
: // Outside turning cube
635 nTransition
= XML_fade
;
636 nTransition14
= XML_prism
;
637 bOOXmlSpecificTransition
= true;
639 case animations::TransitionSubType::DIAMOND
: // Glitter
640 nTransition
= XML_fade
;
641 nTransition14
= XML_glitter
;
643 pPattern
= "hexagon";
644 bOOXmlSpecificTransition
= true;
646 case animations::TransitionSubType::HEART
: // Honeycomb
647 nTransition
= XML_fade
;
648 nTransition14
= XML_honeycomb
;
649 bOOXmlSpecificTransition
= true;
657 AnimationSpeed animationSpeed
= AnimationSpeed_MEDIUM
;
658 const char* speed
= nullptr;
659 sal_Int32 advanceTiming
= -1;
660 sal_Int32 changeType
= 0;
662 sal_Int32 nTransitionDuration
= -1;
663 bool isTransitionDurationSet
= false;
665 // try to use TransitionDuration instead of old Speed property
666 if (ImplGetPropertyValue(mXPagePropSet
, "TransitionDuration"))
668 double fTransitionDuration
= -1.0;
669 mAny
>>= fTransitionDuration
;
670 if (fTransitionDuration
>= 0)
672 nTransitionDuration
= fTransitionDuration
* 1000.0;
674 // override values because in MS formats meaning of fast/medium/slow is different
675 if (nTransitionDuration
<= 500)
680 else if (nTransitionDuration
>= 1000)
689 bool isStandardValue
= nTransitionDuration
== 500
690 || nTransitionDuration
== 750
691 || nTransitionDuration
== 1000;
694 isTransitionDurationSet
= true;
697 else if (ImplGetPropertyValue(mXPagePropSet
, "Speed"))
699 mAny
>>= animationSpeed
;
701 switch (animationSpeed
)
704 case AnimationSpeed_MEDIUM
:
707 case AnimationSpeed_SLOW
:
710 case AnimationSpeed_FAST
:
715 // check if we resolved what transition to export or time is set
716 if (!nPPTTransitionType
&& !bOOXmlSpecificTransition
&& !isTransitionDurationSet
)
719 if (ImplGetPropertyValue(mXPagePropSet
, "Change"))
722 // 1 means automatic, 2 half automatic - not sure what it means - at least I don't see it in UI
723 if (changeType
== 1 && ImplGetPropertyValue(mXPagePropSet
, "Duration"))
724 mAny
>>= advanceTiming
;
726 if (!bOOXmlSpecificTransition
)
728 switch (nPPTTransitionType
)
730 case PPT_TRANSITION_TYPE_BLINDS
:
731 nTransition
= XML_blinds
;
732 pDirection
= (nDirection
== 0) ? "vert" : "horz";
734 case PPT_TRANSITION_TYPE_CHECKER
:
735 nTransition
= XML_checker
;
736 pDirection
= (nDirection
== 1) ? "vert" : "horz";
738 case PPT_TRANSITION_TYPE_CIRCLE
:
739 nTransition
= XML_circle
;
741 case PPT_TRANSITION_TYPE_COMB
:
742 nTransition
= XML_comb
;
743 pDirection
= (nDirection
== 1) ? "vert" : "horz";
745 case PPT_TRANSITION_TYPE_COVER
:
746 nTransition
= XML_cover
;
747 pDirection
= Get8Direction(nDirection
);
749 case PPT_TRANSITION_TYPE_DIAMOND
:
750 nTransition
= XML_diamond
;
752 case PPT_TRANSITION_TYPE_DISSOLVE
:
753 nTransition
= XML_dissolve
;
755 case PPT_TRANSITION_TYPE_FADE
:
756 nTransition
= XML_fade
;
759 case PPT_TRANSITION_TYPE_SMOOTHFADE
:
760 nTransition
= XML_fade
;
762 case PPT_TRANSITION_TYPE_NEWSFLASH
:
763 nTransition
= XML_newsflash
;
765 case PPT_TRANSITION_TYPE_PLUS
:
766 nTransition
= XML_plus
;
768 case PPT_TRANSITION_TYPE_PULL
:
769 nTransition
= XML_pull
;
770 pDirection
= Get8Direction(nDirection
);
772 case PPT_TRANSITION_TYPE_PUSH
:
773 nTransition
= XML_push
;
774 pDirection
= GetSideDirection(nDirection
);
776 case PPT_TRANSITION_TYPE_RANDOM
:
777 nTransition
= XML_random
;
779 case PPT_TRANSITION_TYPE_RANDOM_BARS
:
780 nTransition
= XML_randomBar
;
781 pDirection
= (nDirection
== 1) ? "vert" : "horz";
783 case PPT_TRANSITION_TYPE_SPLIT
:
784 nTransition
= XML_split
;
785 pDirection
= (nDirection
& 1) ? "in" : "out";
786 pOrientation
= (nDirection
< 2) ? "horz" : "vert";
788 case PPT_TRANSITION_TYPE_STRIPS
:
789 nTransition
= XML_strips
;
790 pDirection
= GetCornerDirection(nDirection
);
792 case PPT_TRANSITION_TYPE_WEDGE
:
793 nTransition
= XML_wedge
;
795 case PPT_TRANSITION_TYPE_WHEEL
:
796 nTransition
= XML_wheel
;
797 if (nDirection
!= 4 && nDirection
<= 9)
799 pSpokesTmp
[0] = '0' + nDirection
;
800 pSpokes
= pSpokesTmp
;
803 case PPT_TRANSITION_TYPE_WIPE
:
804 nTransition
= XML_wipe
;
805 pDirection
= GetSideDirection(nDirection
);
807 case PPT_TRANSITION_TYPE_ZOOM
:
808 nTransition
= XML_zoom
;
809 pDirection
= (nDirection
== 1) ? "in" : "out";
811 // coverity[dead_error_line] - following conditions exist to avoid compiler warning
812 case PPT_TRANSITION_TYPE_NONE
:
819 bool isAdvanceTimingSet
= advanceTiming
!= -1;
820 if (nTransition14
|| pPresetTransition
|| isTransitionDurationSet
)
822 const char* pRequiresNS
= (nTransition14
|| isTransitionDurationSet
) ? "p14" : "p15";
824 pFS
->startElement(FSNS(XML_mc
, XML_AlternateContent
), FSEND
);
825 pFS
->startElement(FSNS(XML_mc
, XML_Choice
), XML_Requires
, pRequiresNS
, FSEND
);
827 if(isTransitionDurationSet
&& isAdvanceTimingSet
)
829 pFS
->startElementNS(XML_p
, XML_transition
,
831 XML_advTm
, I32S(advanceTiming
* 1000),
832 FSNS(XML_p14
, XML_dur
), I32S(nTransitionDuration
),
835 else if(isTransitionDurationSet
)
837 pFS
->startElementNS(XML_p
, XML_transition
,
839 FSNS(XML_p14
, XML_dur
), I32S(nTransitionDuration
),
842 else if(isAdvanceTimingSet
)
844 pFS
->startElementNS(XML_p
, XML_transition
,
846 XML_advTm
, I32S(advanceTiming
* 1000),
851 pFS
->startElementNS(XML_p
, XML_transition
,
858 pFS
->singleElementNS(XML_p14
, nTransition14
,
859 XML_isInverted
, pInverted
,
860 XML_dir
, pDirection14
,
861 XML_pattern
, pPattern
,
864 else if (pPresetTransition
)
866 pFS
->singleElementNS(XML_p15
, XML_prstTrans
,
867 XML_prst
, pPresetTransition
,
870 else if (isTransitionDurationSet
&& nTransition
)
872 pFS
->singleElementNS(XML_p
, nTransition
,
874 XML_orient
, pOrientation
,
876 XML_thruBlk
, pThruBlk
,
880 pFS
->endElement(FSNS(XML_p
, XML_transition
));
882 pFS
->endElement(FSNS(XML_mc
, XML_Choice
));
883 pFS
->startElement(FSNS(XML_mc
, XML_Fallback
), FSEND
);
886 pFS
->startElementNS(XML_p
, XML_transition
,
888 XML_advTm
, isAdvanceTimingSet
? I32S(advanceTiming
* 1000) : nullptr,
893 pFS
->singleElementNS(XML_p
, nTransition
,
895 XML_orient
, pOrientation
,
897 XML_thruBlk
, pThruBlk
,
901 pFS
->endElementNS(XML_p
, XML_transition
);
903 if (nTransition14
|| pPresetTransition
|| isTransitionDurationSet
)
905 pFS
->endElement(FSNS(XML_mc
, XML_Fallback
));
906 pFS
->endElement(FSNS(XML_mc
, XML_AlternateContent
));
910 static OUString
lcl_GetInitials(const OUString
& sName
)
914 if (!sName
.isEmpty())
916 sRet
.append(sName
[0]);
917 sal_Int32 nStart
= 0, nOffset
;
919 while ((nOffset
= sName
.indexOf(' ', nStart
)) != -1)
921 if (nOffset
+ 1 < sName
.getLength())
922 sRet
.append(sName
[ nOffset
+ 1 ]);
923 nStart
= nOffset
+ 1;
927 return sRet
.makeStringAndClear();
930 void PowerPointExport::WriteAuthors()
932 if (maAuthors
.empty())
935 FSHelperPtr pFS
= openFragmentStreamWithSerializer("ppt/commentAuthors.xml",
936 "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml");
937 addRelation(mPresentationFS
->getOutputStream(),
938 oox::getRelationship(Relationship::COMMENTAUTHORS
),
939 "commentAuthors.xml");
941 pFS
->startElementNS(XML_p
, XML_cmAuthorLst
,
942 FSNS(XML_xmlns
, XML_p
), OUStringToOString(this->getNamespaceURL(OOX_NS(ppt
)), RTL_TEXTENCODING_UTF8
),
945 for (const AuthorsMap::value_type
& i
: maAuthors
)
947 pFS
->singleElementNS(XML_p
, XML_cmAuthor
,
948 XML_id
, I32S(i
.second
.nId
),
949 XML_name
, USS(i
.first
),
950 XML_initials
, USS(lcl_GetInitials(i
.first
)),
951 XML_lastIdx
, I32S(i
.second
.nLastIndex
),
952 XML_clrIdx
, I32S(i
.second
.nId
),
956 pFS
->endElementNS(XML_p
, XML_cmAuthorLst
);
959 sal_Int32
PowerPointExport::GetAuthorIdAndLastIndex(const OUString
& sAuthor
, sal_Int32
& nLastIndex
)
961 if (maAuthors
.count(sAuthor
) <= 0)
963 struct AuthorComments aAuthorComments
;
965 aAuthorComments
.nId
= maAuthors
.size();
966 aAuthorComments
.nLastIndex
= 0;
968 maAuthors
[ sAuthor
] = aAuthorComments
;
971 nLastIndex
= ++maAuthors
[ sAuthor
].nLastIndex
;
973 return maAuthors
[ sAuthor
].nId
;
976 bool PowerPointExport::WriteComments(sal_uInt32 nPageNum
)
978 Reference
< XAnnotationAccess
> xAnnotationAccess(mXDrawPage
, uno::UNO_QUERY
);
979 if (xAnnotationAccess
.is())
981 Reference
< XAnnotationEnumeration
> xAnnotationEnumeration(xAnnotationAccess
->createAnnotationEnumeration());
983 if (xAnnotationEnumeration
->hasMoreElements())
985 FSHelperPtr pFS
= openFragmentStreamWithSerializer(OUStringBuffer()
986 .append("ppt/comments/comment")
987 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
989 .makeStringAndClear(),
990 "application/vnd.openxmlformats-officedocument.presentationml.comments+xml");
992 pFS
->startElementNS(XML_p
, XML_cmLst
,
993 FSNS(XML_xmlns
, XML_p
), OUStringToOString(this->getNamespaceURL(OOX_NS(ppt
)), RTL_TEXTENCODING_UTF8
),
998 Reference
< XAnnotation
> xAnnotation(xAnnotationEnumeration
->nextElement());
999 DateTime
aDateTime(xAnnotation
->getDateTime());
1000 RealPoint2D
aRealPoint2D(xAnnotation
->getPosition());
1001 Reference
< XText
> xText(xAnnotation
->getTextRange());
1002 sal_Int32 nLastIndex
;
1003 sal_Int32 nId
= GetAuthorIdAndLastIndex(xAnnotation
->getAuthor(), nLastIndex
);
1006 snprintf(cDateTime
, 31, "%02d-%02d-%02dT%02d:%02d:%02d.%09" SAL_PRIuUINT32
, aDateTime
.Year
, aDateTime
.Month
, aDateTime
.Day
, aDateTime
.Hours
, aDateTime
.Minutes
, aDateTime
.Seconds
, aDateTime
.NanoSeconds
);
1008 pFS
->startElementNS(XML_p
, XML_cm
,
1009 XML_authorId
, I32S(nId
),
1011 XML_idx
, I32S(nLastIndex
),
1014 pFS
->singleElementNS(XML_p
, XML_pos
,
1015 XML_x
, I64S(static_cast<sal_Int64
>((57600*aRealPoint2D
.X
+ 1270)/2540.0)),
1016 XML_y
, I64S(static_cast<sal_Int64
>((57600*aRealPoint2D
.Y
+ 1270)/2540.0)),
1019 pFS
->startElementNS(XML_p
, XML_text
,
1021 pFS
->write(xText
->getString());
1022 pFS
->endElementNS(XML_p
, XML_text
);
1024 pFS
->endElementNS(XML_p
, XML_cm
);
1027 while (xAnnotationEnumeration
->hasMoreElements());
1029 pFS
->endElementNS(XML_p
, XML_cmLst
);
1038 void PowerPointExport::WriteVBA()
1043 uno::Reference
<document::XStorageBasedDocument
> xStorageBasedDocument(getModel(), uno::UNO_QUERY
);
1044 if (!xStorageBasedDocument
.is())
1047 uno::Reference
<embed::XStorage
> xDocumentStorage(xStorageBasedDocument
->getDocumentStorage(), uno::UNO_QUERY
);
1048 OUString
aMacrosName("_MS_VBA_Macros");
1049 if (!xDocumentStorage
.is() || !xDocumentStorage
->hasByName(aMacrosName
))
1052 const sal_Int32 nOpenMode
= embed::ElementModes::READ
;
1053 uno::Reference
<io::XInputStream
> xMacrosStream(xDocumentStorage
->openStreamElement(aMacrosName
, nOpenMode
), uno::UNO_QUERY
);
1054 if (!xMacrosStream
.is())
1057 uno::Reference
<io::XOutputStream
> xOutputStream
= openFragmentStream("ppt/vbaProject.bin", "application/vnd.ms-office.vbaProject");
1058 comphelper::OStorageHelper::CopyInputToOutput(xMacrosStream
, xOutputStream
);
1060 // Write the relationship.
1061 addRelation(mPresentationFS
->getOutputStream(), oox::getRelationship(Relationship::VBAPROJECT
), "vbaProject.bin");
1064 void PowerPointExport::ImplWriteSlide(sal_uInt32 nPageNum
, sal_uInt32 nMasterNum
, sal_uInt16
/* nMode */,
1065 bool bHasBackground
, Reference
< XPropertySet
> const& aXBackgroundPropSet
)
1067 SAL_INFO("sd.eppt", "write slide: " << nPageNum
<< "\n----------------");
1071 mPresentationFS
->startElementNS(XML_p
, XML_sldIdLst
, FSEND
);
1073 // add explicit relation of presentation to this slide
1074 OUString sRelId
= addRelation(mPresentationFS
->getOutputStream(),
1075 oox::getRelationship(Relationship::SLIDE
),
1077 .append("slides/slide")
1078 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1080 .makeStringAndClear());
1082 mPresentationFS
->singleElementNS(XML_p
, XML_sldId
,
1083 XML_id
, I32S(GetNewSlideId()),
1084 FSNS(XML_r
, XML_id
), USS(sRelId
),
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
,
1114 pFS
->startElementNS(XML_p
, XML_cSld
, FSEND
);
1119 ImplWriteBackground(pFS
, aXBackgroundPropSet
);
1122 WriteShapeTree(pFS
, NORMAL
, false);
1124 pFS
->endElementNS(XML_p
, XML_cSld
);
1126 WriteTransition(pFS
);
1127 WriteAnimations(pFS
, mXDrawPage
, *this);
1129 pFS
->endElementNS(XML_p
, XML_sld
);
1131 // add implicit relation to slide layout
1132 addRelation(pFS
->getOutputStream(),
1133 oox::getRelationship(Relationship::SLIDELAYOUT
),
1135 .append("../slideLayouts/slideLayout")
1136 .append(GetLayoutFileId(GetPPTXLayoutId(GetLayoutOffset(mXPagePropSet
)), nMasterNum
))
1138 .makeStringAndClear());
1140 if (WriteComments(nPageNum
))
1141 // add implicit relation to slide comments
1142 addRelation(pFS
->getOutputStream(),
1143 oox::getRelationship(Relationship::COMMENTS
),
1145 .append("../comments/comment")
1146 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1148 .makeStringAndClear());
1150 SAL_INFO("sd.eppt", "----------------");
1153 void PowerPointExport::ImplWriteNotes(sal_uInt32 nPageNum
)
1155 if (!mbCreateNotes
|| !ContainsOtherShapeThanPlaceholders())
1158 SAL_INFO("sd.eppt", "write Notes " << nPageNum
<< "\n----------------");
1160 FSHelperPtr pFS
= openFragmentStreamWithSerializer(OUStringBuffer()
1161 .append("ppt/notesSlides/notesSlide")
1162 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1164 .makeStringAndClear(),
1165 "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml");
1167 pFS
->startElementNS(XML_p
, XML_notes
, PNMSS
, FSEND
);
1169 pFS
->startElementNS(XML_p
, XML_cSld
, FSEND
);
1171 WriteShapeTree(pFS
, NOTICE
, false);
1173 pFS
->endElementNS(XML_p
, XML_cSld
);
1175 pFS
->endElementNS(XML_p
, XML_notes
);
1177 // add implicit relation to slide
1178 addRelation(pFS
->getOutputStream(),
1179 oox::getRelationship(Relationship::SLIDE
),
1181 .append("../slides/slide")
1182 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1184 .makeStringAndClear());
1186 // add slide implicit relation to notes
1187 if (nPageNum
< mpSlidesFSArray
.size())
1188 addRelation(mpSlidesFSArray
[ nPageNum
]->getOutputStream(),
1189 oox::getRelationship(Relationship::NOTESSLIDE
),
1191 .append("../notesSlides/notesSlide")
1192 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1194 .makeStringAndClear());
1196 // add implicit relation to notes master
1197 addRelation(pFS
->getOutputStream(),
1198 oox::getRelationship(Relationship::NOTESMASTER
),
1199 "../notesMasters/notesMaster1.xml");
1201 SAL_INFO("sd.eppt", "-----------------");
1204 void PowerPointExport::AddLayoutIdAndRelation(const FSHelperPtr
& pFS
, sal_Int32 nLayoutFileId
)
1206 // add implicit relation of slide master to slide layout
1207 OUString sRelId
= addRelation(pFS
->getOutputStream(),
1208 oox::getRelationship(Relationship::SLIDELAYOUT
),
1210 .append("../slideLayouts/slideLayout")
1211 .append(nLayoutFileId
)
1213 .makeStringAndClear());
1215 pFS
->singleElementNS(XML_p
, XML_sldLayoutId
,
1216 XML_id
, I64S(GetNewSlideMasterId()),
1217 FSNS(XML_r
, XML_id
), USS(sRelId
),
1221 void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum
, Reference
< XPropertySet
> const& aXBackgroundPropSet
)
1223 SAL_INFO("sd.eppt", "write master slide: " << nPageNum
<< "\n--------------");
1227 mPresentationFS
->startElementNS(XML_p
, XML_sldMasterIdLst
, FSEND
);
1229 OUString sRelId
= addRelation(mPresentationFS
->getOutputStream(),
1230 oox::getRelationship(Relationship::SLIDEMASTER
),
1232 .append("slideMasters/slideMaster")
1233 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1235 .makeStringAndClear());
1237 mPresentationFS
->singleElementNS(XML_p
, XML_sldMasterId
,
1238 XML_id
, OString::number(GetNewSlideMasterId()).getStr(),
1239 FSNS(XML_r
, XML_id
), USS(sRelId
),
1242 if (nPageNum
== mnMasterPages
- 1)
1243 mPresentationFS
->endElementNS(XML_p
, XML_sldMasterIdLst
);
1246 openFragmentStreamWithSerializer(OUStringBuffer()
1247 .append("ppt/slideMasters/slideMaster")
1248 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1250 .makeStringAndClear(),
1251 "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml");
1253 // write theme per master
1254 WriteTheme(nPageNum
);
1256 // add implicit relation to the presentation theme
1257 addRelation(pFS
->getOutputStream(),
1258 oox::getRelationship(Relationship::THEME
),
1260 .append("../theme/theme")
1261 .append(static_cast<sal_Int32
>(nPageNum
) + 1)
1263 .makeStringAndClear());
1265 pFS
->startElementNS(XML_p
, XML_sldMaster
, PNMSS
, FSEND
);
1267 pFS
->startElementNS(XML_p
, XML_cSld
, FSEND
);
1269 ImplWriteBackground(pFS
, aXBackgroundPropSet
);
1270 WriteShapeTree(pFS
, MASTER
, true);
1272 pFS
->endElementNS(XML_p
, XML_cSld
);
1274 // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
1275 pFS
->singleElementNS(XML_p
, XML_clrMap
,
1280 XML_accent1
, "accent1",
1281 XML_accent2
, "accent2",
1282 XML_accent3
, "accent3",
1283 XML_accent4
, "accent4",
1284 XML_accent5
, "accent5",
1285 XML_accent6
, "accent6",
1287 XML_folHlink
, "folHlink",
1290 // use master's id type as they have same range, mso does that as well
1291 pFS
->startElementNS(XML_p
, XML_sldLayoutIdLst
, FSEND
);
1293 for (int i
= 0; i
< LAYOUT_SIZE
; i
++)
1295 sal_Int32 nLayoutFileId
= GetLayoutFileId(i
, nPageNum
);
1296 if (nLayoutFileId
> 0)
1298 AddLayoutIdAndRelation(pFS
, nLayoutFileId
);
1302 ImplWritePPTXLayout(i
, nPageNum
);
1303 AddLayoutIdAndRelation(pFS
, GetLayoutFileId(i
, nPageNum
));
1307 pFS
->endElementNS(XML_p
, XML_sldLayoutIdLst
);
1309 pFS
->endElementNS(XML_p
, XML_sldMaster
);
1311 SAL_INFO("sd.eppt", "----------------");
1314 sal_Int32
PowerPointExport::GetLayoutFileId(sal_Int32 nOffset
, sal_uInt32 nMasterNum
)
1316 SAL_INFO("sd.eppt", "GetLayoutFileId offset: " << nOffset
<< " master: " << nMasterNum
);
1317 if (mLayoutInfo
[ nOffset
].mnFileIdArray
.size() <= nMasterNum
)
1320 return mLayoutInfo
[ nOffset
].mnFileIdArray
[ nMasterNum
];
1323 void PowerPointExport::ImplWritePPTXLayout(sal_Int32 nOffset
, sal_uInt32 nMasterNum
)
1325 SAL_INFO("sd.eppt", "write layout: " << nOffset
);
1327 Reference
< drawing::XDrawPagesSupplier
> xDPS(getModel(), uno::UNO_QUERY
);
1328 Reference
< drawing::XDrawPages
> xDrawPages(xDPS
->getDrawPages(), uno::UNO_QUERY
);
1329 Reference
< drawing::XDrawPage
> xSlide
;
1330 Reference
< container::XIndexAccess
> xIndexAccess(xDrawPages
, uno::UNO_QUERY
);
1332 xSlide
= xDrawPages
->insertNewByIndex(xIndexAccess
->getCount());
1336 printf("new page created\n");
1339 Reference
< beans::XPropertySet
> xPropSet(xSlide
, uno::UNO_QUERY
);
1340 xPropSet
->setPropertyValue("Layout", makeAny(short(aLayoutInfo
[ nOffset
].nType
)));
1341 #if OSL_DEBUG_LEVEL > 1
1342 dump_pset(xPropSet
);
1344 mXPagePropSet
.set(xSlide
, UNO_QUERY
);
1345 mXShapes
.set(xSlide
, UNO_QUERY
);
1347 if (mLayoutInfo
[ nOffset
].mnFileIdArray
.size() < mnMasterPages
)
1349 mLayoutInfo
[ nOffset
].mnFileIdArray
.resize(mnMasterPages
);
1352 if (mLayoutInfo
[ nOffset
].mnFileIdArray
[ nMasterNum
] != 0)
1356 = openFragmentStreamWithSerializer(OUStringBuffer()
1357 .append("ppt/slideLayouts/slideLayout")
1358 .append(mnLayoutFileIdMax
)
1360 .makeStringAndClear(),
1361 "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml");
1363 // add implicit relation of slide layout to slide master
1364 addRelation(pFS
->getOutputStream(),
1365 oox::getRelationship(Relationship::SLIDEMASTER
),
1367 .append("../slideMasters/slideMaster")
1368 .append(static_cast<sal_Int32
>(nMasterNum
) + 1)
1370 .makeStringAndClear());
1372 pFS
->startElementNS(XML_p
, XML_sldLayout
,
1374 XML_type
, aLayoutInfo
[ nOffset
].sType
,
1378 pFS
->startElementNS(XML_p
, XML_cSld
,
1379 XML_name
, aLayoutInfo
[ nOffset
].sName
,
1381 //pFS->write( MINIMAL_SPTREE ); // TODO: write actual shape tree
1382 WriteShapeTree(pFS
, LAYOUT
, true);
1384 pFS
->endElementNS(XML_p
, XML_cSld
);
1386 pFS
->endElementNS(XML_p
, XML_sldLayout
);
1388 mLayoutInfo
[ nOffset
].mnFileIdArray
[ nMasterNum
] = mnLayoutFileIdMax
;
1390 mnLayoutFileIdMax
++;
1392 xDrawPages
->remove(xSlide
);
1395 void PowerPointExport::WriteShapeTree(const FSHelperPtr
& pFS
, PageType ePageType
, bool bMaster
)
1397 PowerPointShapeExport
aDML(pFS
, &maShapeMap
, this);
1398 aDML
.SetMaster(bMaster
);
1399 aDML
.SetPageType(ePageType
);
1400 aDML
.SetBackgroundDark(mbIsBackgroundDark
);
1402 pFS
->startElementNS(XML_p
, XML_spTree
, FSEND
);
1403 pFS
->write(MAIN_GROUP
);
1405 ResetGroupTable(mXShapes
->getCount());
1407 while (GetNextGroupEntry())
1410 sal_uInt32 nGroups
= GetGroupsClosed();
1411 for (sal_uInt32 i
= 0; i
< nGroups
; i
++)
1413 SAL_INFO("sd.eppt", "leave group");
1416 if (GetShapeByIndex(GetCurrentGroupIndex(), true))
1418 SAL_INFO("sd.eppt", "mType: " << mType
);
1419 aDML
.WriteShape(mXShape
);
1423 pFS
->endElementNS(XML_p
, XML_spTree
);
1426 ShapeExport
& PowerPointShapeExport::WritePageShape(const Reference
< XShape
>& xShape
, PageType ePageType
, bool bPresObj
)
1428 if ((ePageType
== NOTICE
&& bPresObj
) || ePageType
== LAYOUT
|| ePageType
== MASTER
)
1429 return WritePlaceholderShape(xShape
, SlideImage
);
1431 return WriteTextShape(xShape
);
1434 bool PowerPointShapeExport::WritePlaceholder(const Reference
< XShape
>& xShape
, PlaceholderType ePlaceholder
, bool bMaster
)
1436 SAL_INFO("sd.eppt", "WritePlaceholder " << bMaster
<< " " << ShapeExport::NonEmptyText(xShape
));
1437 if (bMaster
&& ShapeExport::NonEmptyText(xShape
))
1439 WritePlaceholderShape(xShape
, ePlaceholder
);
1447 ShapeExport
& PowerPointShapeExport::WritePlaceholderShape(const Reference
< XShape
>& xShape
, PlaceholderType ePlaceholder
)
1449 mpFS
->startElementNS(XML_p
, XML_sp
, FSEND
);
1451 // non visual shape properties
1452 mpFS
->startElementNS(XML_p
, XML_nvSpPr
, FSEND
);
1453 const OString
aPlaceholderID("PlaceHolder " + OString::number(mnShapeIdMax
++));
1454 WriteNonVisualDrawingProperties(xShape
, aPlaceholderID
.getStr());
1455 mpFS
->startElementNS(XML_p
, XML_cNvSpPr
, FSEND
);
1456 mpFS
->singleElementNS(XML_a
, XML_spLocks
, XML_noGrp
, "1", FSEND
);
1457 mpFS
->endElementNS(XML_p
, XML_cNvSpPr
);
1458 mpFS
->startElementNS(XML_p
, XML_nvPr
, FSEND
);
1460 const char* pType
= nullptr;
1461 switch (ePlaceholder
)
1491 SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder
);
1493 SAL_INFO("sd.eppt", "write placeholder " << pType
);
1494 mpFS
->singleElementNS(XML_p
, XML_ph
, XML_type
, pType
, FSEND
);
1495 mpFS
->endElementNS(XML_p
, XML_nvPr
);
1496 mpFS
->endElementNS(XML_p
, XML_nvSpPr
);
1498 // visual shape properties
1499 mpFS
->startElementNS(XML_p
, XML_spPr
, FSEND
);
1500 WriteShapeTransformation(xShape
, XML_a
);
1501 WritePresetShape("rect");
1502 Reference
< XPropertySet
> xProps(xShape
, UNO_QUERY
);
1504 WriteBlipFill(xProps
, "Graphic");
1505 mpFS
->endElementNS(XML_p
, XML_spPr
);
1507 WriteTextBox(xShape
, XML_p
);
1509 mpFS
->endElementNS(XML_p
, XML_sp
);
1514 #define SYS_COLOR_SCHEMES " <a:dk1>\
1515 <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
1518 <a:sysClr val=\"window\" lastClr=\"FFFFFF\"/>\
1521 #define MINIMAL_THEME " <a:fontScheme name=\"Office\">\
1523 <a:latin typeface=\"Arial\"/>\
1524 <a:ea typeface=\"DejaVu Sans\"/>\
1525 <a:cs typeface=\"DejaVu Sans\"/>\
1528 <a:latin typeface=\"Arial\"/>\
1529 <a:ea typeface=\"DejaVu Sans\"/>\
1530 <a:cs typeface=\"DejaVu Sans\"/>\
1533 <a:fmtScheme name=\"Office\">\
1536 <a:schemeClr val=\"phClr\"/>\
1538 <a:gradFill rotWithShape=\"1\">\
1541 <a:schemeClr val=\"phClr\">\
1542 <a:tint val=\"50000\"/>\
1543 <a:satMod val=\"300000\"/>\
1546 <a:gs pos=\"35000\">\
1547 <a:schemeClr val=\"phClr\">\
1548 <a:tint val=\"37000\"/>\
1549 <a:satMod val=\"300000\"/>\
1552 <a:gs pos=\"100000\">\
1553 <a:schemeClr val=\"phClr\">\
1554 <a:tint val=\"15000\"/>\
1555 <a:satMod val=\"350000\"/>\
1559 <a:lin ang=\"16200000\" scaled=\"1\"/>\
1561 <a:gradFill rotWithShape=\"1\">\
1564 <a:schemeClr val=\"phClr\">\
1565 <a:shade val=\"51000\"/>\
1566 <a:satMod val=\"130000\"/>\
1569 <a:gs pos=\"80000\">\
1570 <a:schemeClr val=\"phClr\">\
1571 <a:shade val=\"93000\"/>\
1572 <a:satMod val=\"130000\"/>\
1575 <a:gs pos=\"100000\">\
1576 <a:schemeClr val=\"phClr\">\
1577 <a:shade val=\"94000\"/>\
1578 <a:satMod val=\"135000\"/>\
1582 <a:lin ang=\"16200000\" scaled=\"0\"/>\
1586 <a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1588 <a:schemeClr val=\"phClr\">\
1589 <a:shade val=\"95000\"/>\
1590 <a:satMod val=\"105000\"/>\
1593 <a:prstDash val=\"solid\"/>\
1595 <a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1597 <a:schemeClr val=\"phClr\"/>\
1599 <a:prstDash val=\"solid\"/>\
1601 <a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
1603 <a:schemeClr val=\"phClr\"/>\
1605 <a:prstDash val=\"solid\"/>\
1611 <a:outerShdw blurRad=\"40000\" dist=\"20000\" dir=\"5400000\" rotWithShape=\"0\">\
1612 <a:srgbClr val=\"000000\">\
1613 <a:alpha val=\"38000\"/>\
1620 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1621 <a:srgbClr val=\"000000\">\
1622 <a:alpha val=\"35000\"/>\
1629 <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
1630 <a:srgbClr val=\"000000\">\
1631 <a:alpha val=\"35000\"/>\
1636 <a:camera prst=\"orthographicFront\">\
1637 <a:rot lat=\"0\" lon=\"0\" rev=\"0\"/>\
1639 <a:lightRig rig=\"threePt\" dir=\"t\">\
1640 <a:rot lat=\"0\" lon=\"0\" rev=\"1200000\"/>\
1644 <a:bevelT w=\"63500\" h=\"25400\"/>\
1647 </a:effectStyleLst>\
1650 <a:schemeClr val=\"phClr\"/>\
1652 <a:gradFill rotWithShape=\"1\">\
1655 <a:schemeClr val=\"phClr\">\
1656 <a:tint val=\"40000\"/>\
1657 <a:satMod val=\"350000\"/>\
1660 <a:gs pos=\"40000\">\
1661 <a:schemeClr val=\"phClr\">\
1662 <a:tint val=\"45000\"/>\
1663 <a:shade val=\"99000\"/>\
1664 <a:satMod val=\"350000\"/>\
1667 <a:gs pos=\"100000\">\
1668 <a:schemeClr val=\"phClr\">\
1669 <a:shade val=\"20000\"/>\
1670 <a:satMod val=\"255000\"/>\
1674 <a:path path=\"circle\">\
1675 <a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/>\
1678 <a:gradFill rotWithShape=\"1\">\
1681 <a:schemeClr val=\"phClr\">\
1682 <a:tint val=\"80000\"/>\
1683 <a:satMod val=\"300000\"/>\
1686 <a:gs pos=\"100000\">\
1687 <a:schemeClr val=\"phClr\">\
1688 <a:shade val=\"30000\"/>\
1689 <a:satMod val=\"200000\"/>\
1693 <a:path path=\"circle\">\
1694 <a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/>\
1697 </a:bgFillStyleLst>\
1700 void PowerPointExport::WriteDefaultColorSchemes(const FSHelperPtr
& pFS
)
1702 for (int nId
= PredefinedClrSchemeId::dk2
; nId
!= PredefinedClrSchemeId::Count
; nId
++)
1704 OUString sName
= PredefinedClrNames
[static_cast<PredefinedClrSchemeId
>(nId
)];
1705 sal_Int32 nColor
= 0;
1709 case PredefinedClrSchemeId::dk2
:
1712 case PredefinedClrSchemeId::lt2
:
1715 case PredefinedClrSchemeId::accent1
:
1718 case PredefinedClrSchemeId::accent2
:
1721 case PredefinedClrSchemeId::accent3
:
1724 case PredefinedClrSchemeId::accent4
:
1727 case PredefinedClrSchemeId::accent5
:
1730 case PredefinedClrSchemeId::accent6
:
1733 case PredefinedClrSchemeId::hlink
:
1736 case PredefinedClrSchemeId::folHlink
:
1741 OUString sOpenColorScheme
= OUStringBuffer()
1745 .makeStringAndClear();
1746 pFS
->write(sOpenColorScheme
);
1748 pFS
->singleElementNS(XML_a
, XML_srgbClr
, XML_val
, I32SHEX(nColor
), FSEND
);
1750 OUString sCloseColorScheme
= OUStringBuffer()
1754 .makeStringAndClear();
1755 pFS
->write(sCloseColorScheme
);
1759 bool PowerPointExport::WriteColorSchemes(const FSHelperPtr
& pFS
, const OUString
& rThemePath
)
1763 uno::Reference
<beans::XPropertySet
> xDocProps(getModel(), uno::UNO_QUERY
);
1766 uno::Reference
<beans::XPropertySetInfo
> xPropsInfo
= xDocProps
->getPropertySetInfo();
1768 const OUString aGrabBagPropName
= "InteropGrabBag";
1769 if (xPropsInfo
.is() && xPropsInfo
->hasPropertyByName(aGrabBagPropName
))
1771 comphelper::SequenceAsHashMap
aGrabBag(xDocProps
->getPropertyValue(aGrabBagPropName
));
1772 uno::Sequence
<beans::PropertyValue
> aCurrentTheme
;
1774 aGrabBag
.getValue(rThemePath
) >>= aCurrentTheme
;
1776 if (!aCurrentTheme
.getLength())
1779 // Order is important
1780 for (int nId
= PredefinedClrSchemeId::dk2
; nId
!= PredefinedClrSchemeId::Count
; nId
++)
1782 OUString sName
= PredefinedClrNames
[static_cast<PredefinedClrSchemeId
>(nId
)];
1783 sal_Int32 nColor
= 0;
1785 for (auto aIt
= aCurrentTheme
.begin(); aIt
!= aCurrentTheme
.end(); aIt
++)
1787 if (aIt
->Name
== sName
)
1789 aIt
->Value
>>= nColor
;
1794 OUString sOpenColorScheme
= OUStringBuffer()
1798 .makeStringAndClear();
1799 pFS
->write(sOpenColorScheme
);
1801 pFS
->singleElementNS(XML_a
, XML_srgbClr
, XML_val
, I32SHEX(nColor
), FSEND
);
1803 OUString sCloseColorScheme
= OUStringBuffer()
1807 .makeStringAndClear();
1808 pFS
->write(sCloseColorScheme
);
1811 // TODO: write complete color schemes & only if successful, protection against partial export
1816 catch (const uno::Exception
&)
1818 SAL_WARN("writerfilter", "Failed to save documents grab bag");
1824 void PowerPointExport::WriteTheme(sal_Int32 nThemeNum
)
1826 OUString sThemePath
= OUStringBuffer()
1827 .append("ppt/theme/theme")
1828 .append(nThemeNum
+ 1)
1830 .makeStringAndClear();
1832 FSHelperPtr pFS
= openFragmentStreamWithSerializer(sThemePath
,
1833 "application/vnd.openxmlformats-officedocument.theme+xml");
1835 pFS
->startElementNS(XML_a
, XML_theme
,
1836 FSNS(XML_xmlns
, XML_a
), OUStringToOString(this->getNamespaceURL(OOX_NS(dml
)), RTL_TEXTENCODING_UTF8
),
1837 XML_name
, "Office Theme",
1840 pFS
->startElementNS(XML_a
, XML_themeElements
, FSEND
);
1841 pFS
->startElementNS(XML_a
, XML_clrScheme
, XML_name
, "Office", FSEND
);
1843 pFS
->write(SYS_COLOR_SCHEMES
);
1845 if (!WriteColorSchemes(pFS
, sThemePath
))
1847 // if style is not defined, try to use first one
1848 if (!WriteColorSchemes(pFS
, "ppt/theme/theme1.xml"))
1850 // color schemes are required - use default values
1851 WriteDefaultColorSchemes(pFS
);
1855 pFS
->endElementNS(XML_a
, XML_clrScheme
);
1857 // export remaining part
1858 pFS
->write(MINIMAL_THEME
);
1860 pFS
->endElementNS(XML_a
, XML_themeElements
);
1861 pFS
->endElementNS(XML_a
, XML_theme
);
1864 bool PowerPointExport::ImplCreateDocument()
1866 mbCreateNotes
= false;
1868 for (sal_uInt32 i
= 0; i
< mnPages
; i
++)
1870 if (!GetPageByIndex(i
, NOTICE
))
1873 if (ContainsOtherShapeThanPlaceholders())
1875 mbCreateNotes
= true;
1883 void PowerPointExport::WriteNotesMaster()
1885 SAL_INFO("sd.eppt", "write Notes master\n---------------");
1887 mPresentationFS
->startElementNS(XML_p
, XML_notesMasterIdLst
, FSEND
);
1889 OUString sRelId
= addRelation(mPresentationFS
->getOutputStream(),
1890 oox::getRelationship(Relationship::NOTESMASTER
),
1891 "notesMasters/notesMaster1.xml");
1893 mPresentationFS
->singleElementNS(XML_p
, XML_notesMasterId
,
1894 FSNS(XML_r
, XML_id
), USS(sRelId
),
1897 mPresentationFS
->endElementNS(XML_p
, XML_notesMasterIdLst
);
1900 openFragmentStreamWithSerializer("ppt/notesMasters/notesMaster1.xml",
1901 "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml");
1902 // write theme per master
1903 WriteTheme(mnMasterPages
);
1905 // add implicit relation to the presentation theme
1906 addRelation(pFS
->getOutputStream(),
1907 oox::getRelationship(Relationship::THEME
),
1909 .append("../theme/theme")
1910 .append(static_cast<sal_Int32
>(mnMasterPages
) + 1)
1912 .makeStringAndClear());
1914 pFS
->startElementNS(XML_p
, XML_notesMaster
, PNMSS
, FSEND
);
1916 pFS
->startElementNS(XML_p
, XML_cSld
, FSEND
);
1918 Reference
< XPropertySet
> aXBackgroundPropSet
;
1919 if (ImplGetPropertyValue(mXPagePropSet
, "Background") &&
1920 (mAny
>>= aXBackgroundPropSet
))
1921 ImplWriteBackground(pFS
, aXBackgroundPropSet
);
1923 WriteShapeTree(pFS
, NOTICE
, true);
1925 pFS
->endElementNS(XML_p
, XML_cSld
);
1927 // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
1928 pFS
->singleElementNS(XML_p
, XML_clrMap
,
1933 XML_accent1
, "accent1",
1934 XML_accent2
, "accent2",
1935 XML_accent3
, "accent3",
1936 XML_accent4
, "accent4",
1937 XML_accent5
, "accent5",
1938 XML_accent6
, "accent6",
1940 XML_folHlink
, "folHlink",
1943 pFS
->endElementNS(XML_p
, XML_notesMaster
);
1945 SAL_INFO("sd.eppt", "----------------");
1948 sal_Int32
PowerPointExport::GetShapeID(const Reference
<XShape
>& rXShape
)
1950 return ShapeExport::GetShapeID(rXShape
, &maShapeMap
);
1953 sal_Int32
PowerPointExport::GetNextAnimationNodeID()
1955 return mnAnimationNodeIdMax
++;
1958 bool PowerPointExport::ImplCreateMainNotes()
1966 OUString
PowerPointExport::getImplementationName()
1968 return OUString("com.sun.star.comp.Impress.oox.PowerPointExport");
1972 extern "C" SAL_DLLPUBLIC_EXPORT
uno::XInterface
*
1973 css_comp_Impress_oox_PowerPointExport(uno::XComponentContext
* rxCtxt
,
1974 uno::Sequence
<css::uno::Any
> const& rArguments
)
1976 return cppu::acquire(new PowerPointExport(rxCtxt
, rArguments
));
1979 #if OSL_DEBUG_LEVEL > 1
1980 void dump_pset(Reference
< XPropertySet
> const& rXPropSet
)
1982 Reference
< XPropertySetInfo
> info
= rXPropSet
->getPropertySetInfo();
1983 Sequence
< beans::Property
> props
= info
->getProperties();
1985 for (int i
=0; i
< props
.getLength(); i
++)
1987 OString name
= OUStringToOString(props
[i
].Name
, RTL_TEXTENCODING_UTF8
);
1989 Any value
= rXPropSet
->getPropertyValue(props
[i
].Name
);
1994 RectanglePoint pointValue
;
1996 if (value
>>= strValue
)
1997 SAL_INFO("sd.eppt", name
<< " = \"" << strValue
<< "\"");
1998 else if (value
>>= intValue
)
1999 SAL_INFO("sd.eppt", name
<< " = " << intValue
<< "(hex : " << std::hex
<< intValue
<< ")");
2000 else if (value
>>= boolValue
)
2001 SAL_INFO("sd.eppt", name
<< " = " << boolValue
<< " (bool)");
2002 else if (value
>>= pointValue
)
2003 SAL_INFO("sd.eppt", name
<< " = " << pointValue
<< " (RectanglePoint)");
2005 SAL_INFO("sd.eppt", "??? <unhandled type>");
2010 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */