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/awt/FontWeight.hpp>
45 #include <com/sun/star/awt/FontUnderline.hpp>
46 #include <com/sun/star/awt/FontSlant.hpp>
47 #include <com/sun/star/container/XEnumerationAccess.hpp>
48 #include <com/sun/star/presentation/ParagraphTarget.hpp>
49 #include <com/sun/star/text/XSimpleText.hpp>
50 #include <com/sun/star/animations/XIterateContainer.hpp>
51 #include <com/sun/star/presentation/TextAnimationType.hpp>
53 #include <oox/ppt/pptfilterhelpers.hxx>
54 #include "pptexanimations.hxx"
55 #include "pptexsoundcollection.hxx"
56 #include "../ppt/pptanimations.hxx"
57 #include <filter/msfilter/escherex.hxx>
58 #include <osl/diagnose.h>
59 #include <tools/debug.hxx>
63 using ::com::sun::star::uno::Any
;
64 using ::com::sun::star::util::XCloneable
;
65 using ::com::sun::star::uno::Reference
;
66 using ::com::sun::star::uno::UNO_QUERY
;
67 using ::com::sun::star::uno::UNO_QUERY_THROW
;
68 using ::com::sun::star::uno::Sequence
;
69 using ::com::sun::star::uno::Exception
;
70 using ::com::sun::star::beans::NamedValue
;
71 using ::com::sun::star::container::XEnumerationAccess
;
72 using ::com::sun::star::container::XEnumeration
;
74 using namespace ::com::sun::star::text
;
75 using namespace ::com::sun::star::drawing
;
76 using namespace ::com::sun::star::animations
;
77 using namespace ::com::sun::star::presentation
;
82 static void ImplTranslateAttribute( OUString
& rString
, const TranslateMode eTranslateMode
)
84 if ( eTranslateMode
== TRANSLATE_NONE
)
87 if ( ( eTranslateMode
& TRANSLATE_VALUE
) || ( eTranslateMode
& TRANSLATE_ATTRIBUTE
) )
89 const oox::ppt::ImplAttributeNameConversion
* p
= oox::ppt::getAttributeConversionList();
92 if( rString
.equalsAscii( p
->mpAPIName
) )
98 if ( eTranslateMode
& TRANSLATE_VALUE
)
101 rString
+= OUString::createFromAscii( p
->mpMSName
);
104 rString
= OUString::createFromAscii( p
->mpMSName
);
107 else if ( eTranslateMode
& TRANSLATE_MEASURE
)
109 const sal_Char
* pDest
[] = { "#ppt_x", "#ppt_y", "#ppt_w", "#ppt_h", nullptr };
110 const sal_Char
* pSource
[] = { "x", "y", "width", "height", nullptr };
111 sal_Int32 nIndex
= 0;
113 const sal_Char
** ps
= pSource
;
114 const sal_Char
** pd
= pDest
;
118 const OUString
aSearch( OUString::createFromAscii( *ps
) );
119 while( (nIndex
= rString
.indexOf( aSearch
, nIndex
)) != -1 )
121 sal_Int32 nLength
= aSearch
.getLength();
122 if( nIndex
&& ( rString
[nIndex
-1] == '#' ) )
128 const OUString
aNew( OUString::createFromAscii( *pd
) );
129 rString
= rString
.replaceAt( nIndex
, nLength
, aNew
);
130 nIndex
+= aNew
.getLength();
138 sal_uInt32
AnimationExporter::TranslatePresetSubType( const sal_uInt32 nPresetClass
, const sal_uInt32 nPresetId
, const OUString
& rPresetSubType
)
140 sal_uInt32 nPresetSubType
= 0;
141 bool bTranslated
= false;
143 if ( ( nPresetClass
== sal_uInt32(EffectPresetClass::ENTRANCE
) ) || ( nPresetClass
== sal_uInt32(EffectPresetClass::EXIT
) ) )
145 if ( nPresetId
!= 21 )
151 if ( rPresetSubType
== "downward" )
156 else if ( rPresetSubType
== "across" )
165 if ( rPresetSubType
== "across" )
174 if ( rPresetSubType
== "right-to-top" )
179 else if ( rPresetSubType
== "right-to-bottom" )
184 else if ( rPresetSubType
== "left-to-top" )
189 else if ( rPresetSubType
== "left-to-bottom" )
200 const oox::ppt::convert_subtype
* p
= oox::ppt::convert_subtype::getList();
201 while( p
->mpStrSubType
)
203 if ( rPresetSubType
.equalsAscii( p
->mpStrSubType
) )
205 nPresetSubType
= p
->mnID
;
214 nPresetSubType
= static_cast<sal_uInt32
>(rPresetSubType
.toInt32());
215 return nPresetSubType
;
218 const sal_Char
* AnimationExporter::FindTransitionName( const sal_Int16 nType
, const sal_Int16 nSubType
, const bool bDirection
)
220 const sal_Char
* pRet
= nullptr;
223 const oox::ppt::transition
* p
= oox::ppt::transition::getList();
227 if ( nType
== p
->mnType
)
229 if ( nSubType
== p
->mnSubType
)
231 if ( bDirection
== p
->mbDirection
)
238 if ( nFit
== 7 ) // maximum
245 SvStream
& WriteAnimationNode(SvStream
& rOut
, AnimationNode
const & rNode
)
247 rOut
.WriteInt32( rNode
.mnU1
);
248 rOut
.WriteInt32( rNode
.mnRestart
);
249 rOut
.WriteInt32( rNode
.mnGroupType
);
250 rOut
.WriteInt32( rNode
.mnFill
);
251 rOut
.WriteInt32( rNode
.mnU3
);
252 rOut
.WriteInt32( rNode
.mnU4
);
253 rOut
.WriteInt32( rNode
.mnDuration
);
254 rOut
.WriteInt32( rNode
.mnNodeType
);
259 AnimationExporter::AnimationExporter( const EscherSolverContainer
& rSolverContainer
, ppt::ExSoundCollection
& rExSoundCollection
) :
260 mrSolverContainer ( rSolverContainer
),
261 mrExSoundCollection ( rExSoundCollection
),
266 sal_Int16
AnimationExporter::GetFillMode( const Reference
< XAnimationNode
>& xNode
, const sal_Int16 nFillDefault
)
268 sal_Int16 nFill
= xNode
->getFill();
269 //#i119699 <Animation> The animation effect "Emphasis->FlashBulb" play incorrectly in Aoo saves a .ppt to another .ppt and plays the saved one.
270 //#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.
271 if ((xNode
->getType() == AnimationNodeType::ANIMATE
)
272 ||(xNode
->getType() == AnimationNodeType::SET
)
273 ||(xNode
->getType() == AnimationNodeType::TRANSITIONFILTER
))
275 if ( nFill
== AnimationFill::DEFAULT
)
279 if ( nFill
== AnimationFill::DEFAULT
)
281 nFill
= nFillDefault
;
283 if( nFill
== AnimationFill::AUTO
)
285 nFill
= AnimationFill::REMOVE
;
286 bool bIsIndefiniteTiming
= true;
287 Any aAny
= xNode
->getDuration();
288 if( aAny
.hasValue() )
291 if( aAny
>>= eTiming
)
292 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
294 if ( bIsIndefiniteTiming
)
296 aAny
= xNode
->getEnd();
297 if( aAny
.hasValue() )
300 if( aAny
>>= eTiming
)
301 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
303 if ( bIsIndefiniteTiming
)
305 if ( !xNode
->getRepeatCount().hasValue() )
307 aAny
= xNode
->getRepeatDuration();
308 if( aAny
.hasValue() )
311 if( aAny
>>= eTiming
)
312 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
314 if ( bIsIndefiniteTiming
)
315 nFill
= AnimationFill::FREEZE
;
323 void AnimationExporter::doexport( const Reference
< XDrawPage
>& xPage
, SvStream
& rStrm
)
325 Reference
< XAnimationNodeSupplier
> xNodeSupplier( xPage
, UNO_QUERY
);
326 if( xNodeSupplier
.is() )
328 const Reference
< XAnimationNode
> xRootNode( xNodeSupplier
->getAnimationNode() );
331 processAfterEffectNodes( xRootNode
);
332 exportNode( rStrm
, xRootNode
, DFF_msofbtAnimGroup
, 1, 0, false, AnimationFill::AUTO
);
337 void AnimationExporter::processAfterEffectNodes( const Reference
< XAnimationNode
>& xRootNode
)
341 Reference
< XEnumerationAccess
> xEnumerationAccess( xRootNode
, UNO_QUERY_THROW
);
342 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), css::uno::UNO_SET_THROW
);
343 while( xEnumeration
->hasMoreElements() )
345 Reference
< XAnimationNode
> xNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
347 Reference
< XEnumerationAccess
> xEnumerationAccess2( xNode
, UNO_QUERY
);
348 if ( xEnumerationAccess2
.is() )
350 Reference
< XEnumeration
> xEnumeration2( xEnumerationAccess2
->createEnumeration(), css::uno::UNO_SET_THROW
);
351 while( xEnumeration2
->hasMoreElements() )
353 Reference
< XAnimationNode
> xChildNode( xEnumeration2
->nextElement(), UNO_QUERY_THROW
);
355 Reference
< XEnumerationAccess
> xEnumerationAccess3( xChildNode
, UNO_QUERY_THROW
);
356 Reference
< XEnumeration
> xEnumeration3( xEnumerationAccess3
->createEnumeration(), css::uno::UNO_SET_THROW
);
357 while( xEnumeration3
->hasMoreElements() )
359 Reference
< XAnimationNode
> xChildNode2( xEnumeration3
->nextElement(), UNO_QUERY_THROW
);
361 Reference
< XEnumerationAccess
> xEnumerationAccess4( xChildNode2
, UNO_QUERY_THROW
);
362 Reference
< XEnumeration
> xEnumeration4( xEnumerationAccess4
->createEnumeration(), css::uno::UNO_SET_THROW
);
363 while( xEnumeration4
->hasMoreElements() )
365 Reference
< XAnimationNode
> xChildNode3( xEnumeration4
->nextElement(), UNO_QUERY_THROW
);
367 switch( xChildNode3
->getType() )
369 // found an after effect
370 case AnimationNodeType::SET
:
371 case AnimationNodeType::ANIMATECOLOR
:
373 Reference
< XAnimationNode
> xMaster
;
375 Sequence
< NamedValue
> aUserData( xChildNode3
->getUserData() );
376 sal_Int32 nLength
= aUserData
.getLength();
377 const NamedValue
* p
= aUserData
.getConstArray();
381 if ( p
->Name
== "master-element" )
383 p
->Value
>>= xMaster
;
389 AfterEffectNodePtr
pAfterEffectNode( new AfterEffectNode( xChildNode3
, xMaster
) );
390 maAfterEffectNodes
.push_back( pAfterEffectNode
);
402 OSL_FAIL( "(@CL)AnimationExporter::processAfterEffectNodes(), exception caught!" );
406 bool AnimationExporter::isAfterEffectNode( const Reference
< XAnimationNode
>& xNode
) const
408 return std::any_of(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
409 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxNode
== xNode
; });
412 bool AnimationExporter::hasAfterEffectNode( const Reference
< XAnimationNode
>& xNode
, Reference
< XAnimationNode
>& xAfterEffectNode
) const
414 auto aIter
= std::find_if(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
415 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxMaster
== xNode
; });
416 if (aIter
!= maAfterEffectNodes
.end())
418 xAfterEffectNode
= (*aIter
)->mxNode
;
425 // check if this group only contain empty groups. this may happen when
426 // after effect nodes are not exported at theire original position
427 bool AnimationExporter::isEmptyNode( const Reference
< XAnimationNode
>& xNode
) const
429 if( xNode
.is() ) switch( xNode
->getType() )
431 case AnimationNodeType::PAR
:
432 case AnimationNodeType::SEQ
:
433 case AnimationNodeType::ITERATE
:
435 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
436 if( xEnumerationAccess
.is() )
438 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
439 if( xEnumeration
.is() )
441 while( xEnumeration
->hasMoreElements() )
443 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
444 if( xChildNode
.is() && !isEmptyNode( xChildNode
) )
452 case AnimationNodeType::SET
:
453 case AnimationNodeType::ANIMATECOLOR
:
454 return isAfterEffectNode( xNode
);
462 void AnimationExporter::exportNode( SvStream
& rStrm
, Reference
< XAnimationNode
> const & xNode_in
, const sal_uInt16 nContainerRecType
,
463 const sal_uInt16 nInstance
, const sal_Int32 nGroupLevel
, const bool bTakeBackInteractiveSequenceTiming
, const sal_Int16 nFDef
)
465 auto xNode
= xNode_in
;
467 if( (nGroupLevel
== 4) && isEmptyNode( xNode
) )
470 if ( ( nContainerRecType
== DFF_msofbtAnimGroup
) && ( nGroupLevel
== 2 ) && isEmptyNode( xNode
) )
473 if( nContainerRecType
== DFF_msofbtAnimGroup
)
476 bool bTakeBackInteractiveSequenceTimingForChild
= false;
477 sal_Int16 nFillDefault
= GetFillMode( xNode
, nFDef
);
479 Reference
< XAnimationNode
> xAudioNode
;
480 static sal_uInt32 nAudioGroup
;
483 bool bSkipChildren
= false;
484 EscherExContainer
aContainer( rStrm
, nContainerRecType
, nInstance
);
485 switch( xNode
->getType() )
487 case AnimationNodeType::CUSTOM
:
489 exportAnimNode( rStrm
, xNode
, nFillDefault
);
490 exportAnimPropertySet( rStrm
, xNode
);
491 exportAnimEvent( rStrm
, xNode
);
492 exportAnimValue( rStrm
, xNode
, false );
496 case AnimationNodeType::PAR
:
498 exportAnimNode( rStrm
, xNode
, nFillDefault
);
499 exportAnimPropertySet( rStrm
, xNode
);
500 sal_Int32 nFlags
= nGroupLevel
== 2 ? 0x10 : 0;
501 if ( bTakeBackInteractiveSequenceTiming
)
503 exportAnimEvent( rStrm
, xNode
, nFlags
);
504 exportAnimValue( rStrm
, xNode
, nGroupLevel
== 4 );
508 case AnimationNodeType::SEQ
:
510 exportAnimNode( rStrm
, xNode
, nFillDefault
);
511 sal_Int16 nNodeType
= exportAnimPropertySet( rStrm
, xNode
);
512 sal_Int32 nFlags
= 12;
513 if ( ( nGroupLevel
== 1 ) && ( nNodeType
== css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
) )
516 bTakeBackInteractiveSequenceTimingForChild
= true;
518 exportAnimAction( rStrm
, xNode
);
519 exportAnimEvent( rStrm
, xNode
, nFlags
);
520 exportAnimValue( rStrm
, xNode
, false );
524 case AnimationNodeType::ITERATE
:
527 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
529 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
530 aAnim
.mnNodeType
= 1;
532 switch( xNode
->getRestart() )
535 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
536 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
537 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
538 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
541 switch( xNode
->getFill() )
544 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
545 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
546 case AnimationFill::FREEZE
: aAnim
.mnFill
= 2; break;
547 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
548 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
550 WriteAnimationNode( rStrm
, aAnim
);
552 exportIterate( rStrm
, xNode
);
553 exportAnimPropertySet( rStrm
, xNode
);
554 exportAnimEvent( rStrm
, xNode
);
555 exportAnimValue( rStrm
, xNode
, false );
559 case AnimationNodeType::ANIMATE
:
561 exportAnimNode( rStrm
, xNode
, nFillDefault
);
562 exportAnimPropertySet( rStrm
, xNode
);
563 exportAnimEvent( rStrm
, xNode
);
564 exportAnimValue( rStrm
, xNode
, false );
565 exportAnimate( rStrm
, xNode
);
569 case AnimationNodeType::SET
:
571 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
572 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
574 exportAnimNode( rStrm
, xNode
, nFillDefault
);
575 exportAnimPropertySet( rStrm
, xNode
);
576 exportAnimateSet( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_SET
: AFTEREFFECT_NONE
);
577 exportAnimEvent( rStrm
, xNode
);
578 exportAnimValue( rStrm
, xNode
, false );
582 bSkipChildren
= true;
587 case AnimationNodeType::ANIMATEMOTION
:
589 exportAnimNode( rStrm
, xNode
, nFillDefault
);
590 exportAnimPropertySet( rStrm
, xNode
);
591 exportAnimateMotion( rStrm
, xNode
);
592 exportAnimEvent( rStrm
, xNode
);
593 exportAnimValue( rStrm
, xNode
, false );
597 case AnimationNodeType::ANIMATECOLOR
:
599 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
600 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
602 if( bIsAfterEffectNode
)
603 xNode
= createAfterEffectNodeClone( xNode
);
605 exportAnimNode( rStrm
, xNode
, nFillDefault
);
606 exportAnimPropertySet( rStrm
, xNode
);
607 exportAnimateColor( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_COLOR
: AFTEREFFECT_NONE
);
608 exportAnimEvent( rStrm
, xNode
);
609 exportAnimValue( rStrm
, xNode
, false );
613 bSkipChildren
= true;
618 case AnimationNodeType::ANIMATETRANSFORM
:
620 exportAnimNode( rStrm
, xNode
, nFillDefault
);
621 exportAnimPropertySet( rStrm
, xNode
);
622 exportAnimateTransform( rStrm
, xNode
);
623 exportAnimEvent( rStrm
, xNode
);
624 exportAnimValue( rStrm
, xNode
, false );
628 case AnimationNodeType::TRANSITIONFILTER
:
630 exportAnimNode( rStrm
, xNode
, nFillDefault
);
631 exportAnimPropertySet( rStrm
, xNode
);
632 exportAnimEvent( rStrm
, xNode
);
633 exportAnimValue( rStrm
, xNode
, false );
634 exportTransitionFilter( rStrm
, xNode
);
638 case AnimationNodeType::AUDIO
: // #i58428#
640 exportAnimNode( rStrm
, xNode
, nFillDefault
);
641 exportAnimPropertySet( rStrm
, xNode
);
643 Reference
< XAudio
> xAudio( xNode
, UNO_QUERY
);
646 Any
aAny( xAudio
->getSource() );
649 if ( ( aAny
>>= aURL
) && !aURL
.isEmpty() )
652 sal_Int32 nTrigger
= 3;
653 sal_Int32 nU3
= nAudioGroup
;
654 sal_Int32 nBegin
= 0;
656 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 1 );
658 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
659 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
666 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 2 );
668 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
669 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
672 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
674 sal_uInt32
const nRefMode
= 3;
675 sal_uInt32
const nRefType
= 2;
676 sal_uInt32 nRefId
= mrExSoundCollection
.GetId( aURL
);
677 sal_Int32
const begin
= -1;
678 sal_Int32
const end
= -1;
680 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
681 rStrm
.WriteUInt32( nRefMode
).WriteUInt32( nRefType
).WriteUInt32( nRefId
).WriteInt32( begin
).WriteInt32( end
);
685 exportAnimValue( rStrm
, xNode
, false );
691 // export after effect node if one exists for this node
692 Reference
< XAnimationNode
> xAfterEffectNode
;
693 if( hasAfterEffectNode( xNode
, xAfterEffectNode
) )
695 exportNode( rStrm
, xAfterEffectNode
, DFF_msofbtAnimSubGoup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
698 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
699 if( xEnumerationAccess
.is() )
701 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
702 if( xEnumeration
.is() )
704 while( xEnumeration
->hasMoreElements() )
706 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
707 if( xChildNode
.is() )
709 if ( xChildNode
->getType() == AnimationNodeType::AUDIO
)
711 xAudioNode
= xChildNode
;
712 nAudioGroup
= mnCurrentGroup
;
715 exportNode( rStrm
, xChildNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
722 if ( xAudioNode
.is() )
723 exportNode( rStrm
, xAudioNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
725 if( xNode
->getType() == AnimationNodeType::ITERATE
)
729 Reference
< XAnimationNode
> AnimationExporter::createAfterEffectNodeClone( const Reference
< XAnimationNode
>& xNode
)
733 Reference
< css::util::XCloneable
> xClonable( xNode
, UNO_QUERY_THROW
);
734 Reference
< XAnimationNode
> xCloneNode( xClonable
->createClone(), UNO_QUERY_THROW
);
737 xCloneNode
->setBegin( aEmpty
);
743 OSL_FAIL("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
748 bool AnimationExporter::GetNodeType( const Reference
< XAnimationNode
>& xNode
, sal_Int16
& nType
)
750 // trying to get the nodetype
751 Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
752 if ( aUserData
.hasElements() )
754 const NamedValue
* p
= aUserData
.getConstArray();
755 sal_Int32 nLength
= aUserData
.getLength();
758 if ( p
->Name
== "node-type" )
760 if ( p
->Value
>>= nType
)
769 void AnimationExporter::exportAnimNode( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
,
770 const sal_Int16 nFillDefault
)
772 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
776 switch( xNode
->getRestart() )
779 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
780 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
781 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
782 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
785 switch( nFillDefault
)
788 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
789 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
790 case AnimationFill::FREEZE
:
791 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
792 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
794 // attribute Duration
795 double fDuration
= 0.0;
796 css::animations::Timing eTiming
;
797 if ( xNode
->getDuration() >>= eTiming
)
799 if ( eTiming
== Timing_INDEFINITE
)
800 aAnim
.mnDuration
= -1;
802 else if ( xNode
->getDuration() >>= fDuration
)
804 aAnim
.mnDuration
= static_cast<sal_Int32
>( fDuration
* 1000.0 );
807 aAnim
.mnDuration
= -1;
809 // NodeType, NodeGroup
810 aAnim
.mnNodeType
= 1;
811 aAnim
.mnGroupType
= mso_Anim_GroupType_SEQ
;
812 switch( xNode
->getType() )
814 case AnimationNodeType::PAR
:
815 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
817 case AnimationNodeType::SEQ
:
820 if( GetNodeType( xNode
, nType
) )
823 case css::presentation::EffectNodeType::TIMING_ROOT
: aAnim
.mnNodeType
= 0x12; break;
824 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: aAnim
.mnNodeType
= 0x18; break;
829 case AnimationNodeType::ANIMATE
:
830 case AnimationNodeType::SET
:
832 case AnimationNodeType::CUSTOM
:
833 case AnimationNodeType::ITERATE
:
834 case AnimationNodeType::ANIMATEMOTION
:
835 case AnimationNodeType::ANIMATECOLOR
:
836 case AnimationNodeType::ANIMATETRANSFORM
:
838 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
839 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
843 case AnimationNodeType::AUDIO
:
845 aAnim
.mnGroupType
= mso_Anim_GroupType_MEDIA
;
846 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
850 case AnimationNodeType::TRANSITIONFILTER
:
852 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
853 aAnim
.mnNodeType
= mso_Anim_Behaviour_FILTER
;
858 WriteAnimationNode( rStrm
, aAnim
);
861 void AnimationExporter::GetUserData( const Sequence
< NamedValue
>& rUserData
, const Any
** pAny
, std::size_t nLen
)
863 // storing user data into pAny, to allow direct access later
864 memset( pAny
, 0, nLen
);
865 if ( !rUserData
.hasElements() )
868 const NamedValue
* p
= rUserData
.getConstArray();
869 sal_Int32 nLength
= rUserData
.getLength();
872 if ( p
->Name
== "node-type" )
874 pAny
[ DFF_ANIM_NODE_TYPE
] = &(p
->Value
);
876 else if ( p
->Name
== "preset-class" )
878 pAny
[ DFF_ANIM_PRESET_CLASS
] = &(p
->Value
);
880 else if ( p
->Name
== "preset-id" )
882 pAny
[ DFF_ANIM_PRESET_ID
] = &(p
->Value
);
884 else if ( p
->Name
== "preset-sub-type" )
886 pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] = &(p
->Value
);
888 else if ( p
->Name
== "master-element" )
890 pAny
[ DFF_ANIM_AFTEREFFECT
] = &(p
->Value
);
896 sal_uInt32
AnimationExporter::GetPresetID( const OUString
& rPreset
, sal_uInt32 nAPIPresetClass
, bool& bPresetId
)
898 sal_uInt32 nPresetId
= 0;
901 if ( rPreset
.match("ppt_", 0) )
903 sal_Int32 nLast
= rPreset
.lastIndexOf( '_' );
904 if ( ( nLast
!= -1 ) && ( ( nLast
+ 1 ) < rPreset
.getLength() ) )
906 OUString
aNumber( rPreset
.copy( nLast
+ 1 ) );
907 nPresetId
= aNumber
.toInt32();
913 const oox::ppt::preset_mapping
* p
= oox::ppt::preset_mapping::getList();
914 while( p
->mpStrPresetId
&& ((p
->mnPresetClass
!= static_cast<sal_Int32
>(nAPIPresetClass
)) || !rPreset
.equalsAscii( p
->mpStrPresetId
)) )
917 if( p
->mpStrPresetId
)
919 nPresetId
= p
->mnPresetId
;
927 sal_Int16
AnimationExporter::exportAnimPropertySet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
929 sal_Int16 nNodeType
= css::presentation::EffectNodeType::DEFAULT
;
931 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
933 Reference
< XAnimationNode
> xMaster
;
935 Any aMasterRel
, aOverride
, aRunTimeContext
;
937 // storing user data into pAny, to allow direct access later
938 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
939 const css::uno::Any
* pAny
[ DFF_ANIM_PROPERTY_ID_COUNT
];
940 GetUserData( aUserData
, pAny
, sizeof( pAny
) );
942 if( pAny
[ DFF_ANIM_AFTEREFFECT
] )
943 ( *pAny
[ DFF_ANIM_AFTEREFFECT
] ) >>= xMaster
;
945 // calculate master-rel
948 sal_Int32 nMasterRel
= 2;
949 if( xNode
.is() && xMaster
.is() && (xNode
->getParent() == xMaster
->getParent() ) )
952 aMasterRel
<<= nMasterRel
;
954 pAny
[ DFF_ANIM_MASTERREL
] = &aMasterRel
;
956 aOverride
<<= sal_Int32(1);
957 pAny
[ DFF_ANIM_OVERRIDE
] = &aOverride
;
959 aRunTimeContext
<<= sal_Int32(1);
960 pAny
[ DFF_ANIM_RUNTIMECONTEXT
] = &aRunTimeContext
;
963 // the order is important
964 if ( pAny
[ DFF_ANIM_NODE_TYPE
] )
966 if ( *pAny
[ DFF_ANIM_NODE_TYPE
] >>= nNodeType
)
968 sal_uInt32 nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
;
971 case css::presentation::EffectNodeType::ON_CLICK
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
; break;
972 case css::presentation::EffectNodeType::WITH_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_WITH_PREVIOUS
; break;
973 case css::presentation::EffectNodeType::AFTER_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS
; break;
974 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE
; break;
975 case css::presentation::EffectNodeType::TIMING_ROOT
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_TIMING_ROOT
; break;
976 case css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ
; break;
978 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_NODE_TYPE
, nPPTNodeType
);
981 sal_uInt32 nPresetId
= 0;
982 sal_uInt32 nPresetSubType
= 0;
983 sal_uInt32 nAPIPresetClass
= EffectPresetClass::CUSTOM
;
984 sal_uInt32 nPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
985 bool bPresetClass
, bPresetId
, bPresetSubType
;
986 bPresetId
= bPresetClass
= bPresetSubType
= false;
988 if ( pAny
[ DFF_ANIM_PRESET_CLASS
] )
990 if ( *pAny
[ DFF_ANIM_PRESET_CLASS
] >>= nAPIPresetClass
)
992 sal_uInt8 nPPTPresetClass
;
993 switch( nAPIPresetClass
)
995 case EffectPresetClass::ENTRANCE
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_ENTRANCE
; break;
996 case EffectPresetClass::EXIT
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EXIT
; break;
997 case EffectPresetClass::EMPHASIS
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EMPHASIS
; break;
998 case EffectPresetClass::MOTIONPATH
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MOTIONPATH
; break;
999 case EffectPresetClass::OLEACTION
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_OLE_ACTION
; break;
1000 case EffectPresetClass::MEDIACALL
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MEDIACALL
; break;
1002 nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
1004 nPresetClass
= nPPTPresetClass
;
1005 bPresetClass
= true;
1008 if ( pAny
[ DFF_ANIM_PRESET_ID
] )
1011 if ( *pAny
[ DFF_ANIM_PRESET_ID
] >>= sPreset
)
1012 nPresetId
= GetPresetID( sPreset
, nAPIPresetClass
, bPresetId
);
1015 if ( pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] )
1017 OUString sPresetSubType
;
1018 if ( *pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] >>= sPresetSubType
)
1020 nPresetSubType
= TranslatePresetSubType( nPresetClass
, nPresetId
, sPresetSubType
);
1021 bPresetSubType
= true;
1025 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_ID
, nPresetId
);
1026 if ( bPresetSubType
)
1027 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_SUB_TYPE
, nPresetSubType
);
1029 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_CLASS
, nPresetClass
);
1031 if ( pAny
[ DFF_ANIM_ID
] )
1036 if ( pAny
[ DFF_ANIM_AFTEREFFECT
] )
1038 bool bAfterEffect
= false;
1039 if ( *pAny
[ DFF_ANIM_AFTEREFFECT
] >>= bAfterEffect
)
1040 exportAnimPropertyByte( rStrm
, DFF_ANIM_AFTEREFFECT
, int(bAfterEffect
) );
1043 if ( pAny
[ DFF_ANIM_RUNTIMECONTEXT
] )
1045 sal_Int32 nRunTimeContext
= 0;
1046 if ( *pAny
[ DFF_ANIM_RUNTIMECONTEXT
] >>= nRunTimeContext
)
1047 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_RUNTIMECONTEXT
, nRunTimeContext
);
1049 if ( pAny
[ DFF_ANIM_PATH_EDIT_MODE
] )
1056 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
1060 bool bDirection
= !xColor
->getDirection();
1061 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_DIRECTION
, bDirection
? 1 : 0 );
1065 if ( pAny
[ DFF_ANIM_OVERRIDE
] )
1067 sal_Int32 nOverride
= 0;
1068 if ( *pAny
[ DFF_ANIM_OVERRIDE
] >>= nOverride
)
1069 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_OVERRIDE
, nOverride
);
1072 if ( pAny
[ DFF_ANIM_MASTERREL
] )
1074 sal_Int32 nMasterRel
= 0;
1075 if ( *pAny
[ DFF_ANIM_MASTERREL
] >>= nMasterRel
)
1076 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_MASTERREL
, nMasterRel
);
1080 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1083 sal_Int16 nEndAfterSlide = 0;
1084 nEndAfterSlide = xAudio->getEndAfterSlide();
1085 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1088 Reference
< XAnimate
> xAnim( xNode
, UNO_QUERY
);
1091 // TODO: DFF_ANIM_TIMEFILTER
1093 if ( pAny
[ DFF_ANIM_EVENT_FILTER
] )
1095 // TODO DFF_ANIM_EVENT_FILTER
1097 if ( pAny
[ DFF_ANIM_VOLUME
] )
1099 // TODO DFF_ANIM_VOLUME
1104 bool AnimationExporter::exportAnimProperty( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const css::uno::Any
& rAny
, const TranslateMode eTranslateMode
)
1107 if ( rAny
.hasValue() )
1109 switch( rAny
.getValueType().getTypeClass() )
1111 case css::uno::TypeClass_UNSIGNED_SHORT
:
1112 case css::uno::TypeClass_SHORT
:
1113 case css::uno::TypeClass_UNSIGNED_LONG
:
1114 case css::uno::TypeClass_LONG
:
1117 if ( rAny
>>= nVal
)
1119 exportAnimPropertyuInt32( rStrm
, nPropertyId
, nVal
);
1125 case css::uno::TypeClass_DOUBLE
:
1128 if ( rAny
>>= fVal
)
1130 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1135 case css::uno::TypeClass_FLOAT
:
1138 if ( rAny
>>= fVal
)
1140 if ( eTranslateMode
& TRANSLATE_NUMBER_TO_STRING
)
1142 OUString
aNumber( OUString::number( fVal
) );
1143 exportAnimPropertyString( rStrm
, nPropertyId
, aNumber
, eTranslateMode
);
1147 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1153 case css::uno::TypeClass_STRING
:
1156 if ( rAny
>>= aStr
)
1158 exportAnimPropertyString( rStrm
, nPropertyId
, aStr
, eTranslateMode
);
1169 void AnimationExporter::exportAnimPropertyString( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const OUString
& rVal
, const TranslateMode eTranslateMode
)
1171 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1172 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_UNISTRING
);
1173 OUString
aStr( rVal
);
1174 if ( eTranslateMode
!= TRANSLATE_NONE
)
1175 ImplTranslateAttribute( aStr
, eTranslateMode
);
1176 writeZString( rStrm
, aStr
);
1179 void AnimationExporter::exportAnimPropertyFloat( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const double& rVal
)
1181 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1182 float fFloat
= static_cast<float>(rVal
);
1183 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_FLOAT
)
1184 .WriteFloat( fFloat
);
1187 void AnimationExporter::exportAnimPropertyuInt32( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt32 nVal
)
1189 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1190 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_INT32
)
1191 .WriteUInt32( nVal
);
1194 void AnimationExporter::exportAnimPropertyByte( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt8 nVal
)
1196 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1197 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_BYTE
)
1198 .WriteUChar( nVal
);
1201 void AnimationExporter::writeZString( SvStream
& rStrm
, const OUString
& rVal
)
1204 for ( i
= 0; i
< rVal
.getLength(); i
++ )
1205 rStrm
.WriteUInt16( rVal
[ i
] );
1206 rStrm
.WriteUInt16( 0 );
1209 void AnimationExporter::exportAnimAction( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1211 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAction
);
1213 sal_Int32
const nConcurrent
= 1;
1214 sal_Int32
const nNextAction
= 1;
1215 sal_Int32 nEndSync
= 0;
1216 sal_Int32
const nU4
= 0;
1217 sal_Int32
const nU5
= 3;
1219 sal_Int16 nAnimationEndSync
= 0;
1220 if ( xNode
->getEndSync() >>= nAnimationEndSync
)
1222 if ( nAnimationEndSync
== AnimationEndSync::ALL
)
1225 rStrm
.WriteInt32( nConcurrent
)
1226 .WriteInt32( nNextAction
)
1227 .WriteInt32( nEndSync
)
1233 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1234 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1235 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
1236 void AnimationExporter::exportAnimEvent( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_Int32 nFlags
)
1239 for ( i
= 0; i
< 4; i
++ )
1242 sal_Int32 nTrigger
= 0;
1244 sal_Int32 nBegin
= 0;
1246 bool bCreateEvent
= false;
1256 css::animations::Timing eTiming
;
1259 if ( nFlags
& 0x20 )
1261 // taking the first child
1262 Reference
< XEnumerationAccess
> xEA( xNode
, UNO_QUERY_THROW
);
1263 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), css::uno::UNO_SET_THROW
);
1264 if ( xE
->hasMoreElements() )
1266 Reference
< XAnimationNode
> xClickNode( xE
->nextElement(), UNO_QUERY
);
1267 aAny
= xClickNode
->getBegin();
1270 else if ( nFlags
& 0x40 )
1272 // begin has to be replaced with void, so don't do anything
1276 aAny
= xNode
->getBegin();
1277 if ( nFlags
& 0x10 ) // replace ON_NEXT with INDEFINITE
1279 if ( ( aAny
>>= aEvent
) && ( aEvent
.Trigger
== EventTrigger::ON_NEXT
) )
1281 eTiming
= Timing_INDEFINITE
;
1288 aAny
= xNode
->getEnd();
1290 double fTiming
= 0.0;
1291 if ( aAny
>>= aEvent
)
1293 bCreateEvent
= true;
1294 switch( aEvent
.Trigger
)
1296 case EventTrigger::NONE
: nTrigger
= 0; break;
1297 case EventTrigger::ON_BEGIN
: nTrigger
= 1; break;
1298 case EventTrigger::ON_END
: nTrigger
= 2; break;
1299 case EventTrigger::BEGIN_EVENT
: nTrigger
= 3; break;
1300 case EventTrigger::END_EVENT
: nTrigger
= 4; nU1
= 2; nU3
= mnCurrentGroup
; break;
1301 case EventTrigger::ON_CLICK
: nTrigger
= 5; break;
1302 case EventTrigger::ON_DBL_CLICK
: nTrigger
= 6; break;
1303 case EventTrigger::ON_MOUSE_ENTER
: nTrigger
= 7; break;
1304 case EventTrigger::ON_MOUSE_LEAVE
: nTrigger
= 8; break;
1305 case EventTrigger::ON_NEXT
: nTrigger
= 9; break;
1306 case EventTrigger::ON_PREV
: nTrigger
= 10; break;
1307 case EventTrigger::ON_STOP_AUDIO
: nTrigger
= 11; break;
1309 if ( aEvent
.Offset
.hasValue() )
1311 if ( aEvent
.Offset
>>= eTiming
)
1313 if ( eTiming
== Timing_INDEFINITE
)
1316 else if ( aEvent
.Offset
>>= fTiming
)
1317 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1319 aSource
= aEvent
.Source
;
1321 else if ( aAny
>>= eTiming
)
1323 bCreateEvent
= true;
1324 if ( eTiming
== Timing_INDEFINITE
)
1327 else if ( aAny
>>= fTiming
)
1329 bCreateEvent
= true;
1330 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1337 if ( nFlags
& ( 1 << i
) )
1339 bCreateEvent
= true;
1347 if ( nFlags
& ( 1 << i
) )
1349 bCreateEvent
= true;
1358 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, i
+ 1 );
1360 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
1361 rStrm
.WriteInt32( nU1
)
1362 .WriteInt32( nTrigger
)
1364 .WriteInt32( nBegin
);
1366 exportAnimateTargetElement( rStrm
, aSource
, ( nFlags
& ( 1 << i
) ) != 0 );
1371 Any
AnimationExporter::convertAnimateValue( const Any
& rSourceValue
, const OUString
& rAttributeName
)
1374 if ( rAttributeName
== "X"
1375 || rAttributeName
== "Y"
1376 || rAttributeName
== "Width"
1377 || rAttributeName
== "Height"
1381 if ( rSourceValue
>>= aStr
)
1383 ImplTranslateAttribute( aStr
, TRANSLATE_MEASURE
);
1387 else if ( rAttributeName
== "Rotate" // "r" or "style.rotation" ?
1388 || rAttributeName
== "Opacity"
1389 || rAttributeName
== "CharHeight"
1390 || rAttributeName
== "SkewX"
1393 double fNumber
= 0.0;
1394 if ( rSourceValue
>>= fNumber
)
1395 aDest
+= OUString::number( fNumber
);
1397 else if ( rAttributeName
== "Color"
1398 || rAttributeName
== "FillColor" // "Fillcolor" or "FillColor" ?
1399 || rAttributeName
== "LineColor"
1400 || rAttributeName
== "CharColor"
1403 sal_Int32 nColor
= 0;
1404 Sequence
< double > aHSL( 3 );
1406 if ( rSourceValue
>>= aHSL
)
1409 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 0 ] / ( 360.0 / 255 ) ) )
1411 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 ) )
1413 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 ) )
1416 else if ( rSourceValue
>>= nColor
)
1419 + OUString::number( static_cast<sal_Int8
>(nColor
) )
1421 + OUString::number( static_cast<sal_Int8
>( nColor
>> 8 ) )
1423 + OUString::number( static_cast<sal_Int8
>( nColor
>> 16 ) )
1427 else if ( rAttributeName
== "FillStyle" )
1429 css::drawing::FillStyle eFillStyle
;
1430 if ( rSourceValue
>>= eFillStyle
)
1432 if ( eFillStyle
== css::drawing::FillStyle_NONE
)
1433 aDest
+= "none"; // ?
1438 else if (rAttributeName
== "FillOn")
1441 if ( rSourceValue
>>= bFillOn
)
1449 else if ( rAttributeName
== "LineStyle" )
1451 css::drawing::LineStyle eLineStyle
;
1452 if ( rSourceValue
>>= eLineStyle
)
1454 if ( eLineStyle
== css::drawing::LineStyle_NONE
)
1460 else if ( rAttributeName
== "CharWeight" )
1462 float fFontWeight
= 0.0;
1463 if ( rSourceValue
>>= fFontWeight
)
1465 if ( fFontWeight
== css::awt::FontWeight::BOLD
)
1471 else if ( rAttributeName
== "CharUnderline" )
1473 sal_Int16 nFontUnderline
= 0;
1474 if ( rSourceValue
>>= nFontUnderline
)
1476 if ( nFontUnderline
== css::awt::FontUnderline::NONE
)
1482 else if ( rAttributeName
== "CharPosture" )
1484 css::awt::FontSlant eFontSlant
;
1485 if ( rSourceValue
>>= eFontSlant
)
1487 if ( eFontSlant
== css::awt::FontSlant_ITALIC
)
1490 aDest
+= "normal"; // ?
1493 else if ( rAttributeName
== "Visibility" )
1495 bool bVisible
= true;
1496 if ( rSourceValue
>>= bVisible
)
1505 if ( !aDest
.isEmpty() )
1508 aRet
= rSourceValue
;
1512 void AnimationExporter::exportAnimateSet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
1514 Reference
< XAnimateSet
> xSet( xNode
, UNO_QUERY
);
1518 EscherExContainer
aAnimateSet( rStrm
, DFF_msofbtAnimateSet
, 0 );
1520 EscherExAtom
aAnimateSetData( rStrm
, DFF_msofbtAnimateSetData
);
1521 sal_uInt32
const nId1
= 1; // ??
1522 sal_uInt32
const nId2
= 1; // ??
1523 rStrm
.WriteUInt32( nId1
).WriteUInt32( nId2
);
1525 Any
aConvertedValue( convertAnimateValue( xSet
->getTo(), xSet
->getAttributeName() ) );
1526 if ( aConvertedValue
.hasValue() )
1527 exportAnimProperty( rStrm
, 1, aConvertedValue
, TRANSLATE_NONE
);
1528 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
1531 sal_uInt32
AnimationExporter::GetValueTypeForAttributeName( const OUString
& rAttributeName
)
1533 sal_uInt32 nValueType
= 0;
1537 const sal_Char
* pName
;
1540 static const Entry lcl_attributeMap
[] =
1543 { "charfontname", 0 },
1544 { "charheight", 1 },
1545 { "charposture", 0 },
1546 // TODO(Q1): This should prolly be changed in PPT import
1547 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1548 { "charrotation", 1 },
1549 { "charunderline", 0 },
1550 { "charweight", 0 },
1562 { "visibility", 1 },
1568 const Entry
* pPtr
= &lcl_attributeMap
[ 0 ];
1569 while( pPtr
->pName
)
1571 if ( rAttributeName
.equalsIgnoreAsciiCaseAscii( pPtr
->pName
) )
1573 nValueType
= pPtr
->nType
;
1578 DBG_ASSERT( pPtr
->pName
, "GetValueTypeForAttributeName, unknown property value!" );
1582 void AnimationExporter::exportAnimate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1584 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1585 if ( !xAnimate
.is() )
1588 Any
aBy ( xAnimate
->getBy() );
1589 Any
aFrom( xAnimate
->getFrom() );
1590 Any
aTo ( xAnimate
->getTo() );
1592 EscherExContainer
aContainer( rStrm
, DFF_msofbtAnimate
, 0 );
1594 EscherExAtom
aAnimateData( rStrm
, DFF_msofbtAnimateData
);
1595 sal_uInt32 nBits
= 0x38;
1596 sal_Int16 nTmp
= xAnimate
->getCalcMode();
1597 sal_uInt32 nCalcMode
= /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp
== AnimationCalcMode::LINEAR
) ? 1 : 0;
1598 sal_uInt32 nValueType
= GetValueTypeForAttributeName( xAnimate
->getAttributeName() );
1600 if ( aBy
.hasValue() )
1602 if ( aFrom
.hasValue() )
1604 if ( aTo
.hasValue() )
1607 rStrm
.WriteUInt32( nCalcMode
)
1608 .WriteUInt32( nBits
)
1609 .WriteUInt32( nValueType
);
1611 if ( aBy
.hasValue() )
1612 exportAnimProperty( rStrm
, 1, aBy
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1613 if ( aFrom
.hasValue() )
1614 exportAnimProperty( rStrm
, 2, aFrom
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1615 if ( aTo
.hasValue() )
1616 exportAnimProperty( rStrm
, 3, aTo
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1618 exportAnimateKeyPoints( rStrm
, xAnimate
);
1619 exportAnimateTarget( rStrm
, xNode
);
1622 void AnimationExporter::exportAnimateTarget( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_uInt32 nForceAttributeNames
, int nAfterEffectType
)
1624 EscherExContainer
aAnimateTarget( rStrm
, DFF_msofbtAnimateTarget
, 0 );
1625 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1626 if ( !xAnimate
.is() )
1630 EscherExAtom
aAnimateTargetSettings( rStrm
, DFF_msofbtAnimateTargetSettings
, 0 );
1631 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1632 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1633 // nAccumulate 0 = none, 1 = always
1634 // nTransformType 0: "property" else "image"
1635 sal_uInt32 nBits
= 0;
1636 sal_uInt32 nAdditive
= 0;
1637 sal_uInt32 nAccumulate
= 0;
1638 sal_uInt32
const nTransformType
= 0;
1639 if ( xAnimate
.is() )
1641 if ( !xAnimate
->getAttributeName().isEmpty() )
1642 nBits
|= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1643 sal_Int16 nAdditiveMode
= xAnimate
->getAdditive();
1644 if ( nAdditiveMode
!= AnimationAdditiveMode::BASE
)
1647 switch( nAdditiveMode
)
1649 case AnimationAdditiveMode::SUM
: nAdditive
= 1; break;
1650 case AnimationAdditiveMode::REPLACE
: nAdditive
= 2; break;
1651 case AnimationAdditiveMode::MULTIPLY
: nAdditive
= 3; break;
1652 case AnimationAdditiveMode::NONE
: nAdditive
= 4; break;
1655 if ( xAnimate
->getAccumulate() )
1661 rStrm
.WriteUInt32( nBits
)
1662 .WriteUInt32( nAdditive
)
1663 .WriteUInt32( nAccumulate
)
1664 .WriteUInt32( nTransformType
);
1666 if ( !xAnimate
->getAttributeName().isEmpty() || nForceAttributeNames
)
1668 EscherExContainer
aAnimateAttributeNames( rStrm
, DFF_msofbtAnimateAttributeNames
, 1 );
1669 OUString
aAttributeName( xAnimate
->getAttributeName() );
1670 if ( nForceAttributeNames
)
1672 if( nForceAttributeNames
== 1 )
1674 aAttributeName
= "r";
1677 sal_Int32 nIndex
= 0;
1680 OUString
aToken( aAttributeName
.getToken( 0, ';', nIndex
) );
1681 exportAnimPropertyString( rStrm
, 0, aToken
, TRANSLATE_ATTRIBUTE
);
1683 while ( nIndex
>= 0 );
1686 if( nAfterEffectType
!= AFTEREFFECT_NONE
)
1688 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
1689 exportAnimPropertyuInt32( rStrm
, 6, 1 );
1690 if( nAfterEffectType
== AFTEREFFECT_COLOR
)
1692 exportAnimPropertyuInt32( rStrm
, 4, 0 );
1693 exportAnimPropertyuInt32( rStrm
, 5, 0 );
1696 exportAnimateTargetElement( rStrm
, aTarget
.hasValue() ? aTarget
: xAnimate
->getTarget(), false );
1699 Reference
< XShape
> AnimationExporter::getTargetElementShape( const Any
& rAny
, sal_Int32
& rBegin
, sal_Int32
& rEnd
, bool& rParagraphTarget
)
1701 Reference
< XShape
> xShape
;
1704 rParagraphTarget
= false;
1708 ParagraphTarget aParaTarget
;
1709 if( rAny
>>= aParaTarget
)
1710 xShape
= aParaTarget
.Shape
;
1713 // now calculating the character range for the paragraph
1714 sal_Int16 nParagraph
= aParaTarget
.Paragraph
;
1715 Reference
< XSimpleText
> xText( xShape
, UNO_QUERY
);
1718 rParagraphTarget
= true;
1719 Reference
< XEnumerationAccess
> xTextParagraphEnumerationAccess( xText
, UNO_QUERY
);
1720 if ( xTextParagraphEnumerationAccess
.is() )
1722 Reference
< XEnumeration
> xTextParagraphEnumeration( xTextParagraphEnumerationAccess
->createEnumeration() );
1723 if ( xTextParagraphEnumeration
.is() )
1725 sal_Int16 nCurrentParagraph
;
1726 rBegin
= rEnd
= nCurrentParagraph
= 0;
1727 while ( xTextParagraphEnumeration
->hasMoreElements() )
1729 Reference
< XTextRange
> xTextRange( xTextParagraphEnumeration
->nextElement(), UNO_QUERY
);
1730 if ( xTextRange
.is() )
1732 OUString
aParaText( xTextRange
->getString() );
1733 sal_Int32 nLength
= aParaText
.getLength() + 1;
1735 if ( nCurrentParagraph
== nParagraph
)
1737 nCurrentParagraph
++;
1750 void AnimationExporter::exportAnimateTargetElement( SvStream
& rStrm
, const Any
& rAny
, const bool bCreate2b01Atom
)
1752 sal_uInt32 nRefMode
= 0; // nRefMode == 2 -> Paragraph
1753 sal_Int32 begin
= -1;
1755 bool bParagraphTarget
;
1757 Reference
< XShape
> xShape
= getTargetElementShape(rAny
, begin
, end
, bParagraphTarget
);
1759 if( bParagraphTarget
)
1762 if ( !(xShape
.is() || bCreate2b01Atom
) )
1765 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
1768 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
1770 sal_uInt32
const nRefType
= 1; // TODO: nRefType == 2 -> Sound;
1771 sal_uInt32 nRefId
= mrSolverContainer
.GetShapeId( xShape
);
1773 rStrm
.WriteUInt32( nRefMode
)
1774 .WriteUInt32( nRefType
)
1775 .WriteUInt32( nRefId
)
1776 .WriteInt32( begin
)
1779 if ( bCreate2b01Atom
)
1781 EscherExAtom
a2b01Atom( rStrm
, 0x2b01 );
1782 rStrm
.WriteUInt32( 1 ); // ?
1786 void AnimationExporter::exportAnimateKeyPoints( SvStream
& rStrm
, const Reference
< XAnimate
>& xAnimate
)
1788 Sequence
< double > aKeyTimes( xAnimate
->getKeyTimes() );
1789 Sequence
< Any
> aValues( xAnimate
->getValues() );
1790 OUString
aFormula( xAnimate
->getFormula() );
1791 if ( !aKeyTimes
.hasElements() )
1794 EscherExContainer
aAnimKeyPoints( rStrm
, DFF_msofbtAnimKeyPoints
);
1796 for ( i
= 0; i
< aKeyTimes
.getLength(); i
++ )
1799 EscherExAtom
aAnimKeyTime( rStrm
, DFF_msofbtAnimKeyTime
);
1800 sal_Int32 nKeyTime
= static_cast<sal_Int32
>( aKeyTimes
[ i
] * 1000.0 );
1801 rStrm
.WriteInt32( nKeyTime
);
1804 if ( aValues
[ i
].hasValue() )
1807 if ( aValues
[ i
] >>= aPair
)
1809 aAny
[ 0 ] = convertAnimateValue( aPair
.First
, xAnimate
->getAttributeName() );
1810 aAny
[ 1 ] = convertAnimateValue( aPair
.Second
, xAnimate
->getAttributeName() );
1814 aAny
[ 0 ] = convertAnimateValue( aValues
[ i
], xAnimate
->getAttributeName() );
1816 if ( !i
&& !aFormula
.isEmpty() )
1818 ImplTranslateAttribute( aFormula
, TRANSLATE_MEASURE
);
1819 aAny
[ 1 ] <<= aFormula
;
1821 exportAnimProperty( rStrm
, 0, aAny
[ 0 ], TRANSLATE_NONE
);
1822 exportAnimProperty( rStrm
, 1, aAny
[ 1 ], TRANSLATE_NONE
);
1827 void AnimationExporter::exportAnimValue( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const bool bExportAlways
)
1831 double fRepeat
= 0.0;
1832 float fRepeatCount
= 0.0;
1833 css::animations::Timing eTiming
;
1834 aAny
= xNode
->getRepeatCount();
1835 if ( aAny
>>= eTiming
)
1837 if ( eTiming
== Timing_INDEFINITE
)
1838 fRepeatCount
= (float(3.40282346638528860e+38));
1840 else if ( aAny
>>= fRepeat
)
1841 fRepeatCount
= static_cast<float>(fRepeat
);
1842 if ( fRepeatCount
!= 0.0 )
1844 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1845 sal_uInt32
const nType
= 0;
1846 rStrm
.WriteUInt32( nType
)
1847 .WriteFloat( fRepeatCount
);
1850 float fAccelerate
= static_cast<float>(xNode
->getAcceleration());
1851 if ( bExportAlways
|| ( fAccelerate
!= 0.0 ) )
1853 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1854 sal_uInt32
const nType
= 3;
1855 rStrm
.WriteUInt32( nType
)
1856 .WriteFloat( fAccelerate
);
1860 float fDecelerate
= static_cast<float>(xNode
->getDecelerate());
1861 if ( bExportAlways
|| ( fDecelerate
!= 0.0 ) )
1863 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1864 sal_uInt32
const nType
= 4;
1865 rStrm
.WriteUInt32( nType
)
1866 .WriteFloat( fDecelerate
);
1870 bool bAutoReverse
= xNode
->getAutoReverse();
1871 if ( bExportAlways
|| bAutoReverse
)
1873 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1874 sal_uInt32
const nType
= 5;
1875 sal_uInt32 nVal
= bAutoReverse
? 1 : 0;
1876 rStrm
.WriteUInt32( nType
)
1877 .WriteUInt32( nVal
);
1881 void AnimationExporter::exportTransitionFilter( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1883 Reference
< XTransitionFilter
> xFilter( xNode
, UNO_QUERY
);
1884 if ( !xFilter
.is() )
1887 EscherExContainer
aAnimateFilter( rStrm
, DFF_msofbtAnimateFilter
);
1889 EscherExAtom
aAnimateFilterData( rStrm
, DFF_msofbtAnimateFilterData
);
1890 sal_uInt32
const nBits
= 3; // bit 0 -> use AnimAttributeValue
1891 // bit 1 -> use nTransition
1893 sal_uInt32 nTransition
= xFilter
->getMode() ? 0 : 1;
1894 rStrm
.WriteUInt32( nBits
)
1895 .WriteUInt32( nTransition
);
1897 const sal_Char
* pFilter
= FindTransitionName( xFilter
->getTransition(), xFilter
->getSubtype(), xFilter
->getDirection() );
1900 const OUString
aStr( OUString::createFromAscii( pFilter
) );
1901 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1903 exportAnimateTarget( rStrm
, xNode
);
1906 void AnimationExporter::exportAnimateMotion( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1908 Reference
< XAnimateMotion
> xMotion( xNode
, UNO_QUERY
);
1909 if ( !xMotion
.is() )
1912 EscherExContainer
aAnimateMotion( rStrm
, DFF_msofbtAnimateMotion
);
1914 { //SJ: Ignored from import filter
1915 EscherExAtom
aAnimateMotionData( rStrm
, DFF_msofbtAnimateMotionData
);
1916 sal_uInt32
const nBits
= 0x98;
1917 sal_uInt32
const nOrigin
= 0x2;
1918 float const fByX
= 100.0; // nBits&1
1919 float const fByY
= 100.0; // nBits&1
1920 float const fFromX
= 0.0; // nBits&2
1921 float const fFromY
= 0.0; // nBits&2
1922 float const fToX
= 100.0; // nBits&4
1923 float const fToY
= 100.0; // nBits&4
1924 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nOrigin
);
1928 if ( xMotion
->getPath() >>= aStr
)
1930 if ( !aStr
.isEmpty() )
1931 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1933 exportAnimateTarget( rStrm
, xNode
);
1937 void AnimationExporter::exportAnimateTransform( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1939 Reference
< XAnimateTransform
> xTransform( xNode
, UNO_QUERY
);
1940 if ( !xTransform
.is() )
1943 if ( xTransform
->getTransformType() == AnimationTransformType::SCALE
)
1945 EscherExContainer
aAnimateScale( rStrm
, DFF_msofbtAnimateScale
);
1947 EscherExAtom
aAnimateScaleData( rStrm
, DFF_msofbtAnimateScaleData
);
1948 sal_uInt32 nBits
= 0;
1949 sal_uInt32
const nZoomContents
= 1;
1957 double fX
= 0.0, fY
= 0.0;
1959 if ( xTransform
->getBy() >>= aPair
)
1961 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1964 fByX
= static_cast<float>( fX
* 100 );
1965 fByY
= static_cast<float>( fY
* 100 );
1968 if ( xTransform
->getFrom() >>= aPair
)
1970 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1973 fFromX
= static_cast<float>( fX
* 100 );
1974 fFromY
= static_cast<float>( fY
* 100 );
1977 if( xTransform
->getTo() >>= aPair
)
1979 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1982 fToX
= static_cast<float>( fX
* 100 );
1983 fToY
= static_cast<float>( fY
* 100 );
1987 // TODO: ZoomContents:
1989 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
1991 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nZoomContents
);
1993 exportAnimateTarget( rStrm
, xNode
);
1995 else if ( xTransform
->getTransformType() == AnimationTransformType::ROTATE
)
1997 EscherExContainer
aAnimateRotation( rStrm
, DFF_msofbtAnimateRotation
);
1999 EscherExAtom
aAnimateRotationData( rStrm
, DFF_msofbtAnimateRotationData
);
2000 sal_uInt32 nBits
= 0;
2001 sal_uInt32
const nU1
= 0;
2007 if ( xTransform
->getBy() >>= fVal
)
2010 fBy
= static_cast<float>(fVal
);
2012 if ( xTransform
->getFrom() >>= fVal
)
2015 fFrom
= static_cast<float>(fVal
);
2017 if ( xTransform
->getTo() >>= fVal
)
2020 fTo
= static_cast<float>(fVal
);
2022 rStrm
.WriteUInt32( nBits
).WriteFloat( fBy
).WriteFloat( fFrom
).WriteFloat( fTo
).WriteUInt32( nU1
);
2024 exportAnimateTarget( rStrm
, xNode
, 1 );
2028 bool AnimationExporter::getColorAny( const Any
& rAny
, const sal_Int16 nColorSpace
, sal_Int32
& rMode
, sal_Int32
& rA
, sal_Int32
& rB
, sal_Int32
& rC
)
2030 bool bIsColor
= true;
2033 if ( nColorSpace
== AnimationColorSpace::HSL
)
2036 sal_Int32 nColor
= 0;
2037 Sequence
< double > aHSL( 3 );
2038 if ( rAny
>>= nColor
) // RGB color
2040 rA
= static_cast<sal_uInt8
>( nColor
>> 16 );
2041 rB
= static_cast<sal_uInt8
>( nColor
>> 8 );
2042 rC
= static_cast<sal_uInt8
>(nColor
);
2044 else if ( rAny
>>= aHSL
) // HSL
2046 rA
= static_cast<sal_Int32
>( aHSL
[ 0 ] * 255.0 / 360.0 );
2047 rB
= static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 );
2048 rC
= static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 );
2055 void AnimationExporter::exportAnimateColor( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
2057 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
2061 EscherExContainer
aAnimateColor( rStrm
, DFF_msofbtAnimateColor
);
2063 EscherExAtom
aAnimateColorData( rStrm
, DFF_msofbtAnimateColorData
);
2064 sal_uInt32 nBits
= 8;
2066 sal_Int32 nByMode
, nByA
, nByB
, nByC
;
2067 nByMode
= nByA
= nByB
= nByC
= 0;
2069 sal_Int32 nFromMode
, nFromA
, nFromB
, nFromC
;
2070 nFromMode
= nFromA
= nFromB
= nFromC
= 0;
2072 sal_Int32 nToMode
, nToA
, nToB
, nToC
;
2073 nToMode
= nToA
= nToB
= nToC
= 0;
2075 sal_Int16 nColorSpace
= xColor
->getColorInterpolation();
2077 Any
aAny( xColor
->getBy() );
2078 if ( aAny
.hasValue() )
2080 if ( getColorAny( aAny
, nColorSpace
, nByMode
, nByA
, nByB
, nByC
) )
2083 aAny
= xColor
->getFrom();
2084 if ( aAny
.hasValue() )
2086 if ( getColorAny( aAny
, nColorSpace
, nFromMode
, nFromA
, nFromB
, nFromC
) )
2089 aAny
= xColor
->getTo();
2090 if ( aAny
.hasValue() )
2092 if ( getColorAny( aAny
, nColorSpace
, nToMode
, nToA
, nToB
, nToC
) )
2095 rStrm
.WriteUInt32( nBits
)
2096 .WriteInt32( nByMode
).WriteInt32( nByA
).WriteInt32( nByB
).WriteInt32( nByC
)
2097 .WriteInt32( nFromMode
).WriteInt32( nFromA
).WriteInt32( nFromB
).WriteInt32( nFromC
)
2098 .WriteInt32( nToMode
).WriteInt32( nToA
).WriteInt32( nToB
).WriteInt32( nToC
);
2100 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
2103 void AnimationExporter::exportIterate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
2105 Reference
< XIterateContainer
> xIterate( xNode
, UNO_QUERY
);
2106 if ( !xIterate
.is() )
2109 EscherExAtom
aAnimIteration( rStrm
, DFF_msofbtAnimIteration
);
2111 float fInterval
= 10.0;
2112 sal_Int32 nTextUnitEffect
= 0;
2113 sal_Int32
const nU1
= 1;
2114 sal_Int32
const nU2
= 1;
2115 sal_Int32
const nU3
= 0xe;
2117 sal_Int16 nIterateType
= xIterate
->getIterateType();
2118 switch( nIterateType
)
2120 case TextAnimationType::BY_WORD
: nTextUnitEffect
= 1; break;
2121 case TextAnimationType::BY_LETTER
: nTextUnitEffect
= 2; break;
2124 fInterval
= static_cast<float>(xIterate
->getIterateInterval());
2126 // convert interval from absolute to percentage
2127 double fDuration
= 0.0;
2129 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
2130 if( xEnumerationAccess
.is() )
2132 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
2133 if( xEnumeration
.is() )
2135 while( xEnumeration
->hasMoreElements() )
2137 Reference
< XAnimate
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
2138 if( xChildNode
.is() )
2140 double fChildBegin
= 0.0;
2141 double fChildDuration
= 0.0;
2142 xChildNode
->getBegin() >>= fChildBegin
;
2143 xChildNode
->getDuration() >>= fChildDuration
;
2145 fChildDuration
+= fChildBegin
;
2146 if( fChildDuration
> fDuration
)
2147 fDuration
= fChildDuration
;
2154 fInterval
= static_cast<float>(100.0 * fInterval
/ fDuration
);
2156 rStrm
.WriteFloat( fInterval
).WriteInt32( nTextUnitEffect
).WriteInt32( nU1
).WriteInt32( nU2
).WriteInt32( nU3
);
2157 aTarget
= xIterate
->getTarget();
2162 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */