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 .
20 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
21 #include <com/sun/star/animations/AnimationFill.hpp>
22 #include <com/sun/star/animations/AnimationRestart.hpp>
23 #include <com/sun/star/animations/Timing.hpp>
24 #include <com/sun/star/animations/Event.hpp>
25 #include <com/sun/star/animations/AnimationEndSync.hpp>
26 #include <com/sun/star/animations/EventTrigger.hpp>
27 #include <com/sun/star/presentation/EffectNodeType.hpp>
28 #include <com/sun/star/presentation/EffectPresetClass.hpp>
29 #include <com/sun/star/animations/AnimationNodeType.hpp>
30 #include <com/sun/star/animations/AnimationTransformType.hpp>
31 #include <com/sun/star/animations/AnimationCalcMode.hpp>
32 #include <com/sun/star/util/XCloneable.hpp>
33 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
34 #include <com/sun/star/animations/XAnimateSet.hpp>
35 #include <com/sun/star/animations/XAudio.hpp>
36 #include <com/sun/star/animations/XTransitionFilter.hpp>
37 #include <com/sun/star/animations/XAnimateColor.hpp>
38 #include <com/sun/star/animations/XAnimateMotion.hpp>
39 #include <com/sun/star/animations/XAnimateTransform.hpp>
40 #include <com/sun/star/animations/ValuePair.hpp>
41 #include <com/sun/star/animations/AnimationColorSpace.hpp>
42 #include <com/sun/star/drawing/FillStyle.hpp>
43 #include <com/sun/star/drawing/LineStyle.hpp>
44 #include <com/sun/star/drawing/XDrawPage.hpp>
45 #include <com/sun/star/awt/FontWeight.hpp>
46 #include <com/sun/star/awt/FontUnderline.hpp>
47 #include <com/sun/star/awt/FontSlant.hpp>
48 #include <com/sun/star/container/XEnumerationAccess.hpp>
49 #include <com/sun/star/presentation/ParagraphTarget.hpp>
50 #include <com/sun/star/text/XSimpleText.hpp>
51 #include <com/sun/star/animations/XIterateContainer.hpp>
52 #include <com/sun/star/presentation/TextAnimationType.hpp>
54 #include <oox/ppt/pptfilterhelpers.hxx>
55 #include "pptexanimations.hxx"
56 #include "pptexsoundcollection.hxx"
57 #include "../ppt/pptanimations.hxx"
58 #include <filter/msfilter/escherex.hxx>
59 #include <osl/diagnose.h>
60 #include <tools/debug.hxx>
61 #include <comphelper/diagnose_ex.hxx>
62 #include <o3tl/string_view.hxx>
66 using ::com::sun::star::uno::Any
;
67 using ::com::sun::star::util::XCloneable
;
68 using ::com::sun::star::uno::Reference
;
69 using ::com::sun::star::uno::UNO_QUERY
;
70 using ::com::sun::star::uno::UNO_QUERY_THROW
;
71 using ::com::sun::star::uno::Sequence
;
72 using ::com::sun::star::uno::Exception
;
73 using ::com::sun::star::beans::NamedValue
;
74 using ::com::sun::star::container::XEnumerationAccess
;
75 using ::com::sun::star::container::XEnumeration
;
77 using namespace ::com::sun::star::text
;
78 using namespace ::com::sun::star::drawing
;
79 using namespace ::com::sun::star::animations
;
80 using namespace ::com::sun::star::presentation
;
85 static void ImplTranslateAttribute( OUString
& rString
, const TranslateMode eTranslateMode
)
87 if ( eTranslateMode
== TRANSLATE_NONE
)
90 if ( ( eTranslateMode
& TRANSLATE_VALUE
) || ( eTranslateMode
& TRANSLATE_ATTRIBUTE
) )
92 const oox::ppt::ImplAttributeNameConversion
* p
= oox::ppt::getAttributeConversionList();
95 if( rString
.equalsAscii( p
->mpAPIName
) )
101 if ( eTranslateMode
& TRANSLATE_VALUE
)
104 rString
+= OUString::createFromAscii( p
->mpMSName
);
107 rString
= OUString::createFromAscii( p
->mpMSName
);
110 else if ( eTranslateMode
& TRANSLATE_MEASURE
)
112 const char* pDest
[] = { "#ppt_x", "#ppt_y", "#ppt_w", "#ppt_h", nullptr };
113 const char* pSource
[] = { "x", "y", "width", "height", nullptr };
114 sal_Int32 nIndex
= 0;
116 const char** ps
= pSource
;
117 const char** pd
= pDest
;
123 const OUString
aSearch( OUString::createFromAscii( *ps
) );
124 while( (nIndex
= rString
.indexOf( aSearch
, nIndex
)) != -1 )
126 sal_Int32 nLength
= aSearch
.getLength();
127 if( nIndex
&& ( rString
[nIndex
-1] == '#' ) )
133 const OUString
aNew( OUString::createFromAscii( *pd
) );
134 rString
= rString
.replaceAt( nIndex
, nLength
, aNew
);
135 nIndex
+= aNew
.getLength();
143 sal_uInt32
AnimationExporter::TranslatePresetSubType( const sal_uInt32 nPresetClass
, const sal_uInt32 nPresetId
, std::u16string_view rPresetSubType
)
145 sal_uInt32 nPresetSubType
= 0;
146 bool bTranslated
= false;
148 if ( ( nPresetClass
== sal_uInt32(EffectPresetClass::ENTRANCE
) ) || ( nPresetClass
== sal_uInt32(EffectPresetClass::EXIT
) ) )
150 if ( nPresetId
!= 21 )
156 if ( rPresetSubType
== u
"downward" )
161 else if ( rPresetSubType
== u
"across" )
170 if ( rPresetSubType
== u
"across" )
179 if ( rPresetSubType
== u
"right-to-top" )
184 else if ( rPresetSubType
== u
"right-to-bottom" )
189 else if ( rPresetSubType
== u
"left-to-top" )
194 else if ( rPresetSubType
== u
"left-to-bottom" )
205 const oox::ppt::convert_subtype
* p
= oox::ppt::convert_subtype::getList();
206 while( p
->mpStrSubType
)
208 if ( o3tl::equalsAscii( rPresetSubType
, p
->mpStrSubType
) )
210 nPresetSubType
= p
->mnID
;
219 nPresetSubType
= o3tl::toUInt32(rPresetSubType
);
220 return nPresetSubType
;
223 const char* AnimationExporter::FindTransitionName( const sal_Int16 nType
, const sal_Int16 nSubType
, const bool bDirection
)
225 const char* pRet
= nullptr;
228 const oox::ppt::transition
* p
= oox::ppt::transition::getList();
232 if ( nType
== p
->mnType
)
234 if ( nSubType
== p
->mnSubType
)
236 if ( bDirection
== p
->mbDirection
)
243 if ( nFit
== 7 ) // maximum
250 SvStream
& WriteAnimationNode(SvStream
& rOut
, AnimationNode
const & rNode
)
252 rOut
.WriteInt32( rNode
.mnU1
);
253 rOut
.WriteInt32( rNode
.mnRestart
);
254 rOut
.WriteInt32( rNode
.mnGroupType
);
255 rOut
.WriteInt32( rNode
.mnFill
);
256 rOut
.WriteInt32( rNode
.mnU3
);
257 rOut
.WriteInt32( rNode
.mnU4
);
258 rOut
.WriteInt32( rNode
.mnDuration
);
259 rOut
.WriteInt32( rNode
.mnNodeType
);
264 AnimationExporter::AnimationExporter( const EscherSolverContainer
& rSolverContainer
, ppt::ExSoundCollection
& rExSoundCollection
) :
265 mrSolverContainer ( rSolverContainer
),
266 mrExSoundCollection ( rExSoundCollection
),
271 sal_Int16
AnimationExporter::GetFillMode( const Reference
< XAnimationNode
>& xNode
, const sal_Int16 nFillDefault
)
273 sal_Int16 nFill
= xNode
->getFill();
274 //#i119699 <Animation> The animation effect "Emphasis->FlashBulb" play incorrectly in Aoo saves a .ppt to another .ppt and plays the saved one.
275 //#i119740 <Animation> The animation effect "Entrance->Flash Once" fails to play in Aoo while Aoo saves a .ppt to another .ppt and plays the saved one.
276 if ((xNode
->getType() == AnimationNodeType::ANIMATE
)
277 ||(xNode
->getType() == AnimationNodeType::SET
)
278 ||(xNode
->getType() == AnimationNodeType::TRANSITIONFILTER
))
280 if ( nFill
== AnimationFill::DEFAULT
)
284 if ( nFill
== AnimationFill::DEFAULT
)
286 nFill
= nFillDefault
;
288 if( nFill
== AnimationFill::AUTO
)
290 nFill
= AnimationFill::REMOVE
;
291 bool bIsIndefiniteTiming
= true;
292 Any aAny
= xNode
->getDuration();
293 if( aAny
.hasValue() )
296 if( aAny
>>= eTiming
)
297 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
299 if ( bIsIndefiniteTiming
)
301 aAny
= xNode
->getEnd();
302 if( aAny
.hasValue() )
305 if( aAny
>>= eTiming
)
306 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
308 if ( bIsIndefiniteTiming
)
310 if ( !xNode
->getRepeatCount().hasValue() )
312 aAny
= xNode
->getRepeatDuration();
313 if( aAny
.hasValue() )
316 if( aAny
>>= eTiming
)
317 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
319 if ( bIsIndefiniteTiming
)
320 nFill
= AnimationFill::FREEZE
;
328 void AnimationExporter::doexport( const Reference
< XDrawPage
>& xPage
, SvStream
& rStrm
)
330 Reference
< XAnimationNodeSupplier
> xNodeSupplier( xPage
, UNO_QUERY
);
331 if( xNodeSupplier
.is() )
333 const Reference
< XAnimationNode
> xRootNode( xNodeSupplier
->getAnimationNode() );
336 processAfterEffectNodes( xRootNode
);
337 exportNode( rStrm
, xRootNode
, DFF_msofbtAnimGroup
, 1, 0, false, AnimationFill::AUTO
);
342 void AnimationExporter::processAfterEffectNodes( const Reference
< XAnimationNode
>& xRootNode
)
346 Reference
< XEnumerationAccess
> xEnumerationAccess( xRootNode
, UNO_QUERY_THROW
);
347 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), css::uno::UNO_SET_THROW
);
348 while( xEnumeration
->hasMoreElements() )
350 Reference
< XAnimationNode
> xNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
352 Reference
< XEnumerationAccess
> xEnumerationAccess2( xNode
, UNO_QUERY
);
353 if ( xEnumerationAccess2
.is() )
355 Reference
< XEnumeration
> xEnumeration2( xEnumerationAccess2
->createEnumeration(), css::uno::UNO_SET_THROW
);
356 while( xEnumeration2
->hasMoreElements() )
358 Reference
< XAnimationNode
> xChildNode( xEnumeration2
->nextElement(), UNO_QUERY_THROW
);
360 Reference
< XEnumerationAccess
> xEnumerationAccess3( xChildNode
, UNO_QUERY_THROW
);
361 Reference
< XEnumeration
> xEnumeration3( xEnumerationAccess3
->createEnumeration(), css::uno::UNO_SET_THROW
);
362 while( xEnumeration3
->hasMoreElements() )
364 Reference
< XAnimationNode
> xChildNode2( xEnumeration3
->nextElement(), UNO_QUERY_THROW
);
366 Reference
< XEnumerationAccess
> xEnumerationAccess4( xChildNode2
, UNO_QUERY_THROW
);
367 Reference
< XEnumeration
> xEnumeration4( xEnumerationAccess4
->createEnumeration(), css::uno::UNO_SET_THROW
);
368 while( xEnumeration4
->hasMoreElements() )
370 Reference
< XAnimationNode
> xChildNode3( xEnumeration4
->nextElement(), UNO_QUERY_THROW
);
372 switch( xChildNode3
->getType() )
374 // found an after effect
375 case AnimationNodeType::SET
:
376 case AnimationNodeType::ANIMATECOLOR
:
378 Reference
< XAnimationNode
> xMaster
;
380 const Sequence
< NamedValue
> aUserData( xChildNode3
->getUserData() );
381 const NamedValue
* p
= std::find_if(aUserData
.begin(), aUserData
.end(),
382 [](const NamedValue
& rProp
) { return rProp
.Name
== "master-element"; });
384 if (p
!= aUserData
.end())
385 p
->Value
>>= xMaster
;
387 AfterEffectNodePtr pAfterEffectNode
= std::make_shared
<AfterEffectNode
>( xChildNode3
, xMaster
);
388 maAfterEffectNodes
.push_back( pAfterEffectNode
);
400 TOOLS_WARN_EXCEPTION( "sd", "(@CL)AnimationExporter::processAfterEffectNodes()" );
404 bool AnimationExporter::isAfterEffectNode( const Reference
< XAnimationNode
>& xNode
) const
406 return std::any_of(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
407 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxNode
== xNode
; });
410 bool AnimationExporter::hasAfterEffectNode( const Reference
< XAnimationNode
>& xNode
, Reference
< XAnimationNode
>& xAfterEffectNode
) const
412 auto aIter
= std::find_if(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
413 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxMaster
== xNode
; });
414 if (aIter
!= maAfterEffectNodes
.end())
416 xAfterEffectNode
= (*aIter
)->mxNode
;
423 // check if this group only contain empty groups. this may happen when
424 // after effect nodes are not exported at their original position
425 bool AnimationExporter::isEmptyNode( const Reference
< XAnimationNode
>& xNode
) const
427 if( xNode
.is() ) switch( xNode
->getType() )
429 case AnimationNodeType::PAR
:
430 case AnimationNodeType::SEQ
:
431 case AnimationNodeType::ITERATE
:
433 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
434 if( xEnumerationAccess
.is() )
436 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
437 if( xEnumeration
.is() )
439 while( xEnumeration
->hasMoreElements() )
441 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
442 if( xChildNode
.is() && !isEmptyNode( xChildNode
) )
450 case AnimationNodeType::SET
:
451 case AnimationNodeType::ANIMATECOLOR
:
452 return isAfterEffectNode( xNode
);
460 void AnimationExporter::exportNode( SvStream
& rStrm
, Reference
< XAnimationNode
> const & xNode_in
, const sal_uInt16 nContainerRecType
,
461 const sal_uInt16 nInstance
, const sal_Int32 nGroupLevel
, const bool bTakeBackInteractiveSequenceTiming
, const sal_Int16 nFDef
)
463 auto xNode
= xNode_in
;
465 if( (nGroupLevel
== 4) && isEmptyNode( xNode
) )
468 if ( ( nContainerRecType
== DFF_msofbtAnimGroup
) && ( nGroupLevel
== 2 ) && isEmptyNode( xNode
) )
471 if( nContainerRecType
== DFF_msofbtAnimGroup
)
474 bool bTakeBackInteractiveSequenceTimingForChild
= false;
475 sal_Int16 nFillDefault
= GetFillMode( xNode
, nFDef
);
477 Reference
< XAnimationNode
> xAudioNode
;
478 static sal_uInt32 nAudioGroup
;
481 bool bSkipChildren
= false;
482 EscherExContainer
aContainer( rStrm
, nContainerRecType
, nInstance
);
483 switch( xNode
->getType() )
485 case AnimationNodeType::CUSTOM
:
487 exportAnimNode( rStrm
, xNode
, nFillDefault
);
488 exportAnimPropertySet( rStrm
, xNode
);
489 exportAnimEvent( rStrm
, xNode
);
490 exportAnimValue( rStrm
, xNode
, false );
494 case AnimationNodeType::PAR
:
496 exportAnimNode( rStrm
, xNode
, nFillDefault
);
497 exportAnimPropertySet( rStrm
, xNode
);
498 sal_Int32 nFlags
= nGroupLevel
== 2 ? 0x10 : 0;
499 if ( bTakeBackInteractiveSequenceTiming
)
501 exportAnimEvent( rStrm
, xNode
, nFlags
);
502 exportAnimValue( rStrm
, xNode
, nGroupLevel
== 4 );
506 case AnimationNodeType::SEQ
:
508 exportAnimNode( rStrm
, xNode
, nFillDefault
);
509 sal_Int16 nNodeType
= exportAnimPropertySet( rStrm
, xNode
);
510 sal_Int32 nFlags
= 12;
511 if ( ( nGroupLevel
== 1 ) && ( nNodeType
== css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
) )
514 bTakeBackInteractiveSequenceTimingForChild
= true;
516 exportAnimAction( rStrm
, xNode
);
517 exportAnimEvent( rStrm
, xNode
, nFlags
);
518 exportAnimValue( rStrm
, xNode
, false );
522 case AnimationNodeType::ITERATE
:
525 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
527 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
528 aAnim
.mnNodeType
= 1;
530 switch( xNode
->getRestart() )
533 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
534 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
535 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
536 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
539 switch( xNode
->getFill() )
542 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
543 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
544 case AnimationFill::FREEZE
: aAnim
.mnFill
= 2; break;
545 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
546 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
548 WriteAnimationNode( rStrm
, aAnim
);
550 exportIterate( rStrm
, xNode
);
551 exportAnimPropertySet( rStrm
, xNode
);
552 exportAnimEvent( rStrm
, xNode
);
553 exportAnimValue( rStrm
, xNode
, false );
557 case AnimationNodeType::ANIMATE
:
559 exportAnimNode( rStrm
, xNode
, nFillDefault
);
560 exportAnimPropertySet( rStrm
, xNode
);
561 exportAnimEvent( rStrm
, xNode
);
562 exportAnimValue( rStrm
, xNode
, false );
563 exportAnimate( rStrm
, xNode
);
567 case AnimationNodeType::SET
:
569 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
570 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
572 exportAnimNode( rStrm
, xNode
, nFillDefault
);
573 exportAnimPropertySet( rStrm
, xNode
);
574 exportAnimateSet( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_SET
: AFTEREFFECT_NONE
);
575 exportAnimEvent( rStrm
, xNode
);
576 exportAnimValue( rStrm
, xNode
, false );
580 bSkipChildren
= true;
585 case AnimationNodeType::ANIMATEMOTION
:
587 exportAnimNode( rStrm
, xNode
, nFillDefault
);
588 exportAnimPropertySet( rStrm
, xNode
);
589 exportAnimateMotion( rStrm
, xNode
);
590 exportAnimEvent( rStrm
, xNode
);
591 exportAnimValue( rStrm
, xNode
, false );
595 case AnimationNodeType::ANIMATECOLOR
:
597 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
598 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
600 if( bIsAfterEffectNode
)
601 xNode
= createAfterEffectNodeClone( xNode
);
603 exportAnimNode( rStrm
, xNode
, nFillDefault
);
604 exportAnimPropertySet( rStrm
, xNode
);
605 exportAnimateColor( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_COLOR
: AFTEREFFECT_NONE
);
606 exportAnimEvent( rStrm
, xNode
);
607 exportAnimValue( rStrm
, xNode
, false );
611 bSkipChildren
= true;
616 case AnimationNodeType::ANIMATETRANSFORM
:
618 exportAnimNode( rStrm
, xNode
, nFillDefault
);
619 exportAnimPropertySet( rStrm
, xNode
);
620 exportAnimateTransform( rStrm
, xNode
);
621 exportAnimEvent( rStrm
, xNode
);
622 exportAnimValue( rStrm
, xNode
, false );
626 case AnimationNodeType::TRANSITIONFILTER
:
628 exportAnimNode( rStrm
, xNode
, nFillDefault
);
629 exportAnimPropertySet( rStrm
, xNode
);
630 exportAnimEvent( rStrm
, xNode
);
631 exportAnimValue( rStrm
, xNode
, false );
632 exportTransitionFilter( rStrm
, xNode
);
636 case AnimationNodeType::AUDIO
: // #i58428#
638 exportAnimNode( rStrm
, xNode
, nFillDefault
);
639 exportAnimPropertySet( rStrm
, xNode
);
641 Reference
< XAudio
> xAudio( xNode
, UNO_QUERY
);
644 Any
aAny( xAudio
->getSource() );
647 if ( ( aAny
>>= aURL
) && !aURL
.isEmpty() )
650 sal_Int32 nTrigger
= 3;
651 sal_Int32 nU3
= nAudioGroup
;
652 sal_Int32 nBegin
= 0;
654 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 1 );
656 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
657 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
664 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 2 );
666 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
667 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
670 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
672 sal_uInt32
const nRefMode
= 3;
673 sal_uInt32
const nRefType
= 2;
674 sal_uInt32 nRefId
= mrExSoundCollection
.GetId( aURL
);
675 sal_Int32
const begin
= -1;
676 sal_Int32
const end
= -1;
678 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
679 rStrm
.WriteUInt32( nRefMode
).WriteUInt32( nRefType
).WriteUInt32( nRefId
).WriteInt32( begin
).WriteInt32( end
);
683 exportAnimValue( rStrm
, xNode
, false );
689 // export after effect node if one exists for this node
690 Reference
< XAnimationNode
> xAfterEffectNode
;
691 if( hasAfterEffectNode( xNode
, xAfterEffectNode
) )
693 exportNode( rStrm
, xAfterEffectNode
, DFF_msofbtAnimSubGoup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
696 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
697 if( xEnumerationAccess
.is() )
699 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
700 if( xEnumeration
.is() )
702 while( xEnumeration
->hasMoreElements() )
704 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
705 if( xChildNode
.is() )
707 if ( xChildNode
->getType() == AnimationNodeType::AUDIO
)
709 xAudioNode
= std::move(xChildNode
);
710 nAudioGroup
= mnCurrentGroup
;
713 exportNode( rStrm
, xChildNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
720 if ( xAudioNode
.is() )
721 exportNode( rStrm
, xAudioNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
723 if( xNode
->getType() == AnimationNodeType::ITERATE
)
727 Reference
< XAnimationNode
> AnimationExporter::createAfterEffectNodeClone( const Reference
< XAnimationNode
>& xNode
)
731 Reference
< css::util::XCloneable
> xClonable( xNode
, UNO_QUERY_THROW
);
732 Reference
< XAnimationNode
> xCloneNode( xClonable
->createClone(), UNO_QUERY_THROW
);
735 xCloneNode
->setBegin( aEmpty
);
741 OSL_FAIL("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
746 bool AnimationExporter::GetNodeType( const Reference
< XAnimationNode
>& xNode
, sal_Int16
& nType
)
748 // trying to get the nodetype
749 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
750 for( const NamedValue
& rProp
: aUserData
)
752 if ( rProp
.Name
== "node-type" )
754 if ( rProp
.Value
>>= nType
)
762 void AnimationExporter::exportAnimNode( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
,
763 const sal_Int16 nFillDefault
)
765 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
769 switch( xNode
->getRestart() )
772 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
773 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
774 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
775 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
778 switch( nFillDefault
)
781 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
782 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
783 case AnimationFill::FREEZE
:
784 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
785 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
787 // attribute Duration
788 double fDuration
= 0.0;
789 css::animations::Timing eTiming
;
790 if ( xNode
->getDuration() >>= eTiming
)
792 if ( eTiming
== Timing_INDEFINITE
)
793 aAnim
.mnDuration
= -1;
795 else if ( xNode
->getDuration() >>= fDuration
)
797 aAnim
.mnDuration
= static_cast<sal_Int32
>( fDuration
* 1000.0 );
800 aAnim
.mnDuration
= -1;
802 // NodeType, NodeGroup
803 aAnim
.mnNodeType
= 1;
804 aAnim
.mnGroupType
= mso_Anim_GroupType_SEQ
;
805 switch( xNode
->getType() )
807 case AnimationNodeType::PAR
:
808 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
810 case AnimationNodeType::SEQ
:
813 if( GetNodeType( xNode
, nType
) )
816 case css::presentation::EffectNodeType::TIMING_ROOT
: aAnim
.mnNodeType
= 0x12; break;
817 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: aAnim
.mnNodeType
= 0x18; break;
822 case AnimationNodeType::ANIMATE
:
823 case AnimationNodeType::SET
:
825 case AnimationNodeType::CUSTOM
:
826 case AnimationNodeType::ITERATE
:
827 case AnimationNodeType::ANIMATEMOTION
:
828 case AnimationNodeType::ANIMATECOLOR
:
829 case AnimationNodeType::ANIMATETRANSFORM
:
831 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
832 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
836 case AnimationNodeType::AUDIO
:
838 aAnim
.mnGroupType
= mso_Anim_GroupType_MEDIA
;
839 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
843 case AnimationNodeType::TRANSITIONFILTER
:
845 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
846 aAnim
.mnNodeType
= mso_Anim_Behaviour_FILTER
;
851 WriteAnimationNode( rStrm
, aAnim
);
854 void AnimationExporter::GetUserData( const Sequence
< NamedValue
>& rUserData
, const Any
** pAny
, std::size_t nLen
)
856 // storing user data into pAny, to allow direct access later
857 memset( pAny
, 0, nLen
);
858 if ( !rUserData
.hasElements() )
861 for( const NamedValue
& rProp
: rUserData
)
863 if ( rProp
.Name
== "node-type" )
865 pAny
[ DFF_ANIM_NODE_TYPE
] = &(rProp
.Value
);
867 else if ( rProp
.Name
== "preset-class" )
869 pAny
[ DFF_ANIM_PRESET_CLASS
] = &(rProp
.Value
);
871 else if ( rProp
.Name
== "preset-id" )
873 pAny
[ DFF_ANIM_PRESET_ID
] = &(rProp
.Value
);
875 else if ( rProp
.Name
== "preset-sub-type" )
877 pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] = &(rProp
.Value
);
879 else if ( rProp
.Name
== "master-element" )
881 pAny
[ DFF_ANIM_AFTEREFFECT
] = &(rProp
.Value
);
886 sal_uInt32
AnimationExporter::GetPresetID( std::u16string_view aPreset
, sal_uInt32 nAPIPresetClass
, bool& bPresetId
)
888 sal_uInt32 nPresetId
= 0;
891 if ( o3tl::starts_with(aPreset
, u
"ppt_") )
893 size_t nLast
= aPreset
.rfind( '_' );
894 if ( ( nLast
!= std::u16string_view::npos
) && ( ( nLast
+ 1 ) < aPreset
.size() ) )
896 std::u16string_view
aNumber( aPreset
.substr( nLast
+ 1 ) );
897 nPresetId
= o3tl::toUInt32(aNumber
);
903 const oox::ppt::preset_mapping
* p
= oox::ppt::preset_mapping::getList();
904 while( p
->mpStrPresetId
&& ((p
->mnPresetClass
!= static_cast<sal_Int32
>(nAPIPresetClass
)) || !o3tl::equalsAscii(aPreset
, p
->mpStrPresetId
)) )
907 if( p
->mpStrPresetId
)
909 nPresetId
= p
->mnPresetId
;
917 sal_Int16
AnimationExporter::exportAnimPropertySet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
919 sal_Int16 nNodeType
= css::presentation::EffectNodeType::DEFAULT
;
921 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
923 Reference
< XAnimationNode
> xMaster
;
925 Any aMasterRel
, aOverride
, aRunTimeContext
;
927 // storing user data into pAny, to allow direct access later
928 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
929 const css::uno::Any
* pAny
[ DFF_ANIM_PROPERTY_ID_COUNT
];
930 GetUserData( aUserData
, pAny
, sizeof( pAny
) );
932 if( pAny
[ DFF_ANIM_AFTEREFFECT
] )
933 ( *pAny
[ DFF_ANIM_AFTEREFFECT
] ) >>= xMaster
;
935 // calculate master-rel
938 sal_Int32 nMasterRel
= 2;
939 if( xNode
.is() && xMaster
.is() && (xNode
->getParent() == xMaster
->getParent() ) )
942 aMasterRel
<<= nMasterRel
;
944 pAny
[ DFF_ANIM_MASTERREL
] = &aMasterRel
;
946 aOverride
<<= sal_Int32(1);
947 pAny
[ DFF_ANIM_OVERRIDE
] = &aOverride
;
949 aRunTimeContext
<<= sal_Int32(1);
950 pAny
[ DFF_ANIM_RUNTIMECONTEXT
] = &aRunTimeContext
;
953 // the order is important
954 if ( pAny
[ DFF_ANIM_NODE_TYPE
] )
956 if ( *pAny
[ DFF_ANIM_NODE_TYPE
] >>= nNodeType
)
958 sal_uInt32 nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
;
961 case css::presentation::EffectNodeType::ON_CLICK
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
; break;
962 case css::presentation::EffectNodeType::WITH_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_WITH_PREVIOUS
; break;
963 case css::presentation::EffectNodeType::AFTER_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS
; break;
964 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE
; break;
965 case css::presentation::EffectNodeType::TIMING_ROOT
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_TIMING_ROOT
; break;
966 case css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ
; break;
968 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_NODE_TYPE
, nPPTNodeType
);
971 sal_uInt32 nPresetId
= 0;
972 sal_uInt32 nPresetSubType
= 0;
973 sal_uInt32 nAPIPresetClass
= EffectPresetClass::CUSTOM
;
974 sal_uInt32 nPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
975 bool bPresetClass
, bPresetId
, bPresetSubType
;
976 bPresetId
= bPresetClass
= bPresetSubType
= false;
978 if ( pAny
[ DFF_ANIM_PRESET_CLASS
] )
980 if ( *pAny
[ DFF_ANIM_PRESET_CLASS
] >>= nAPIPresetClass
)
982 sal_uInt8 nPPTPresetClass
;
983 switch( nAPIPresetClass
)
985 case EffectPresetClass::ENTRANCE
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_ENTRANCE
; break;
986 case EffectPresetClass::EXIT
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EXIT
; break;
987 case EffectPresetClass::EMPHASIS
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EMPHASIS
; break;
988 case EffectPresetClass::MOTIONPATH
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MOTIONPATH
; break;
989 case EffectPresetClass::OLEACTION
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_OLE_ACTION
; break;
990 case EffectPresetClass::MEDIACALL
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MEDIACALL
; break;
992 nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
994 nPresetClass
= nPPTPresetClass
;
998 if ( pAny
[ DFF_ANIM_PRESET_ID
] )
1001 if ( *pAny
[ DFF_ANIM_PRESET_ID
] >>= sPreset
)
1002 nPresetId
= GetPresetID( sPreset
, nAPIPresetClass
, bPresetId
);
1005 if ( pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] )
1007 OUString sPresetSubType
;
1008 if ( *pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] >>= sPresetSubType
)
1010 nPresetSubType
= TranslatePresetSubType( nPresetClass
, nPresetId
, sPresetSubType
);
1011 bPresetSubType
= true;
1015 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_ID
, nPresetId
);
1016 if ( bPresetSubType
)
1017 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_SUB_TYPE
, nPresetSubType
);
1019 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_CLASS
, nPresetClass
);
1021 if ( pAny
[ DFF_ANIM_ID
] )
1026 if ( pAny
[ DFF_ANIM_AFTEREFFECT
] )
1028 bool bAfterEffect
= false;
1029 if ( *pAny
[ DFF_ANIM_AFTEREFFECT
] >>= bAfterEffect
)
1030 exportAnimPropertyByte( rStrm
, DFF_ANIM_AFTEREFFECT
, int(bAfterEffect
) );
1033 if ( pAny
[ DFF_ANIM_RUNTIMECONTEXT
] )
1035 sal_Int32 nRunTimeContext
= 0;
1036 if ( *pAny
[ DFF_ANIM_RUNTIMECONTEXT
] >>= nRunTimeContext
)
1037 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_RUNTIMECONTEXT
, nRunTimeContext
);
1039 if ( pAny
[ DFF_ANIM_PATH_EDIT_MODE
] )
1046 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
1050 bool bDirection
= !xColor
->getDirection();
1051 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_DIRECTION
, bDirection
? 1 : 0 );
1055 if ( pAny
[ DFF_ANIM_OVERRIDE
] )
1057 sal_Int32 nOverride
= 0;
1058 if ( *pAny
[ DFF_ANIM_OVERRIDE
] >>= nOverride
)
1059 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_OVERRIDE
, nOverride
);
1062 if ( pAny
[ DFF_ANIM_MASTERREL
] )
1064 sal_Int32 nMasterRel
= 0;
1065 if ( *pAny
[ DFF_ANIM_MASTERREL
] >>= nMasterRel
)
1066 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_MASTERREL
, nMasterRel
);
1070 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1073 sal_Int16 nEndAfterSlide = 0;
1074 nEndAfterSlide = xAudio->getEndAfterSlide();
1075 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1078 Reference
< XAnimate
> xAnim( xNode
, UNO_QUERY
);
1081 // TODO: DFF_ANIM_TIMEFILTER
1083 if ( pAny
[ DFF_ANIM_EVENT_FILTER
] )
1085 // TODO DFF_ANIM_EVENT_FILTER
1087 if ( pAny
[ DFF_ANIM_VOLUME
] )
1089 // TODO DFF_ANIM_VOLUME
1094 bool AnimationExporter::exportAnimProperty( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const css::uno::Any
& rAny
, const TranslateMode eTranslateMode
)
1097 if ( rAny
.hasValue() )
1099 switch( rAny
.getValueTypeClass() )
1101 case css::uno::TypeClass_UNSIGNED_SHORT
:
1102 case css::uno::TypeClass_SHORT
:
1103 case css::uno::TypeClass_UNSIGNED_LONG
:
1104 case css::uno::TypeClass_LONG
:
1107 if ( rAny
>>= nVal
)
1109 exportAnimPropertyuInt32( rStrm
, nPropertyId
, nVal
);
1115 case css::uno::TypeClass_DOUBLE
:
1118 if ( rAny
>>= fVal
)
1120 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1125 case css::uno::TypeClass_FLOAT
:
1128 if ( rAny
>>= fVal
)
1130 if ( eTranslateMode
& TRANSLATE_NUMBER_TO_STRING
)
1132 OUString
aNumber( OUString::number( fVal
) );
1133 exportAnimPropertyString( rStrm
, nPropertyId
, aNumber
, eTranslateMode
);
1137 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1143 case css::uno::TypeClass_STRING
:
1146 if ( rAny
>>= aStr
)
1148 exportAnimPropertyString( rStrm
, nPropertyId
, aStr
, eTranslateMode
);
1159 void AnimationExporter::exportAnimPropertyString( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const OUString
& rVal
, const TranslateMode eTranslateMode
)
1161 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1162 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_UNISTRING
);
1163 OUString
aStr( rVal
);
1164 if ( eTranslateMode
!= TRANSLATE_NONE
)
1165 ImplTranslateAttribute( aStr
, eTranslateMode
);
1166 writeZString( rStrm
, aStr
);
1169 void AnimationExporter::exportAnimPropertyFloat( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const double& rVal
)
1171 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1172 float fFloat
= static_cast<float>(rVal
);
1173 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_FLOAT
)
1174 .WriteFloat( fFloat
);
1177 void AnimationExporter::exportAnimPropertyuInt32( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt32 nVal
)
1179 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1180 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_INT32
)
1181 .WriteUInt32( nVal
);
1184 void AnimationExporter::exportAnimPropertyByte( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt8 nVal
)
1186 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1187 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_BYTE
)
1188 .WriteUChar( nVal
);
1191 void AnimationExporter::writeZString( SvStream
& rStrm
, std::u16string_view aVal
)
1193 for ( size_t i
= 0; i
< aVal
.size(); i
++ )
1194 rStrm
.WriteUInt16( aVal
[ i
] );
1195 rStrm
.WriteUInt16( 0 );
1198 void AnimationExporter::exportAnimAction( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1200 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAction
);
1202 sal_Int32
const nConcurrent
= 1;
1203 sal_Int32
const nNextAction
= 1;
1204 sal_Int32 nEndSync
= 0;
1205 sal_Int32
const nU4
= 0;
1206 sal_Int32
const nU5
= 3;
1208 sal_Int16 nAnimationEndSync
= 0;
1209 if ( xNode
->getEndSync() >>= nAnimationEndSync
)
1211 if ( nAnimationEndSync
== AnimationEndSync::ALL
)
1214 rStrm
.WriteInt32( nConcurrent
)
1215 .WriteInt32( nNextAction
)
1216 .WriteInt32( nEndSync
)
1222 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1223 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1224 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
1225 void AnimationExporter::exportAnimEvent( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_Int32 nFlags
)
1228 for ( i
= 0; i
< 4; i
++ )
1231 sal_Int32 nTrigger
= 0;
1233 sal_Int32 nBegin
= 0;
1235 bool bCreateEvent
= false;
1245 css::animations::Timing eTiming
;
1248 if ( nFlags
& 0x20 )
1250 // taking the first child
1251 Reference
< XEnumerationAccess
> xEA( xNode
, UNO_QUERY_THROW
);
1252 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), css::uno::UNO_SET_THROW
);
1253 if ( xE
->hasMoreElements() )
1255 Reference
< XAnimationNode
> xClickNode( xE
->nextElement(), UNO_QUERY
);
1256 aAny
= xClickNode
->getBegin();
1259 else if ( nFlags
& 0x40 )
1261 // begin has to be replaced with void, so don't do anything
1265 aAny
= xNode
->getBegin();
1266 if ( nFlags
& 0x10 ) // replace ON_NEXT with INDEFINITE
1268 if ( ( aAny
>>= aEvent
) && ( aEvent
.Trigger
== EventTrigger::ON_NEXT
) )
1270 eTiming
= Timing_INDEFINITE
;
1277 aAny
= xNode
->getEnd();
1279 double fTiming
= 0.0;
1280 if ( aAny
>>= aEvent
)
1282 bCreateEvent
= true;
1283 switch( aEvent
.Trigger
)
1285 case EventTrigger::NONE
: nTrigger
= 0; break;
1286 case EventTrigger::ON_BEGIN
: nTrigger
= 1; break;
1287 case EventTrigger::ON_END
: nTrigger
= 2; break;
1288 case EventTrigger::BEGIN_EVENT
: nTrigger
= 3; break;
1289 case EventTrigger::END_EVENT
: nTrigger
= 4; nU1
= 2; nU3
= mnCurrentGroup
; break;
1290 case EventTrigger::ON_CLICK
: nTrigger
= 5; break;
1291 case EventTrigger::ON_DBL_CLICK
: nTrigger
= 6; break;
1292 case EventTrigger::ON_MOUSE_ENTER
: nTrigger
= 7; break;
1293 case EventTrigger::ON_MOUSE_LEAVE
: nTrigger
= 8; break;
1294 case EventTrigger::ON_NEXT
: nTrigger
= 9; break;
1295 case EventTrigger::ON_PREV
: nTrigger
= 10; break;
1296 case EventTrigger::ON_STOP_AUDIO
: nTrigger
= 11; break;
1298 if ( aEvent
.Offset
.hasValue() )
1300 if ( aEvent
.Offset
>>= eTiming
)
1302 if ( eTiming
== Timing_INDEFINITE
)
1305 else if ( aEvent
.Offset
>>= fTiming
)
1306 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1308 aSource
= aEvent
.Source
;
1310 else if ( aAny
>>= eTiming
)
1312 bCreateEvent
= true;
1313 if ( eTiming
== Timing_INDEFINITE
)
1316 else if ( aAny
>>= fTiming
)
1318 bCreateEvent
= true;
1319 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1326 if ( nFlags
& ( 1 << i
) )
1328 bCreateEvent
= true;
1336 if ( nFlags
& ( 1 << i
) )
1338 bCreateEvent
= true;
1347 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, i
+ 1 );
1349 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
1350 rStrm
.WriteInt32( nU1
)
1351 .WriteInt32( nTrigger
)
1353 .WriteInt32( nBegin
);
1355 exportAnimateTargetElement( rStrm
, aSource
, ( nFlags
& ( 1 << i
) ) != 0 );
1360 Any
AnimationExporter::convertAnimateValue( const Any
& rSourceValue
, std::u16string_view rAttributeName
)
1363 if ( rAttributeName
== u
"X"
1364 || rAttributeName
== u
"Y"
1365 || rAttributeName
== u
"Width"
1366 || rAttributeName
== u
"Height"
1370 if ( rSourceValue
>>= aStr
)
1372 ImplTranslateAttribute( aStr
, TRANSLATE_MEASURE
);
1376 else if ( rAttributeName
== u
"Rotate" // "r" or "style.rotation" ?
1377 || rAttributeName
== u
"Opacity"
1378 || rAttributeName
== u
"CharHeight"
1379 || rAttributeName
== u
"SkewX"
1382 double fNumber
= 0.0;
1383 if ( rSourceValue
>>= fNumber
)
1384 aDest
+= OUString::number( fNumber
);
1386 else if ( rAttributeName
== u
"Color"
1387 || rAttributeName
== u
"FillColor" // "Fillcolor" or "FillColor" ?
1388 || rAttributeName
== u
"LineColor"
1389 || rAttributeName
== u
"CharColor"
1392 sal_Int32 nColor
= 0;
1393 Sequence
< double > aHSL( 3 );
1394 OUString
aP( u
","_ustr
);
1395 if ( rSourceValue
>>= aHSL
)
1398 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 0 ] / ( 360.0 / 255 ) ) )
1400 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 ) )
1402 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 ) )
1405 else if ( rSourceValue
>>= nColor
)
1408 + OUString::number( static_cast<sal_Int8
>(nColor
) )
1410 + OUString::number( static_cast<sal_Int8
>( nColor
>> 8 ) )
1412 + OUString::number( static_cast<sal_Int8
>( nColor
>> 16 ) )
1416 else if ( rAttributeName
== u
"FillStyle" )
1418 css::drawing::FillStyle eFillStyle
;
1419 if ( rSourceValue
>>= eFillStyle
)
1421 if ( eFillStyle
== css::drawing::FillStyle_NONE
)
1422 aDest
+= "none"; // ?
1427 else if (rAttributeName
== u
"FillOn")
1430 if ( rSourceValue
>>= bFillOn
)
1438 else if ( rAttributeName
== u
"LineStyle" )
1440 css::drawing::LineStyle eLineStyle
;
1441 if ( rSourceValue
>>= eLineStyle
)
1443 if ( eLineStyle
== css::drawing::LineStyle_NONE
)
1449 else if ( rAttributeName
== u
"CharWeight" )
1451 float fFontWeight
= 0.0;
1452 if ( rSourceValue
>>= fFontWeight
)
1454 if ( fFontWeight
== css::awt::FontWeight::BOLD
)
1460 else if ( rAttributeName
== u
"CharUnderline" )
1462 sal_Int16 nFontUnderline
= 0;
1463 if ( rSourceValue
>>= nFontUnderline
)
1465 if ( nFontUnderline
== css::awt::FontUnderline::NONE
)
1471 else if ( rAttributeName
== u
"CharPosture" )
1473 css::awt::FontSlant eFontSlant
;
1474 if ( rSourceValue
>>= eFontSlant
)
1476 if ( eFontSlant
== css::awt::FontSlant_ITALIC
)
1479 aDest
+= "normal"; // ?
1482 else if ( rAttributeName
== u
"Visibility" )
1484 bool bVisible
= true;
1485 if ( rSourceValue
>>= bVisible
)
1494 if ( !aDest
.isEmpty() )
1497 aRet
= rSourceValue
;
1501 void AnimationExporter::exportAnimateSet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
1503 Reference
< XAnimateSet
> xSet( xNode
, UNO_QUERY
);
1507 EscherExContainer
aAnimateSet( rStrm
, DFF_msofbtAnimateSet
, 0 );
1509 EscherExAtom
aAnimateSetData( rStrm
, DFF_msofbtAnimateSetData
);
1510 sal_uInt32
const nId1
= 1; // ??
1511 sal_uInt32
const nId2
= 1; // ??
1512 rStrm
.WriteUInt32( nId1
).WriteUInt32( nId2
);
1514 Any
aConvertedValue( convertAnimateValue( xSet
->getTo(), xSet
->getAttributeName() ) );
1515 if ( aConvertedValue
.hasValue() )
1516 exportAnimProperty( rStrm
, 1, aConvertedValue
, TRANSLATE_NONE
);
1517 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
1520 sal_uInt32
AnimationExporter::GetValueTypeForAttributeName( std::u16string_view rAttributeName
)
1522 sal_uInt32 nValueType
= 0;
1529 static const Entry lcl_attributeMap
[] =
1532 { "charfontname", 0 },
1533 { "charheight", 1 },
1534 { "charposture", 0 },
1535 // TODO(Q1): This should prolly be changed in PPT import
1536 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1537 { "charrotation", 1 },
1538 { "charunderline", 0 },
1539 { "charweight", 0 },
1551 { "visibility", 1 },
1557 const Entry
* pPtr
= &lcl_attributeMap
[ 0 ];
1558 while( pPtr
->pName
)
1560 if ( o3tl::equalsIgnoreAsciiCase( rAttributeName
, pPtr
->pName
) )
1562 nValueType
= pPtr
->nType
;
1567 DBG_ASSERT( pPtr
->pName
, "GetValueTypeForAttributeName, unknown property value!" );
1571 void AnimationExporter::exportAnimate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1573 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1574 if ( !xAnimate
.is() )
1577 Any
aBy ( xAnimate
->getBy() );
1578 Any
aFrom( xAnimate
->getFrom() );
1579 Any
aTo ( xAnimate
->getTo() );
1581 EscherExContainer
aContainer( rStrm
, DFF_msofbtAnimate
, 0 );
1583 EscherExAtom
aAnimateData( rStrm
, DFF_msofbtAnimateData
);
1584 sal_uInt32 nBits
= 0x38;
1585 sal_Int16 nTmp
= xAnimate
->getCalcMode();
1586 sal_uInt32 nCalcMode
= /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp
== AnimationCalcMode::LINEAR
) ? 1 : 0;
1587 sal_uInt32 nValueType
= GetValueTypeForAttributeName( xAnimate
->getAttributeName() );
1589 if ( aBy
.hasValue() )
1591 if ( aFrom
.hasValue() )
1593 if ( aTo
.hasValue() )
1596 rStrm
.WriteUInt32( nCalcMode
)
1597 .WriteUInt32( nBits
)
1598 .WriteUInt32( nValueType
);
1600 if ( aBy
.hasValue() )
1601 exportAnimProperty( rStrm
, 1, aBy
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1602 if ( aFrom
.hasValue() )
1603 exportAnimProperty( rStrm
, 2, aFrom
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1604 if ( aTo
.hasValue() )
1605 exportAnimProperty( rStrm
, 3, aTo
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1607 exportAnimateKeyPoints( rStrm
, xAnimate
);
1608 exportAnimateTarget( rStrm
, xNode
);
1611 void AnimationExporter::exportAnimateTarget( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_uInt32 nForceAttributeNames
, int nAfterEffectType
)
1613 EscherExContainer
aAnimateTarget( rStrm
, DFF_msofbtAnimateTarget
, 0 );
1614 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1615 if ( !xAnimate
.is() )
1619 EscherExAtom
aAnimateTargetSettings( rStrm
, DFF_msofbtAnimateTargetSettings
, 0 );
1620 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1621 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1622 // nAccumulate 0 = none, 1 = always
1623 // nTransformType 0: "property" else "image"
1624 sal_uInt32 nBits
= 0;
1625 sal_uInt32 nAdditive
= 0;
1626 sal_uInt32 nAccumulate
= 0;
1627 sal_uInt32
const nTransformType
= 0;
1628 if ( xAnimate
.is() )
1630 if ( !xAnimate
->getAttributeName().isEmpty() )
1631 nBits
|= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1632 sal_Int16 nAdditiveMode
= xAnimate
->getAdditive();
1633 if ( nAdditiveMode
!= AnimationAdditiveMode::BASE
)
1636 switch( nAdditiveMode
)
1638 case AnimationAdditiveMode::SUM
: nAdditive
= 1; break;
1639 case AnimationAdditiveMode::REPLACE
: nAdditive
= 2; break;
1640 case AnimationAdditiveMode::MULTIPLY
: nAdditive
= 3; break;
1641 case AnimationAdditiveMode::NONE
: nAdditive
= 4; break;
1644 if ( xAnimate
->getAccumulate() )
1650 rStrm
.WriteUInt32( nBits
)
1651 .WriteUInt32( nAdditive
)
1652 .WriteUInt32( nAccumulate
)
1653 .WriteUInt32( nTransformType
);
1655 if ( !xAnimate
->getAttributeName().isEmpty() || nForceAttributeNames
)
1657 EscherExContainer
aAnimateAttributeNames( rStrm
, DFF_msofbtAnimateAttributeNames
, 1 );
1658 OUString
aAttributeName( xAnimate
->getAttributeName() );
1659 if ( nForceAttributeNames
)
1661 if( nForceAttributeNames
== 1 )
1663 aAttributeName
= "r";
1666 sal_Int32 nIndex
= 0;
1669 OUString
aToken( aAttributeName
.getToken( 0, ';', nIndex
) );
1670 exportAnimPropertyString( rStrm
, 0, aToken
, TRANSLATE_ATTRIBUTE
);
1672 while ( nIndex
>= 0 );
1675 if( nAfterEffectType
!= AFTEREFFECT_NONE
)
1677 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
1678 exportAnimPropertyuInt32( rStrm
, 6, 1 );
1679 if( nAfterEffectType
== AFTEREFFECT_COLOR
)
1681 exportAnimPropertyuInt32( rStrm
, 4, 0 );
1682 exportAnimPropertyuInt32( rStrm
, 5, 0 );
1685 exportAnimateTargetElement( rStrm
, aTarget
.hasValue() ? aTarget
: xAnimate
->getTarget(), false );
1688 Reference
< XShape
> AnimationExporter::getTargetElementShape( const Any
& rAny
, sal_Int32
& rBegin
, sal_Int32
& rEnd
, bool& rParagraphTarget
)
1690 Reference
< XShape
> xShape
;
1693 rParagraphTarget
= false;
1698 ParagraphTarget aParaTarget
;
1699 if( rAny
>>= aParaTarget
)
1700 xShape
= aParaTarget
.Shape
;
1704 // now calculating the character range for the paragraph
1705 sal_Int16 nParagraph
= aParaTarget
.Paragraph
;
1706 Reference
< XSimpleText
> xText( xShape
, UNO_QUERY
);
1710 rParagraphTarget
= true;
1711 Reference
< XEnumerationAccess
> xTextParagraphEnumerationAccess( xText
, UNO_QUERY
);
1712 if ( !xTextParagraphEnumerationAccess
.is() )
1715 Reference
< XEnumeration
> xTextParagraphEnumeration( xTextParagraphEnumerationAccess
->createEnumeration() );
1716 if ( !xTextParagraphEnumeration
.is() )
1719 sal_Int16 nCurrentParagraph
;
1720 rBegin
= rEnd
= nCurrentParagraph
= 0;
1721 while ( xTextParagraphEnumeration
->hasMoreElements() )
1723 Reference
< XTextRange
> xTextRange( xTextParagraphEnumeration
->nextElement(), UNO_QUERY
);
1724 if ( xTextRange
.is() )
1726 OUString
aParaText( xTextRange
->getString() );
1727 sal_Int32 nLength
= aParaText
.getLength() + 1;
1729 if ( nCurrentParagraph
== nParagraph
)
1731 nCurrentParagraph
++;
1739 void AnimationExporter::exportAnimateTargetElement( SvStream
& rStrm
, const Any
& rAny
, const bool bCreate2b01Atom
)
1741 sal_uInt32 nRefMode
= 0; // nRefMode == 2 -> Paragraph
1742 sal_Int32 begin
= -1;
1744 bool bParagraphTarget
;
1746 Reference
< XShape
> xShape
= getTargetElementShape(rAny
, begin
, end
, bParagraphTarget
);
1748 if( bParagraphTarget
)
1751 if ( !(xShape
.is() || bCreate2b01Atom
) )
1754 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
1757 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
1759 sal_uInt32
const nRefType
= 1; // TODO: nRefType == 2 -> Sound;
1760 sal_uInt32 nRefId
= mrSolverContainer
.GetShapeId( xShape
);
1762 rStrm
.WriteUInt32( nRefMode
)
1763 .WriteUInt32( nRefType
)
1764 .WriteUInt32( nRefId
)
1765 .WriteInt32( begin
)
1768 if ( bCreate2b01Atom
)
1770 EscherExAtom
a2b01Atom( rStrm
, 0x2b01 );
1771 rStrm
.WriteUInt32( 1 ); // ?
1775 void AnimationExporter::exportAnimateKeyPoints( SvStream
& rStrm
, const Reference
< XAnimate
>& xAnimate
)
1777 Sequence
< double > aKeyTimes( xAnimate
->getKeyTimes() );
1778 Sequence
< Any
> aValues( xAnimate
->getValues() );
1779 OUString
aFormula( xAnimate
->getFormula() );
1780 if ( !aKeyTimes
.hasElements() )
1783 EscherExContainer
aAnimKeyPoints( rStrm
, DFF_msofbtAnimKeyPoints
);
1785 for ( i
= 0; i
< aKeyTimes
.getLength(); i
++ )
1788 EscherExAtom
aAnimKeyTime( rStrm
, DFF_msofbtAnimKeyTime
);
1789 sal_Int32 nKeyTime
= static_cast<sal_Int32
>( aKeyTimes
[ i
] * 1000.0 );
1790 rStrm
.WriteInt32( nKeyTime
);
1793 if ( aValues
[ i
].hasValue() )
1796 if ( aValues
[ i
] >>= aPair
)
1798 aAny
[ 0 ] = convertAnimateValue( aPair
.First
, xAnimate
->getAttributeName() );
1799 aAny
[ 1 ] = convertAnimateValue( aPair
.Second
, xAnimate
->getAttributeName() );
1803 aAny
[ 0 ] = convertAnimateValue( aValues
[ i
], xAnimate
->getAttributeName() );
1805 if ( !i
&& !aFormula
.isEmpty() )
1807 ImplTranslateAttribute( aFormula
, TRANSLATE_MEASURE
);
1808 aAny
[ 1 ] <<= aFormula
;
1810 exportAnimProperty( rStrm
, 0, aAny
[ 0 ], TRANSLATE_NONE
);
1811 exportAnimProperty( rStrm
, 1, aAny
[ 1 ], TRANSLATE_NONE
);
1816 void AnimationExporter::exportAnimValue( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const bool bExportAlways
)
1820 double fRepeat
= 0.0;
1821 float fRepeatCount
= 0.0;
1822 css::animations::Timing eTiming
;
1823 aAny
= xNode
->getRepeatCount();
1824 if ( aAny
>>= eTiming
)
1826 if ( eTiming
== Timing_INDEFINITE
)
1827 fRepeatCount
= (float(3.40282346638528860e+38));
1829 else if ( aAny
>>= fRepeat
)
1830 fRepeatCount
= static_cast<float>(fRepeat
);
1831 if ( fRepeatCount
!= 0.0 )
1833 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1834 sal_uInt32
const nType
= 0;
1835 rStrm
.WriteUInt32( nType
)
1836 .WriteFloat( fRepeatCount
);
1839 float fAccelerate
= static_cast<float>(xNode
->getAcceleration());
1840 if ( bExportAlways
|| ( fAccelerate
!= 0.0 ) )
1842 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1843 sal_uInt32
const nType
= 3;
1844 rStrm
.WriteUInt32( nType
)
1845 .WriteFloat( fAccelerate
);
1849 float fDecelerate
= static_cast<float>(xNode
->getDecelerate());
1850 if ( bExportAlways
|| ( fDecelerate
!= 0.0 ) )
1852 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1853 sal_uInt32
const nType
= 4;
1854 rStrm
.WriteUInt32( nType
)
1855 .WriteFloat( fDecelerate
);
1859 bool bAutoReverse
= xNode
->getAutoReverse();
1860 if ( bExportAlways
|| bAutoReverse
)
1862 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1863 sal_uInt32
const nType
= 5;
1864 sal_uInt32 nVal
= bAutoReverse
? 1 : 0;
1865 rStrm
.WriteUInt32( nType
)
1866 .WriteUInt32( nVal
);
1870 void AnimationExporter::exportTransitionFilter( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1872 Reference
< XTransitionFilter
> xFilter( xNode
, UNO_QUERY
);
1873 if ( !xFilter
.is() )
1876 EscherExContainer
aAnimateFilter( rStrm
, DFF_msofbtAnimateFilter
);
1878 EscherExAtom
aAnimateFilterData( rStrm
, DFF_msofbtAnimateFilterData
);
1879 sal_uInt32
const nBits
= 3; // bit 0 -> use AnimAttributeValue
1880 // bit 1 -> use nTransition
1882 sal_uInt32 nTransition
= xFilter
->getMode() ? 0 : 1;
1883 rStrm
.WriteUInt32( nBits
)
1884 .WriteUInt32( nTransition
);
1886 const char* pFilter
= FindTransitionName( xFilter
->getTransition(), xFilter
->getSubtype(), xFilter
->getDirection() );
1889 const OUString
aStr( OUString::createFromAscii( pFilter
) );
1890 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1892 exportAnimateTarget( rStrm
, xNode
);
1895 void AnimationExporter::exportAnimateMotion( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1897 Reference
< XAnimateMotion
> xMotion( xNode
, UNO_QUERY
);
1898 if ( !xMotion
.is() )
1901 EscherExContainer
aAnimateMotion( rStrm
, DFF_msofbtAnimateMotion
);
1903 { //SJ: Ignored from import filter
1904 EscherExAtom
aAnimateMotionData( rStrm
, DFF_msofbtAnimateMotionData
);
1905 sal_uInt32
const nBits
= 0x98;
1906 sal_uInt32
const nOrigin
= 0x2;
1907 float const fByX
= 100.0; // nBits&1
1908 float const fByY
= 100.0; // nBits&1
1909 float const fFromX
= 0.0; // nBits&2
1910 float const fFromY
= 0.0; // nBits&2
1911 float const fToX
= 100.0; // nBits&4
1912 float const fToY
= 100.0; // nBits&4
1913 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nOrigin
);
1917 if ( xMotion
->getPath() >>= aStr
)
1919 if ( !aStr
.isEmpty() )
1920 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1922 exportAnimateTarget( rStrm
, xNode
);
1926 void AnimationExporter::exportAnimateTransform( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1928 Reference
< XAnimateTransform
> xTransform( xNode
, UNO_QUERY
);
1929 if ( !xTransform
.is() )
1932 if ( xTransform
->getTransformType() == AnimationTransformType::SCALE
)
1934 EscherExContainer
aAnimateScale( rStrm
, DFF_msofbtAnimateScale
);
1936 EscherExAtom
aAnimateScaleData( rStrm
, DFF_msofbtAnimateScaleData
);
1937 sal_uInt32 nBits
= 0;
1938 sal_uInt32
const nZoomContents
= 1;
1946 double fX
= 0.0, fY
= 0.0;
1948 if ( xTransform
->getBy() >>= aPair
)
1950 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1953 fByX
= static_cast<float>( fX
* 100 );
1954 fByY
= static_cast<float>( fY
* 100 );
1957 if ( xTransform
->getFrom() >>= aPair
)
1959 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1962 fFromX
= static_cast<float>( fX
* 100 );
1963 fFromY
= static_cast<float>( fY
* 100 );
1966 if( xTransform
->getTo() >>= aPair
)
1968 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1971 fToX
= static_cast<float>( fX
* 100 );
1972 fToY
= static_cast<float>( fY
* 100 );
1976 // TODO: ZoomContents:
1978 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
1980 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nZoomContents
);
1982 exportAnimateTarget( rStrm
, xNode
);
1984 else if ( xTransform
->getTransformType() == AnimationTransformType::ROTATE
)
1986 EscherExContainer
aAnimateRotation( rStrm
, DFF_msofbtAnimateRotation
);
1988 EscherExAtom
aAnimateRotationData( rStrm
, DFF_msofbtAnimateRotationData
);
1989 sal_uInt32 nBits
= 0;
1990 sal_uInt32
const nU1
= 0;
1996 if ( xTransform
->getBy() >>= fVal
)
1999 fBy
= static_cast<float>(fVal
);
2001 if ( xTransform
->getFrom() >>= fVal
)
2004 fFrom
= static_cast<float>(fVal
);
2006 if ( xTransform
->getTo() >>= fVal
)
2009 fTo
= static_cast<float>(fVal
);
2011 rStrm
.WriteUInt32( nBits
).WriteFloat( fBy
).WriteFloat( fFrom
).WriteFloat( fTo
).WriteUInt32( nU1
);
2013 exportAnimateTarget( rStrm
, xNode
, 1 );
2017 bool AnimationExporter::getColorAny( const Any
& rAny
, const sal_Int16 nColorSpace
, sal_Int32
& rMode
, sal_Int32
& rA
, sal_Int32
& rB
, sal_Int32
& rC
)
2019 bool bIsColor
= true;
2022 if ( nColorSpace
== AnimationColorSpace::HSL
)
2025 sal_Int32 nColor
= 0;
2026 Sequence
< double > aHSL( 3 );
2027 if ( rAny
>>= nColor
) // RGB color
2029 rA
= static_cast<sal_uInt8
>( nColor
>> 16 );
2030 rB
= static_cast<sal_uInt8
>( nColor
>> 8 );
2031 rC
= static_cast<sal_uInt8
>(nColor
);
2033 else if ( rAny
>>= aHSL
) // HSL
2035 rA
= static_cast<sal_Int32
>( aHSL
[ 0 ] * 255.0 / 360.0 );
2036 rB
= static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 );
2037 rC
= static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 );
2044 void AnimationExporter::exportAnimateColor( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
2046 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
2050 EscherExContainer
aAnimateColor( rStrm
, DFF_msofbtAnimateColor
);
2052 EscherExAtom
aAnimateColorData( rStrm
, DFF_msofbtAnimateColorData
);
2053 sal_uInt32 nBits
= 8;
2055 sal_Int32 nByMode
, nByA
, nByB
, nByC
;
2056 nByMode
= nByA
= nByB
= nByC
= 0;
2058 sal_Int32 nFromMode
, nFromA
, nFromB
, nFromC
;
2059 nFromMode
= nFromA
= nFromB
= nFromC
= 0;
2061 sal_Int32 nToMode
, nToA
, nToB
, nToC
;
2062 nToMode
= nToA
= nToB
= nToC
= 0;
2064 sal_Int16 nColorSpace
= xColor
->getColorInterpolation();
2066 Any
aAny( xColor
->getBy() );
2067 if ( aAny
.hasValue() )
2069 if ( getColorAny( aAny
, nColorSpace
, nByMode
, nByA
, nByB
, nByC
) )
2072 aAny
= xColor
->getFrom();
2073 if ( aAny
.hasValue() )
2075 if ( getColorAny( aAny
, nColorSpace
, nFromMode
, nFromA
, nFromB
, nFromC
) )
2078 aAny
= xColor
->getTo();
2079 if ( aAny
.hasValue() )
2081 if ( getColorAny( aAny
, nColorSpace
, nToMode
, nToA
, nToB
, nToC
) )
2084 rStrm
.WriteUInt32( nBits
)
2085 .WriteInt32( nByMode
).WriteInt32( nByA
).WriteInt32( nByB
).WriteInt32( nByC
)
2086 .WriteInt32( nFromMode
).WriteInt32( nFromA
).WriteInt32( nFromB
).WriteInt32( nFromC
)
2087 .WriteInt32( nToMode
).WriteInt32( nToA
).WriteInt32( nToB
).WriteInt32( nToC
);
2089 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
2092 void AnimationExporter::exportIterate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
2094 Reference
< XIterateContainer
> xIterate( xNode
, UNO_QUERY
);
2095 if ( !xIterate
.is() )
2098 EscherExAtom
aAnimIteration( rStrm
, DFF_msofbtAnimIteration
);
2100 float fInterval
= 10.0;
2101 sal_Int32 nTextUnitEffect
= 0;
2102 sal_Int32
const nU1
= 1;
2103 sal_Int32
const nU2
= 1;
2104 sal_Int32
const nU3
= 0xe;
2106 sal_Int16 nIterateType
= xIterate
->getIterateType();
2107 switch( nIterateType
)
2109 case TextAnimationType::BY_WORD
: nTextUnitEffect
= 1; break;
2110 case TextAnimationType::BY_LETTER
: nTextUnitEffect
= 2; break;
2113 fInterval
= static_cast<float>(xIterate
->getIterateInterval());
2115 // convert interval from absolute to percentage
2116 double fDuration
= 0.0;
2118 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
2119 if( xEnumerationAccess
.is() )
2121 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
2122 if( xEnumeration
.is() )
2124 while( xEnumeration
->hasMoreElements() )
2126 Reference
< XAnimate
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
2127 if( xChildNode
.is() )
2129 double fChildBegin
= 0.0;
2130 double fChildDuration
= 0.0;
2131 xChildNode
->getBegin() >>= fChildBegin
;
2132 xChildNode
->getDuration() >>= fChildDuration
;
2134 fChildDuration
+= fChildBegin
;
2135 if( fChildDuration
> fDuration
)
2136 fDuration
= fChildDuration
;
2143 fInterval
= static_cast<float>(100.0 * fInterval
/ fDuration
);
2145 rStrm
.WriteFloat( fInterval
).WriteInt32( nTextUnitEffect
).WriteInt32( nU1
).WriteInt32( nU2
).WriteInt32( nU3
);
2146 aTarget
= xIterate
->getTarget();
2151 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */