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/animations/AnimationValueType.hpp>
33 #include <com/sun/star/util/XCloneable.hpp>
34 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
35 #include <com/sun/star/animations/XAnimateSet.hpp>
36 #include <com/sun/star/animations/XAudio.hpp>
37 #include <com/sun/star/animations/XTransitionFilter.hpp>
38 #include <com/sun/star/animations/XAnimateColor.hpp>
39 #include <com/sun/star/animations/XAnimateMotion.hpp>
40 #include <com/sun/star/animations/XAnimateTransform.hpp>
41 #include <com/sun/star/animations/TransitionType.hpp>
42 #include <com/sun/star/animations/TransitionSubType.hpp>
43 #include <com/sun/star/animations/ValuePair.hpp>
44 #include <com/sun/star/animations/AnimationColorSpace.hpp>
45 #include <com/sun/star/drawing/FillStyle.hpp>
46 #include <com/sun/star/drawing/LineStyle.hpp>
47 #include <com/sun/star/awt/FontWeight.hpp>
48 #include <com/sun/star/awt/FontUnderline.hpp>
49 #include <com/sun/star/awt/FontSlant.hpp>
50 #include <com/sun/star/container/XEnumerationAccess.hpp>
51 #include <com/sun/star/presentation/ParagraphTarget.hpp>
52 #include <com/sun/star/text/XSimpleText.hpp>
53 #include <com/sun/star/animations/XIterateContainer.hpp>
54 #include <com/sun/star/presentation/TextAnimationType.hpp>
55 #include <com/sun/star/container/XChild.hpp>
56 #include <comphelper/processfactory.hxx>
57 #include <rtl/ustrbuf.hxx>
59 #include <vcl/vclenum.hxx>
60 #include <svx/svdotext.hxx>
61 #include <editeng/outlobj.hxx>
62 #include <editeng/editobj.hxx>
63 #include <pptexanimations.hxx>
64 #include <osl/endian.h>
69 using ::com::sun::star::uno::Any
;
70 using ::com::sun::star::container::XChild
;
71 using ::com::sun::star::util::XCloneable
;
72 using ::com::sun::star::uno::Reference
;
73 using ::com::sun::star::uno::UNO_QUERY
;
74 using ::com::sun::star::uno::UNO_QUERY_THROW
;
75 using ::com::sun::star::uno::Sequence
;
76 using ::com::sun::star::uno::makeAny
;
77 using ::com::sun::star::uno::Exception
;
78 using ::com::sun::star::uno::XInterface
;
79 using ::com::sun::star::beans::NamedValue
;
80 using ::com::sun::star::container::XEnumerationAccess
;
81 using ::com::sun::star::container::XEnumeration
;
82 using ::com::sun::star::lang::XMultiServiceFactory
;
84 using namespace ::com::sun::star::text
;
85 using namespace ::com::sun::star::drawing
;
86 using namespace ::com::sun::star::animations
;
87 using namespace ::com::sun::star::presentation
;
92 void ImplTranslateAttribute( OUString
& rString
, const TranslateMode eTranslateMode
)
94 if ( eTranslateMode
!= TRANSLATE_NONE
)
96 if ( ( eTranslateMode
& TRANSLATE_VALUE
) || ( eTranslateMode
& TRANSLATE_ATTRIBUTE
) )
98 const ImplAttributeNameConversion
* p
= gImplConversionList
;
101 if( rString
.equalsAscii( p
->mpAPIName
) )
107 if ( eTranslateMode
& TRANSLATE_VALUE
)
110 rString
+= OUString::createFromAscii( p
->mpMSName
);
113 rString
= OUString::createFromAscii( p
->mpMSName
);
116 else if ( eTranslateMode
& TRANSLATE_MEASURE
)
118 const sal_Char
* pDest
[] = { "#ppt_x", "#ppt_y", "#ppt_w", "#ppt_h", NULL
};
119 const sal_Char
* pSource
[] = { "x", "y", "width", "height", NULL
};
120 sal_Int32 nIndex
= 0;
122 const sal_Char
** ps
= pSource
;
123 const sal_Char
** pd
= pDest
;
127 const OUString
aSearch( OUString::createFromAscii( *ps
) );
128 while( (nIndex
= rString
.indexOf( aSearch
, nIndex
)) != -1 )
130 sal_Int32 nLength
= aSearch
.getLength();
131 if( nIndex
&& ( rString
[nIndex
-1] == '#' ) )
137 const OUString
aNew( OUString::createFromAscii( *pd
) );
138 rString
= rString
.replaceAt( nIndex
, nLength
, aNew
);
139 nIndex
+= aNew
.getLength();
148 sal_uInt32
AnimationExporter::TranslatePresetSubType( const sal_uInt32 nPresetClass
, const sal_uInt32 nPresetId
, const OUString
& rPresetSubType
)
150 sal_uInt32 nPresetSubType
= 0;
151 bool bTranslated
= false;
153 if ( ( nPresetClass
== (sal_uInt32
)EffectPresetClass::ENTRANCE
) || ( nPresetClass
== (sal_uInt32
)EffectPresetClass::EXIT
) )
155 if ( nPresetId
!= 21 )
161 if ( rPresetSubType
== "downward" )
166 else if ( rPresetSubType
== "across" )
175 if ( rPresetSubType
== "across" )
184 if ( rPresetSubType
== "right-to-top" )
189 else if ( rPresetSubType
== "right-to-bottom" )
194 else if ( rPresetSubType
== "left-to-top" )
199 else if ( rPresetSubType
== "left-to-bottom" )
210 const convert_subtype
* p
= gConvertArray
;
211 while( p
->mpStrSubType
)
213 if ( rPresetSubType
.equalsAscii( p
->mpStrSubType
) )
215 nPresetSubType
= p
->mnID
;
224 nPresetSubType
= (sal_uInt32
)rPresetSubType
.toInt32();
225 return nPresetSubType
;
228 const sal_Char
* AnimationExporter::FindTransitionName( const sal_Int16 nType
, const sal_Int16 nSubType
, const bool bDirection
)
230 const sal_Char
* pRet
= NULL
;
233 const transition
* p
= gTransitions
;
237 if ( nType
== p
->mnType
)
239 if ( nSubType
== p
->mnSubType
)
241 if ( bDirection
== p
->mbDirection
)
248 if ( nFit
== 7 ) // maximum
255 SvStream
& WriteAnimationNode(SvStream
& rOut
, AnimationNode
& rNode
)
257 rOut
.WriteInt32( rNode
.mnU1
);
258 rOut
.WriteInt32( rNode
.mnRestart
);
259 rOut
.WriteInt32( rNode
.mnGroupType
);
260 rOut
.WriteInt32( rNode
.mnFill
);
261 rOut
.WriteInt32( rNode
.mnU3
);
262 rOut
.WriteInt32( rNode
.mnU4
);
263 rOut
.WriteInt32( rNode
.mnDuration
);
264 rOut
.WriteInt32( rNode
.mnNodeType
);
269 AnimationExporter::AnimationExporter( const EscherSolverContainer
& rSolverContainer
, ppt::ExSoundCollection
& rExSoundCollection
) :
270 mrSolverContainer ( rSolverContainer
),
271 mrExSoundCollection ( rExSoundCollection
),
276 sal_Int16
AnimationExporter::GetFillMode( const Reference
< XAnimationNode
>& xNode
, const sal_Int16 nFillDefault
)
278 sal_Int16 nFill
= xNode
->getFill();
279 //#i119699 <Animation> The animation effect "Emphasis->FlashBulb" play incorrectly in Aoo saves a .ppt to another .ppt and plays the saved one.
280 //#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.
281 if ((xNode
->getType() == AnimationNodeType::ANIMATE
)
282 ||(xNode
->getType() == AnimationNodeType::SET
)
283 ||(xNode
->getType() == AnimationNodeType::TRANSITIONFILTER
))
285 if ( nFill
== AnimationFill::DEFAULT
)
289 if ( ( nFill
== AnimationFill::DEFAULT
) ||
290 ( nFill
== AnimationFill::INHERIT
) )
292 if ( nFill
!= AnimationFill::AUTO
)
293 nFill
= nFillDefault
;
295 if( nFill
== AnimationFill::AUTO
)
297 nFill
= AnimationFill::REMOVE
;
298 bool bIsIndefiniteTiming
= true;
299 Any aAny
= xNode
->getDuration();
300 if( aAny
.hasValue() )
303 if( aAny
>>= eTiming
)
304 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
306 if ( bIsIndefiniteTiming
)
308 aAny
= xNode
->getEnd();
309 if( aAny
.hasValue() )
312 if( aAny
>>= eTiming
)
313 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
315 if ( bIsIndefiniteTiming
)
317 if ( !xNode
->getRepeatCount().hasValue() )
319 aAny
= xNode
->getRepeatDuration();
320 if( aAny
.hasValue() )
323 if( aAny
>>= eTiming
)
324 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
326 if ( bIsIndefiniteTiming
)
327 nFill
= AnimationFill::FREEZE
;
335 void AnimationExporter::doexport( const Reference
< XDrawPage
>& xPage
, SvStream
& rStrm
)
337 Reference
< XAnimationNodeSupplier
> xNodeSupplier( xPage
, UNO_QUERY
);
338 if( xNodeSupplier
.is() )
340 const Reference
< XAnimationNode
> xRootNode( xNodeSupplier
->getAnimationNode() );
343 processAfterEffectNodes( xRootNode
);
344 exportNode( rStrm
, xRootNode
, NULL
, DFF_msofbtAnimGroup
, 1, 0, false, AnimationFill::AUTO
);
349 void AnimationExporter::processAfterEffectNodes( const Reference
< XAnimationNode
>& xRootNode
)
353 Reference
< XEnumerationAccess
> xEnumerationAccess( xRootNode
, UNO_QUERY_THROW
);
354 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY_THROW
);
355 while( xEnumeration
->hasMoreElements() )
357 Reference
< XAnimationNode
> xNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
359 Reference
< XEnumerationAccess
> xEnumerationAccess2( xNode
, UNO_QUERY
);
360 if ( xEnumerationAccess2
.is() )
362 Reference
< XEnumeration
> xEnumeration2( xEnumerationAccess2
->createEnumeration(), UNO_QUERY_THROW
);
363 while( xEnumeration2
->hasMoreElements() )
365 Reference
< XAnimationNode
> xChildNode( xEnumeration2
->nextElement(), UNO_QUERY_THROW
);
367 Reference
< XEnumerationAccess
> xEnumerationAccess3( xChildNode
, UNO_QUERY_THROW
);
368 Reference
< XEnumeration
> xEnumeration3( xEnumerationAccess3
->createEnumeration(), UNO_QUERY_THROW
);
369 while( xEnumeration3
->hasMoreElements() )
371 Reference
< XAnimationNode
> xChildNode2( xEnumeration3
->nextElement(), UNO_QUERY_THROW
);
373 Reference
< XEnumerationAccess
> xEnumerationAccess4( xChildNode2
, UNO_QUERY_THROW
);
374 Reference
< XEnumeration
> xEnumeration4( xEnumerationAccess4
->createEnumeration(), UNO_QUERY_THROW
);
375 while( xEnumeration4
->hasMoreElements() )
377 Reference
< XAnimationNode
> xChildNode3( xEnumeration4
->nextElement(), UNO_QUERY_THROW
);
379 switch( xChildNode3
->getType() )
381 // found an after effect
382 case AnimationNodeType::SET
:
383 case AnimationNodeType::ANIMATECOLOR
:
385 Reference
< XAnimationNode
> xMaster
;
387 Sequence
< NamedValue
> aUserData( xChildNode3
->getUserData() );
388 sal_Int32 nLength
= aUserData
.getLength();
389 const NamedValue
* p
= aUserData
.getConstArray();
393 if ( p
->Name
== "master-element" )
395 p
->Value
>>= xMaster
;
401 AfterEffectNodePtr
pAfterEffectNode( new AfterEffectNode( xChildNode3
, xMaster
) );
402 maAfterEffectNodes
.push_back( pAfterEffectNode
);
414 OSL_FAIL( "(@CL)AnimationExporter::processAfterEffectNodes(), exception caught!" );
418 bool AnimationExporter::isAfterEffectNode( const Reference
< XAnimationNode
>& xNode
) const
420 const std::list
< AfterEffectNodePtr
>::const_iterator
aEnd( maAfterEffectNodes
.end() );
421 for (std::list
< AfterEffectNodePtr
>::const_iterator
aIter( maAfterEffectNodes
.begin() );
422 aIter
!= aEnd
; ++aIter
)
424 if( (*aIter
)->mxNode
== xNode
)
430 bool AnimationExporter::hasAfterEffectNode( const Reference
< XAnimationNode
>& xNode
, Reference
< XAnimationNode
>& xAfterEffectNode
) const
432 const std::list
< AfterEffectNodePtr
>::const_iterator
aEnd( maAfterEffectNodes
.end() );
433 for (std::list
< AfterEffectNodePtr
>::const_iterator
aIter( maAfterEffectNodes
.begin() );
434 aIter
!= aEnd
; ++aIter
)
436 if( (*aIter
)->mxMaster
== xNode
)
438 xAfterEffectNode
= (*aIter
)->mxNode
;
446 // check if this group only contain empty groups. this may happen when
447 // after effect nodes are not exported at theire original position
448 bool AnimationExporter::isEmptyNode( const Reference
< XAnimationNode
>& xNode
) const
450 if( xNode
.is() ) switch( xNode
->getType() )
452 case AnimationNodeType::PAR
:
453 case AnimationNodeType::SEQ
:
454 case AnimationNodeType::ITERATE
:
456 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
457 if( xEnumerationAccess
.is() )
459 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
460 if( xEnumeration
.is() )
462 while( xEnumeration
->hasMoreElements() )
464 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
465 if( xChildNode
.is() && !isEmptyNode( xChildNode
) )
473 case AnimationNodeType::SET
:
474 case AnimationNodeType::ANIMATECOLOR
:
475 return isAfterEffectNode( xNode
);
483 void AnimationExporter::exportNode( SvStream
& rStrm
, Reference
< XAnimationNode
> xNode
, const Reference
< XAnimationNode
>* pParent
, const sal_uInt16 nContainerRecType
,
484 const sal_uInt16 nInstance
, const sal_Int32 nGroupLevel
, const bool bTakeBackInteractiveSequenceTiming
, const sal_Int16 nFDef
)
486 if( (nGroupLevel
== 4) && isEmptyNode( xNode
) )
489 if ( ( nContainerRecType
== DFF_msofbtAnimGroup
) && ( nGroupLevel
== 2 ) && isEmptyNode( xNode
) )
492 if( nContainerRecType
== DFF_msofbtAnimGroup
)
495 bool bTakeBackInteractiveSequenceTimingForChild
= false;
496 sal_Int16 nFillDefault
= GetFillMode( xNode
, nFDef
);
498 bool bSkipChildren
= false;
500 Reference
< XAnimationNode
> xAudioNode
;
501 static sal_uInt32 nAudioGroup
;
504 EscherExContainer
aContainer( rStrm
, nContainerRecType
, nInstance
);
505 switch( xNode
->getType() )
507 case AnimationNodeType::CUSTOM
:
509 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
510 exportAnimPropertySet( rStrm
, xNode
);
511 exportAnimEvent( rStrm
, xNode
, 0 );
512 exportAnimValue( rStrm
, xNode
, false );
516 case AnimationNodeType::PAR
:
518 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
519 exportAnimPropertySet( rStrm
, xNode
);
520 sal_Int32 nFlags
= nGroupLevel
== 2 ? 0x10 : 0;
521 if ( bTakeBackInteractiveSequenceTiming
)
523 exportAnimEvent( rStrm
, xNode
, nFlags
);
524 exportAnimValue( rStrm
, xNode
, nGroupLevel
== 4 );
528 case AnimationNodeType::SEQ
:
530 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
531 sal_Int16 nNodeType
= exportAnimPropertySet( rStrm
, xNode
);
532 sal_Int32 nFlags
= 12;
533 if ( ( nGroupLevel
== 1 ) && ( nNodeType
== ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
) )
536 bTakeBackInteractiveSequenceTimingForChild
= true;
538 exportAnimAction( rStrm
, xNode
);
539 exportAnimEvent( rStrm
, xNode
, nFlags
);
540 exportAnimValue( rStrm
, xNode
, false );
544 case AnimationNodeType::ITERATE
:
547 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
549 memset( &aAnim
, 0, sizeof( aAnim
) );
550 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
551 aAnim
.mnNodeType
= 1;
553 switch( xNode
->getRestart() )
556 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
557 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
558 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
559 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
562 switch( xNode
->getFill() )
565 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
566 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
567 case AnimationFill::FREEZE
: aAnim
.mnFill
= 2; break;
568 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
569 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
571 WriteAnimationNode( rStrm
, aAnim
);
573 exportIterate( rStrm
, xNode
);
574 exportAnimPropertySet( rStrm
, xNode
);
575 exportAnimEvent( rStrm
, xNode
, 0 );
576 exportAnimValue( rStrm
, xNode
, false );
580 case AnimationNodeType::ANIMATE
:
582 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
583 exportAnimPropertySet( rStrm
, xNode
);
584 exportAnimEvent( rStrm
, xNode
, 0 );
585 exportAnimValue( rStrm
, xNode
, false );
586 exportAnimate( rStrm
, xNode
);
590 case AnimationNodeType::SET
:
592 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
593 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
595 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
596 exportAnimPropertySet( rStrm
, xNode
);
597 exportAnimateSet( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_SET
: AFTEREFFECT_NONE
);
598 exportAnimEvent( rStrm
, xNode
, 0 );
599 exportAnimValue( rStrm
, xNode
, false );
603 bSkipChildren
= true;
608 case AnimationNodeType::ANIMATEMOTION
:
610 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
611 exportAnimPropertySet( rStrm
, xNode
);
612 exportAnimateMotion( rStrm
, xNode
);
613 exportAnimEvent( rStrm
, xNode
, 0 );
614 exportAnimValue( rStrm
, xNode
, false );
618 case AnimationNodeType::ANIMATECOLOR
:
620 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
621 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
623 if( bIsAfterEffectNode
)
624 xNode
= createAfterEffectNodeClone( xNode
);
626 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
627 exportAnimPropertySet( rStrm
, xNode
);
628 exportAnimateColor( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_COLOR
: AFTEREFFECT_NONE
);
629 exportAnimEvent( rStrm
, xNode
, 0 );
630 exportAnimValue( rStrm
, xNode
, false );
634 bSkipChildren
= true;
639 case AnimationNodeType::ANIMATETRANSFORM
:
641 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
642 exportAnimPropertySet( rStrm
, xNode
);
643 exportAnimateTransform( rStrm
, xNode
);
644 exportAnimEvent( rStrm
, xNode
, 0 );
645 exportAnimValue( rStrm
, xNode
, false );
649 case AnimationNodeType::TRANSITIONFILTER
:
651 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
652 exportAnimPropertySet( rStrm
, xNode
);
653 exportAnimEvent( rStrm
, xNode
, 0 );
654 exportAnimValue( rStrm
, xNode
, false );
655 exportTransitionFilter( rStrm
, xNode
);
659 case AnimationNodeType::AUDIO
: // #i58428#
661 exportAnimNode( rStrm
, xNode
, pParent
, nGroupLevel
, nFillDefault
);
662 exportAnimPropertySet( rStrm
, xNode
);
664 Reference
< XAudio
> xAudio( xNode
, UNO_QUERY
);
667 Any
aAny( xAudio
->getSource() );
670 if ( ( aAny
>>= aURL
) && !aURL
.isEmpty() )
673 sal_Int32 nTrigger
= 3;
674 sal_Int32 nU3
= nAudioGroup
;
675 sal_Int32 nBegin
= 0;
677 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 1 );
679 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
680 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
687 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 2 );
689 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
690 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
693 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
695 sal_uInt32 nRefMode
= 3;
696 sal_uInt32 nRefType
= 2;
697 sal_uInt32 nRefId
= mrExSoundCollection
.GetId( aURL
);
698 sal_Int32 begin
= -1;
701 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
702 rStrm
.WriteUInt32( nRefMode
).WriteUInt32( nRefType
).WriteUInt32( nRefId
).WriteInt32( begin
).WriteInt32( end
);
706 exportAnimValue( rStrm
, xNode
, false );
712 // export after effect node if one exists for this node
713 Reference
< XAnimationNode
> xAfterEffectNode
;
714 if( hasAfterEffectNode( xNode
, xAfterEffectNode
) )
716 exportNode( rStrm
, xAfterEffectNode
, &xNode
, DFF_msofbtAnimSubGoup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
719 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
720 if( xEnumerationAccess
.is() )
722 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
723 if( xEnumeration
.is() )
725 while( xEnumeration
->hasMoreElements() )
727 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
728 if( xChildNode
.is() )
730 if ( xChildNode
->getType() == AnimationNodeType::AUDIO
)
732 xAudioNode
= xChildNode
;
733 nAudioGroup
= mnCurrentGroup
;
736 exportNode( rStrm
, xChildNode
, &xNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
743 if ( xAudioNode
.is() )
744 exportNode( rStrm
, xAudioNode
, &xNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
746 if( xNode
->getType() == AnimationNodeType::ITERATE
)
750 Reference
< XAnimationNode
> AnimationExporter::createAfterEffectNodeClone( const Reference
< XAnimationNode
>& xNode
)
754 Reference
< ::com::sun::star::util::XCloneable
> xClonable( xNode
, UNO_QUERY_THROW
);
755 Reference
< XAnimationNode
> xCloneNode( xClonable
->createClone(), UNO_QUERY_THROW
);
758 xCloneNode
->setBegin( aEmpty
);
764 OSL_FAIL("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
769 bool AnimationExporter::GetNodeType( const Reference
< XAnimationNode
>& xNode
, sal_Int16
& nType
)
771 // trying to get the nodetype
772 Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
773 if ( aUserData
.getLength() )
775 const NamedValue
* p
= aUserData
.getConstArray();
776 sal_Int32 nLength
= aUserData
.getLength();
779 if ( p
->Name
== "node-type" )
781 if ( p
->Value
>>= nType
)
790 void AnimationExporter::exportAnimNode( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
,
791 const ::com::sun::star::uno::Reference
< ::com::sun::star::animations::XAnimationNode
>*, const sal_Int32
, const sal_Int16 nFillDefault
)
793 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
795 memset( &aAnim
, 0, sizeof( aAnim
) );
798 switch( xNode
->getRestart() )
801 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
802 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
803 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
804 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
807 switch( nFillDefault
)
810 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
811 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
812 case AnimationFill::FREEZE
:
813 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
814 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
816 // attribute Duration
817 double fDuration
= 0.0;
818 com::sun::star::animations::Timing eTiming
;
819 if ( xNode
->getDuration() >>= eTiming
)
821 if ( eTiming
== Timing_INDEFINITE
)
822 aAnim
.mnDuration
= -1;
824 else if ( xNode
->getDuration() >>= fDuration
)
826 aAnim
.mnDuration
= (sal_Int32
)( fDuration
* 1000.0 );
829 aAnim
.mnDuration
= -1;
831 // NodeType, NodeGroup
832 aAnim
.mnNodeType
= 1;
833 aAnim
.mnGroupType
= mso_Anim_GroupType_SEQ
;
834 switch( xNode
->getType() )
836 case AnimationNodeType::PAR
:
837 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
838 // PASSTROUGH!!! (as it was intended)
839 case AnimationNodeType::SEQ
:
842 if( GetNodeType( xNode
, nType
) )
845 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT
: aAnim
.mnNodeType
= 0x12; break;
846 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE
: aAnim
.mnNodeType
= 0x18; break;
851 case AnimationNodeType::ANIMATE
:
852 case AnimationNodeType::SET
:
854 case AnimationNodeType::CUSTOM
:
855 case AnimationNodeType::ITERATE
:
856 case AnimationNodeType::ANIMATEMOTION
:
857 case AnimationNodeType::ANIMATECOLOR
:
858 case AnimationNodeType::ANIMATETRANSFORM
:
860 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
861 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
865 case AnimationNodeType::AUDIO
:
867 aAnim
.mnGroupType
= mso_Anim_GroupType_MEDIA
;
868 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
872 case AnimationNodeType::TRANSITIONFILTER
:
874 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
875 aAnim
.mnNodeType
= mso_Anim_Behaviour_FILTER
;
880 WriteAnimationNode( rStrm
, aAnim
);
883 void AnimationExporter::GetUserData( const Sequence
< NamedValue
>& rUserData
, const Any
** pAny
, sal_Size nLen
)
885 // storing user data into pAny, to allow direct access later
886 memset( pAny
, 0, nLen
);
887 if ( rUserData
.getLength() )
889 const NamedValue
* p
= rUserData
.getConstArray();
890 sal_Int32 nLength
= rUserData
.getLength();
893 if ( p
->Name
== "node-type" )
895 pAny
[ DFF_ANIM_NODE_TYPE
] = &(p
->Value
);
897 else if ( p
->Name
== "preset-class" )
899 pAny
[ DFF_ANIM_PRESET_CLASS
] = &(p
->Value
);
901 else if ( p
->Name
== "preset-id" )
903 pAny
[ DFF_ANIM_PRESET_ID
] = &(p
->Value
);
905 else if ( p
->Name
== "preset-sub-type" )
907 pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] = &(p
->Value
);
909 else if ( p
->Name
== "master-element" )
911 pAny
[ DFF_ANIM_AFTEREFFECT
] = &(p
->Value
);;
918 sal_uInt32
AnimationExporter::GetPresetID( const OUString
& rPreset
, sal_uInt32 nAPIPresetClass
, bool& bPresetId
)
920 sal_uInt32 nPresetId
= 0;
923 if ( rPreset
.match( OUString( "ppt_" ), 0 ) )
925 sal_Int32 nLast
= rPreset
.lastIndexOf( '_' );
926 if ( ( nLast
!= -1 ) && ( ( nLast
+ 1 ) < rPreset
.getLength() ) )
928 OUString
aNumber( rPreset
.copy( nLast
+ 1 ) );
929 nPresetId
= aNumber
.toInt32();
935 const preset_maping
* p
= gPresetMaping
;
936 while( p
->mpStrPresetId
&& ((p
->mnPresetClass
!= (sal_Int32
)nAPIPresetClass
) || !rPreset
.equalsAscii( p
->mpStrPresetId
)) )
939 if( p
->mpStrPresetId
)
941 nPresetId
= p
->mnPresetId
;
949 sal_Int16
AnimationExporter::exportAnimPropertySet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
951 sal_Int16 nNodeType
= ::com::sun::star::presentation::EffectNodeType::DEFAULT
;
953 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
955 Reference
< XAnimationNode
> xMaster
;
957 Any aMasterRel
, aOverride
, aRunTimeContext
;
959 // storing user data into pAny, to allow direct access later
960 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
961 const ::com::sun::star::uno::Any
* pAny
[ DFF_ANIM_PROPERTY_ID_COUNT
];
962 GetUserData( aUserData
, pAny
, sizeof( pAny
) );
964 if( pAny
[ DFF_ANIM_AFTEREFFECT
] )
965 ( *pAny
[ DFF_ANIM_AFTEREFFECT
] ) >>= xMaster
;
967 // calculate master-rel
970 sal_Int32 nMasterRel
= 2;
971 if( xNode
.is() && xMaster
.is() && (xNode
->getParent() == xMaster
->getParent() ) )
974 aMasterRel
<<= nMasterRel
;
976 pAny
[ DFF_ANIM_MASTERREL
] = &aMasterRel
;
978 aOverride
<<= (sal_Int32
)1;
979 pAny
[ DFF_ANIM_OVERRIDE
] = &aOverride
;
981 aRunTimeContext
<<= (sal_Int32
)1;
982 pAny
[ DFF_ANIM_RUNTIMECONTEXT
] = &aRunTimeContext
;
985 // the order is important
986 if ( pAny
[ DFF_ANIM_NODE_TYPE
] )
988 if ( *pAny
[ DFF_ANIM_NODE_TYPE
] >>= nNodeType
)
990 sal_uInt32 nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
;
993 case ::com::sun::star::presentation::EffectNodeType::ON_CLICK
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
; break;
994 case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_WITH_PREVIOUS
; break;
995 case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS
; break;
996 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE
; break;
997 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_TIMING_ROOT
; break;
998 case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ
; break;
1000 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_NODE_TYPE
, nPPTNodeType
, TRANSLATE_NONE
);
1003 sal_uInt32 nPresetId
= 0;
1004 sal_uInt32 nPresetSubType
= 0;
1005 sal_uInt32 nAPIPresetClass
= EffectPresetClass::CUSTOM
;
1006 sal_uInt32 nPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
1007 bool bPresetClass
, bPresetId
, bPresetSubType
;
1008 bPresetId
= bPresetClass
= bPresetSubType
= false;
1010 if ( pAny
[ DFF_ANIM_PRESET_CLASS
] )
1012 if ( *pAny
[ DFF_ANIM_PRESET_CLASS
] >>= nAPIPresetClass
)
1014 sal_uInt8 nPPTPresetClass
;
1015 switch( nAPIPresetClass
)
1017 case EffectPresetClass::ENTRANCE
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_ENTRANCE
; break;
1018 case EffectPresetClass::EXIT
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EXIT
; break;
1019 case EffectPresetClass::EMPHASIS
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EMPHASIS
; break;
1020 case EffectPresetClass::MOTIONPATH
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MOTIONPATH
; break;
1021 case EffectPresetClass::OLEACTION
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_OLE_ACTION
; break;
1022 case EffectPresetClass::MEDIACALL
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MEDIACALL
; break;
1024 nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
1026 nPresetClass
= nPPTPresetClass
;
1027 bPresetClass
= true;
1030 if ( pAny
[ DFF_ANIM_PRESET_ID
] )
1033 if ( *pAny
[ DFF_ANIM_PRESET_ID
] >>= sPreset
)
1034 nPresetId
= GetPresetID( sPreset
, nAPIPresetClass
, bPresetId
);
1037 if ( pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] )
1039 OUString sPresetSubType
;
1040 if ( *pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] >>= sPresetSubType
)
1042 nPresetSubType
= TranslatePresetSubType( nPresetClass
, nPresetId
, sPresetSubType
);
1043 bPresetSubType
= true;
1047 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_ID
, nPresetId
, TRANSLATE_NONE
);
1048 if ( bPresetSubType
)
1049 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_SUB_TYPE
, nPresetSubType
, TRANSLATE_NONE
);
1051 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_CLASS
, nPresetClass
, TRANSLATE_NONE
);
1053 if ( pAny
[ DFF_ANIM_ID
] )
1058 if ( pAny
[ DFF_ANIM_AFTEREFFECT
] )
1060 bool bAfterEffect
= false;
1061 if ( *pAny
[ DFF_ANIM_AFTEREFFECT
] >>= bAfterEffect
)
1062 exportAnimPropertyByte( rStrm
, DFF_ANIM_AFTEREFFECT
, int(bAfterEffect
), TRANSLATE_NONE
);
1065 if ( pAny
[ DFF_ANIM_RUNTIMECONTEXT
] )
1067 sal_Int32 nRunTimeContext
= 0;
1068 if ( *pAny
[ DFF_ANIM_RUNTIMECONTEXT
] >>= nRunTimeContext
)
1069 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_RUNTIMECONTEXT
, nRunTimeContext
, TRANSLATE_NONE
);
1071 if ( pAny
[ DFF_ANIM_PATH_EDIT_MODE
] )
1078 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
1082 bool bDirection
= !xColor
->getDirection();
1083 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_DIRECTION
, bDirection
? 1 : 0, TRANSLATE_NONE
);
1087 if ( pAny
[ DFF_ANIM_OVERRIDE
] )
1089 sal_Int32 nOverride
= 0;
1090 if ( *pAny
[ DFF_ANIM_OVERRIDE
] >>= nOverride
)
1091 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_OVERRIDE
, nOverride
, TRANSLATE_NONE
);
1094 if ( pAny
[ DFF_ANIM_MASTERREL
] )
1096 sal_Int32 nMasterRel
= 0;
1097 if ( *pAny
[ DFF_ANIM_MASTERREL
] >>= nMasterRel
)
1098 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_MASTERREL
, nMasterRel
, TRANSLATE_NONE
);
1102 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1105 sal_Int16 nEndAfterSlide = 0;
1106 nEndAfterSlide = xAudio->getEndAfterSlide();
1107 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1110 Reference
< XAnimate
> xAnim( xNode
, UNO_QUERY
);
1113 // TODO: DFF_ANIM_TIMEFILTER
1115 if ( pAny
[ DFF_ANIM_EVENT_FILTER
] )
1117 // TODO DFF_ANIM_EVENT_FILTER
1119 if ( pAny
[ DFF_ANIM_VOLUME
] )
1121 // TODO DFF_ANIM_VOLUME
1126 bool AnimationExporter::exportAnimProperty( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const ::com::sun::star::uno::Any
& rAny
, const TranslateMode eTranslateMode
)
1129 if ( rAny
.hasValue() )
1131 switch( rAny
.getValueType().getTypeClass() )
1133 case ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT
:
1134 case ::com::sun::star::uno::TypeClass_SHORT
:
1135 case ::com::sun::star::uno::TypeClass_UNSIGNED_LONG
:
1136 case ::com::sun::star::uno::TypeClass_LONG
:
1139 if ( rAny
>>= nVal
)
1141 exportAnimPropertyuInt32( rStrm
, nPropertyId
, nVal
, eTranslateMode
);
1147 case ::com::sun::star::uno::TypeClass_DOUBLE
:
1150 if ( rAny
>>= fVal
)
1152 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
, eTranslateMode
);
1157 case ::com::sun::star::uno::TypeClass_FLOAT
:
1160 if ( rAny
>>= fVal
)
1162 if ( eTranslateMode
& TRANSLATE_NUMBER_TO_STRING
)
1165 OUString
aNumber( OUString::number( fVal
) );
1167 exportAnimPropertyString( rStrm
, nPropertyId
, aNumber
, eTranslateMode
);
1171 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
, eTranslateMode
);
1177 case ::com::sun::star::uno::TypeClass_STRING
:
1180 if ( rAny
>>= aStr
)
1182 exportAnimPropertyString( rStrm
, nPropertyId
, aStr
, eTranslateMode
);
1193 void AnimationExporter::exportAnimPropertyString( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const OUString
& rVal
, const TranslateMode eTranslateMode
)
1195 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1196 sal_uInt8 nType
= DFF_ANIM_PROP_TYPE_UNISTRING
;
1197 rStrm
.WriteUChar( nType
);
1198 OUString
aStr( rVal
);
1199 if ( eTranslateMode
!= TRANSLATE_NONE
)
1200 ImplTranslateAttribute( aStr
, eTranslateMode
);
1201 writeZString( rStrm
, aStr
);
1204 void AnimationExporter::exportAnimPropertyFloat( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const double& rVal
, const TranslateMode
)
1206 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1207 sal_uInt8 nType
= DFF_ANIM_PROP_TYPE_FLOAT
;
1208 float fFloat
= (float)rVal
;
1209 rStrm
.WriteUChar( nType
)
1210 .WriteFloat( fFloat
);
1213 void AnimationExporter::exportAnimPropertyuInt32( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt32 nVal
, const TranslateMode
)
1215 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1216 sal_uInt8 nType
= DFF_ANIM_PROP_TYPE_INT32
;
1217 rStrm
.WriteUChar( nType
)
1218 .WriteUInt32( nVal
);
1221 void AnimationExporter::exportAnimPropertyByte( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt8 nVal
, const TranslateMode
)
1223 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1224 sal_uInt8 nType
= DFF_ANIM_PROP_TYPE_BYTE
;
1225 rStrm
.WriteUChar( nType
)
1226 .WriteUChar( nVal
);
1229 void AnimationExporter::writeZString( SvStream
& rStrm
, const OUString
& rVal
)
1232 for ( i
= 0; i
< rVal
.getLength(); i
++ )
1233 rStrm
.WriteUInt16( rVal
[ i
] );
1234 rStrm
.WriteUInt16( 0 );
1237 void AnimationExporter::exportAnimAction( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1239 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAction
);
1241 sal_Int32 nConcurrent
= 1;
1242 sal_Int32 nNextAction
= 1;
1243 sal_Int32 nEndSync
= 0;
1247 sal_Int16 nAnimationEndSync
= 0;
1248 if ( xNode
->getEndSync() >>= nAnimationEndSync
)
1250 if ( nAnimationEndSync
== AnimationEndSync::ALL
)
1253 rStrm
.WriteInt32( nConcurrent
)
1254 .WriteInt32( nNextAction
)
1255 .WriteInt32( nEndSync
)
1261 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1262 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1263 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
1264 void AnimationExporter::exportAnimEvent( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_Int32 nFlags
)
1267 for ( i
= 0; i
< 4; i
++ )
1270 sal_Int32 nTrigger
= 0;
1272 sal_Int32 nBegin
= 0;
1274 bool bCreateEvent
= false;
1284 com::sun::star::animations::Timing eTiming
;
1287 if ( nFlags
& 0x20 )
1289 // taking the first child
1290 Reference
< XEnumerationAccess
> xEA( xNode
, UNO_QUERY_THROW
);
1291 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), UNO_QUERY_THROW
);
1292 if ( xE
.is() && xE
->hasMoreElements() )
1295 Reference
< XAnimationNode
> xClickNode( xE
->nextElement(), UNO_QUERY
);
1296 aAny
= xClickNode
->getBegin();
1300 else if ( nFlags
& 0x40 )
1302 // begin has to be replaced with void, so don't do anything
1306 aAny
= xNode
->getBegin();
1307 if ( nFlags
& 0x10 ) // replace ON_NEXT with IDEFINITE
1309 if ( ( aAny
>>= aEvent
) && ( aEvent
.Trigger
== EventTrigger::ON_NEXT
) )
1311 eTiming
= Timing_INDEFINITE
;
1318 aAny
= xNode
->getEnd();
1320 double fTiming
= 0.0;
1321 if ( aAny
>>= aEvent
)
1323 bCreateEvent
= true;
1324 switch( aEvent
.Trigger
)
1326 case EventTrigger::NONE
: nTrigger
= 0; break;
1327 case EventTrigger::ON_BEGIN
: nTrigger
= 1; break;
1328 case EventTrigger::ON_END
: nTrigger
= 2; break;
1329 case EventTrigger::BEGIN_EVENT
: nTrigger
= 3; break;
1330 case EventTrigger::END_EVENT
: nTrigger
= 4; nU1
= 2; nU3
= mnCurrentGroup
; break;
1331 case EventTrigger::ON_CLICK
: nTrigger
= 5; break;
1332 case EventTrigger::ON_DBL_CLICK
: nTrigger
= 6; break;
1333 case EventTrigger::ON_MOUSE_ENTER
: nTrigger
= 7; break;
1334 case EventTrigger::ON_MOUSE_LEAVE
: nTrigger
= 8; break;
1335 case EventTrigger::ON_NEXT
: nTrigger
= 9; break;
1336 case EventTrigger::ON_PREV
: nTrigger
= 10; break;
1337 case EventTrigger::ON_STOP_AUDIO
: nTrigger
= 11; break;
1339 if ( aEvent
.Offset
.hasValue() )
1341 if ( aEvent
.Offset
>>= eTiming
)
1343 if ( eTiming
== Timing_INDEFINITE
)
1346 else if ( aEvent
.Offset
>>= fTiming
)
1347 nBegin
= (sal_Int32
)( fTiming
* 1000.0 );
1349 aSource
= aEvent
.Source
;
1351 else if ( aAny
>>= eTiming
)
1353 bCreateEvent
= true;
1354 if ( eTiming
== Timing_INDEFINITE
)
1357 else if ( aAny
>>= fTiming
)
1359 bCreateEvent
= true;
1360 nBegin
= (sal_Int32
)( fTiming
* 1000.0 );
1367 if ( nFlags
& ( 1 << i
) )
1369 bCreateEvent
= true;
1377 if ( nFlags
& ( 1 << i
) )
1379 bCreateEvent
= true;
1388 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, i
+ 1 );
1390 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
1391 rStrm
.WriteInt32( nU1
)
1392 .WriteInt32( nTrigger
)
1394 .WriteInt32( nBegin
);
1396 exportAnimateTargetElement( rStrm
, aSource
, ( nFlags
& ( 1 << i
) ) != 0 );
1401 Any
AnimationExporter::convertAnimateValue( const Any
& rSourceValue
, const OUString
& rAttributeName
)
1404 if ( rAttributeName
== "X"
1405 || rAttributeName
== "Y"
1406 || rAttributeName
== "Width"
1407 || rAttributeName
== "Height"
1411 if ( rSourceValue
>>= aStr
)
1413 ImplTranslateAttribute( aStr
, TRANSLATE_MEASURE
);
1417 else if ( rAttributeName
== "Rotate" // "r" or "style.rotation" ?
1418 || rAttributeName
== "SkewX"
1419 || rAttributeName
== "Opacity"
1420 || rAttributeName
== "CharHeight"
1423 double fNumber
= 0.0;
1424 if ( rSourceValue
>>= fNumber
)
1425 aDest
+= OUString::number( fNumber
);
1427 else if ( rAttributeName
== "Color"
1428 || rAttributeName
== "FillColor" // "Fillcolor" or "FillColor" ?
1429 || rAttributeName
== "LineColor"
1430 || rAttributeName
== "CharColor"
1433 sal_Int32 nColor
= 0;
1434 Sequence
< double > aHSL( 3 );
1436 if ( rSourceValue
>>= aHSL
)
1439 aDest
+= OUString::number( (sal_Int32
)( aHSL
[ 0 ] / ( 360.0 / 255 ) ) );
1441 aDest
+= OUString::number( (sal_Int32
)( aHSL
[ 1 ] * 255.0 ) );
1443 aDest
+= OUString::number( (sal_Int32
)( aHSL
[ 2 ] * 255.0 ) );
1446 else if ( rSourceValue
>>= nColor
)
1449 aDest
+= OUString::number( ( (sal_Int8
)nColor
) );
1451 aDest
+= OUString::number( ( (sal_Int8
)( nColor
>> 8 ) ) );
1453 aDest
+= OUString::number( ( (sal_Int8
)( nColor
>> 16 ) ) );
1457 else if ( rAttributeName
== "FillStyle" )
1459 ::com::sun::star::drawing::FillStyle eFillStyle
;
1460 if ( rSourceValue
>>= eFillStyle
)
1462 if ( eFillStyle
== ::com::sun::star::drawing::FillStyle_NONE
)
1463 aDest
+= "none"; // ?
1468 else if ( rAttributeName
== "LineStyle" )
1470 ::com::sun::star::drawing::LineStyle eLineStyle
;
1471 if ( rSourceValue
>>= eLineStyle
)
1473 if ( eLineStyle
== ::com::sun::star::drawing::LineStyle_NONE
)
1479 else if ( rAttributeName
== "CharWeight" )
1481 float fFontWeight
= 0.0;
1482 if ( rSourceValue
>>= fFontWeight
)
1484 if ( fFontWeight
== com::sun::star::awt::FontWeight::BOLD
)
1490 else if ( rAttributeName
== "CharUnderline" )
1492 sal_Int16 nFontUnderline
= 0;
1493 if ( rSourceValue
>>= nFontUnderline
)
1495 if ( nFontUnderline
== com::sun::star::awt::FontUnderline::NONE
)
1501 else if ( rAttributeName
== "CharPosture" )
1503 ::com::sun::star::awt::FontSlant eFontSlant
;
1504 if ( rSourceValue
>>= eFontSlant
)
1506 if ( eFontSlant
== com::sun::star::awt::FontSlant_ITALIC
)
1509 aDest
+= "normal"; // ?
1512 else if ( rAttributeName
== "Visibility" )
1514 bool bVisible
= true;
1515 if ( rSourceValue
>>= bVisible
)
1524 if ( !aDest
.isEmpty() )
1527 aRet
= rSourceValue
;
1531 void AnimationExporter::exportAnimateSet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
1533 Reference
< XAnimateSet
> xSet( xNode
, UNO_QUERY
);
1536 EscherExContainer
aAnimateSet( rStrm
, DFF_msofbtAnimateSet
, 0 );
1538 EscherExAtom
aAnimateSetData( rStrm
, DFF_msofbtAnimateSetData
);
1539 sal_uInt32 nId1
= 1; // ??
1540 sal_uInt32 nId2
= 1; // ??
1541 rStrm
.WriteUInt32( nId1
).WriteUInt32( nId2
);
1543 Any
aConvertedValue( convertAnimateValue( xSet
->getTo(), xSet
->getAttributeName() ) );
1544 if ( aConvertedValue
.hasValue() )
1545 exportAnimProperty( rStrm
, 1, aConvertedValue
, TRANSLATE_NONE
);
1546 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
1550 sal_uInt32
AnimationExporter::GetValueTypeForAttributeName( const OUString
& rAttributeName
)
1552 sal_uInt32 nValueType
= 0;
1556 const sal_Char
* pName
;
1559 static const Entry lcl_attributeMap
[] =
1562 { "charfontname", 0 },
1563 { "charheight", 1 },
1564 { "charposture", 0 },
1565 // TODO(Q1): This should prolly be changed in PPT import
1566 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1567 { "charrotation", 1 },
1568 { "charunderline", 0 },
1569 { "charweight", 0 },
1581 { "visibility", 1 },
1587 const Entry
* pPtr
= &lcl_attributeMap
[ 0 ];
1588 while( pPtr
->pName
)
1590 if ( rAttributeName
.equalsIgnoreAsciiCaseAscii( pPtr
->pName
) )
1592 nValueType
= pPtr
->nType
;
1597 DBG_ASSERT( pPtr
->pName
, "GetValueTypeForAttributeName, unknown property value!" );
1601 void AnimationExporter::exportAnimate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1603 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1604 if ( xAnimate
.is() )
1606 Any
aBy ( xAnimate
->getBy() );
1607 Any
aFrom( xAnimate
->getFrom() );
1608 Any
aTo ( xAnimate
->getTo() );
1610 EscherExContainer
aContainer( rStrm
, DFF_msofbtAnimate
, 0 );
1612 EscherExAtom
aAnimateData( rStrm
, DFF_msofbtAnimateData
);
1613 sal_uInt32 nBits
= 0x38;
1614 sal_Int16 nTmp
= xAnimate
->getCalcMode();
1615 sal_uInt32 nCalcMode
= /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp
== AnimationCalcMode::LINEAR
) ? 1 : 0;
1616 nTmp
= xAnimate
->getValueType();
1617 sal_uInt32 nValueType
= GetValueTypeForAttributeName( xAnimate
->getAttributeName() );
1619 if ( aBy
.hasValue() )
1621 if ( aFrom
.hasValue() )
1623 if ( aTo
.hasValue() )
1626 rStrm
.WriteUInt32( nCalcMode
)
1627 .WriteUInt32( nBits
)
1628 .WriteUInt32( nValueType
);
1630 if ( aBy
.hasValue() )
1631 exportAnimProperty( rStrm
, 1, aBy
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1632 if ( aFrom
.hasValue() )
1633 exportAnimProperty( rStrm
, 2, aFrom
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1634 if ( aTo
.hasValue() )
1635 exportAnimProperty( rStrm
, 3, aTo
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1637 exportAnimateKeyPoints( rStrm
, xAnimate
);
1638 exportAnimateTarget( rStrm
, xNode
);
1642 void AnimationExporter::exportAnimateTarget( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_uInt32 nForceAttributeNames
, int nAfterEffectType
)
1644 EscherExContainer
aAnimateTarget( rStrm
, DFF_msofbtAnimateTarget
, 0 );
1645 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1646 if ( xAnimate
.is() )
1649 EscherExAtom
aAnimateTargetSettings( rStrm
, DFF_msofbtAnimateTargetSettings
, 0 );
1650 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1651 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1652 // nAccumulate 0 = none, 1 = always
1653 // nTransformType 0: "property" else "image"
1654 sal_uInt32 nBits
= 0;
1655 sal_uInt32 nAdditive
= 0;
1656 sal_uInt32 nAccumulate
= 0;
1657 sal_uInt32 nTransformType
= 0;
1658 if ( xAnimate
.is() )
1660 if ( !xAnimate
->getAttributeName().isEmpty() )
1661 nBits
|= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1662 sal_Int16 nAdditiveMode
= xAnimate
->getAdditive();
1663 if ( nAdditiveMode
!= AnimationAdditiveMode::BASE
)
1666 switch( nAdditiveMode
)
1668 case AnimationAdditiveMode::SUM
: nAdditive
= 1; break;
1669 case AnimationAdditiveMode::REPLACE
: nAdditive
= 2; break;
1670 case AnimationAdditiveMode::MULTIPLY
: nAdditive
= 3; break;
1671 case AnimationAdditiveMode::NONE
: nAdditive
= 4; break;
1674 if ( xAnimate
->getAccumulate() )
1680 rStrm
.WriteUInt32( nBits
)
1681 .WriteUInt32( nAdditive
)
1682 .WriteUInt32( nAccumulate
)
1683 .WriteUInt32( nTransformType
);
1685 if ( !xAnimate
->getAttributeName().isEmpty() || nForceAttributeNames
)
1687 EscherExContainer
aAnimateAttributeNames( rStrm
, DFF_msofbtAnimateAttributeNames
, 1 );
1688 OUString
aAttributeName( xAnimate
->getAttributeName() );
1689 if ( nForceAttributeNames
)
1691 if( nForceAttributeNames
== 1 )
1693 aAttributeName
= "r";
1696 sal_Int32 nIndex
= 0;
1699 OUString
aToken( aAttributeName
.getToken( 0, ';', nIndex
) );
1700 exportAnimPropertyString( rStrm
, 0, aToken
, TRANSLATE_ATTRIBUTE
);
1702 while ( nIndex
>= 0 );
1705 if( nAfterEffectType
!= AFTEREFFECT_NONE
)
1707 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
1708 exportAnimPropertyuInt32( rStrm
, 6, 1, TRANSLATE_NONE
);
1709 if( nAfterEffectType
== AFTEREFFECT_COLOR
)
1711 exportAnimPropertyuInt32( rStrm
, 4, 0, TRANSLATE_NONE
);
1712 exportAnimPropertyuInt32( rStrm
, 5, 0, TRANSLATE_NONE
);
1715 exportAnimateTargetElement( rStrm
, aTarget
.hasValue() ? aTarget
: xAnimate
->getTarget(), false );
1719 Reference
< XShape
> AnimationExporter::getTargetElementShape( const Any
& rAny
, sal_Int32
& rBegin
, sal_Int32
& rEnd
, bool& rParagraphTarget
)
1721 Reference
< XShape
> xShape
;
1724 rParagraphTarget
= false;
1728 ParagraphTarget aParaTarget
;
1729 if( rAny
>>= aParaTarget
)
1730 xShape
= aParaTarget
.Shape
;
1733 // now calculating the character range for the paragraph
1734 sal_Int16 nParagraph
= aParaTarget
.Paragraph
;
1735 Reference
< XSimpleText
> xText( xShape
, UNO_QUERY
);
1738 rParagraphTarget
= true;
1739 Reference
< XEnumerationAccess
> xTextParagraphEnumerationAccess( xText
, UNO_QUERY
);
1740 if ( xTextParagraphEnumerationAccess
.is() )
1742 Reference
< XEnumeration
> xTextParagraphEnumeration( xTextParagraphEnumerationAccess
->createEnumeration() );
1743 if ( xTextParagraphEnumeration
.is() )
1745 sal_Int16 nCurrentParagraph
;
1746 rBegin
= rEnd
= nCurrentParagraph
= 0;
1747 while ( xTextParagraphEnumeration
->hasMoreElements() )
1749 Reference
< XTextRange
> xTextRange( xTextParagraphEnumeration
->nextElement(), UNO_QUERY
);
1750 if ( xTextRange
.is() )
1752 OUString
aParaText( xTextRange
->getString() );
1753 sal_Int32 nLength
= aParaText
.getLength() + 1;
1755 if ( nCurrentParagraph
== nParagraph
)
1757 nCurrentParagraph
++;
1770 void AnimationExporter::exportAnimateTargetElement( SvStream
& rStrm
, const Any
& rAny
, const bool bCreate2b01Atom
)
1772 sal_uInt32 nRefMode
= 0; // nRefMode == 2 -> Paragraph
1773 sal_Int32 begin
= -1;
1775 bool bParagraphTarget
;
1777 Reference
< XShape
> xShape
= getTargetElementShape(rAny
, begin
, end
, bParagraphTarget
);
1779 if( bParagraphTarget
)
1782 if ( xShape
.is() || bCreate2b01Atom
)
1784 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
1787 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
1789 sal_uInt32 nRefType
= 1; // TODO: nRefType == 2 -> Sound;
1790 sal_uInt32 nRefId
= ((EscherSolverContainer
&)mrSolverContainer
).GetShapeId( xShape
);
1792 rStrm
.WriteUInt32( nRefMode
)
1793 .WriteUInt32( nRefType
)
1794 .WriteUInt32( nRefId
)
1795 .WriteInt32( begin
)
1798 if ( bCreate2b01Atom
)
1800 EscherExAtom
a2b01Atom( rStrm
, 0x2b01 );
1801 rStrm
.WriteUInt32( 1 ); // ?
1806 void AnimationExporter::exportAnimateKeyPoints( SvStream
& rStrm
, const Reference
< XAnimate
>& xAnimate
)
1808 Sequence
< double > aKeyTimes( xAnimate
->getKeyTimes() );
1809 Sequence
< Any
> aValues( xAnimate
->getValues() );
1810 OUString
aFormula( xAnimate
->getFormula() );
1811 if ( aKeyTimes
.getLength() )
1813 EscherExContainer
aAnimKeyPoints( rStrm
, DFF_msofbtAnimKeyPoints
);
1815 for ( i
= 0; i
< aKeyTimes
.getLength(); i
++ )
1818 EscherExAtom
aAnimKeyTime( rStrm
, DFF_msofbtAnimKeyTime
);
1819 sal_Int32 nKeyTime
= (sal_Int32
)( aKeyTimes
[ i
] * 1000.0 );
1820 rStrm
.WriteInt32( nKeyTime
);
1823 if ( aValues
[ i
].hasValue() )
1826 if ( aValues
[ i
] >>= aPair
)
1828 aAny
[ 0 ] = convertAnimateValue( aPair
.First
, xAnimate
->getAttributeName() );
1829 aAny
[ 1 ] = convertAnimateValue( aPair
.Second
, xAnimate
->getAttributeName() );
1833 aAny
[ 0 ] = convertAnimateValue( aValues
[ i
], xAnimate
->getAttributeName() );
1835 if ( !i
&& !aFormula
.isEmpty() )
1837 ImplTranslateAttribute( aFormula
, TRANSLATE_MEASURE
);
1838 aAny
[ 1 ] <<= aFormula
;
1840 exportAnimProperty( rStrm
, 0, aAny
[ 0 ], TRANSLATE_NONE
);
1841 exportAnimProperty( rStrm
, 1, aAny
[ 1 ], TRANSLATE_NONE
);
1847 void AnimationExporter::exportAnimValue( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const bool bExportAlways
)
1851 double fRepeat
= 0.0;
1852 float fRepeatCount
= 0.0;
1853 com::sun::star::animations::Timing eTiming
;
1854 aAny
= xNode
->getRepeatCount();
1855 if ( aAny
>>= eTiming
)
1857 if ( eTiming
== Timing_INDEFINITE
)
1858 fRepeatCount
= ((float)3.40282346638528860e+38);
1860 else if ( aAny
>>= fRepeat
)
1861 fRepeatCount
= (float)fRepeat
;
1862 if ( fRepeatCount
!= 0.0 )
1864 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1865 sal_uInt32 nType
= 0;
1866 rStrm
.WriteUInt32( nType
)
1867 .WriteFloat( fRepeatCount
);
1870 float fAccelerate
= (float)xNode
->getAcceleration();
1871 if ( bExportAlways
|| ( fAccelerate
!= 0.0 ) )
1873 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1874 sal_uInt32 nType
= 3;
1875 rStrm
.WriteUInt32( nType
)
1876 .WriteFloat( fAccelerate
);
1880 float fDecelerate
= (float)xNode
->getDecelerate();
1881 if ( bExportAlways
|| ( fDecelerate
!= 0.0 ) )
1883 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1884 sal_uInt32 nType
= 4;
1885 rStrm
.WriteUInt32( nType
)
1886 .WriteFloat( fDecelerate
);
1890 bool bAutoReverse
= xNode
->getAutoReverse();
1891 if ( bExportAlways
|| bAutoReverse
)
1893 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1894 sal_uInt32 nType
= 5;
1895 sal_uInt32 nVal
= bAutoReverse
? 1 : 0;
1896 rStrm
.WriteUInt32( nType
)
1897 .WriteUInt32( nVal
);
1901 void AnimationExporter::exportTransitionFilter( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1903 Reference
< XTransitionFilter
> xFilter( xNode
, UNO_QUERY
);
1906 EscherExContainer
aAnimateFilter( rStrm
, DFF_msofbtAnimateFilter
);
1908 EscherExAtom
aAnimateFilterData( rStrm
, DFF_msofbtAnimateFilterData
);
1909 sal_uInt32 nBits
= 3; // bit 0 -> use AnimAttributeValue
1910 // bit 1 -> use nTransition
1912 sal_uInt32 nTransition
= xFilter
->getMode() ? 0 : 1;
1913 rStrm
.WriteUInt32( nBits
)
1914 .WriteUInt32( nTransition
);
1916 const sal_Char
* pFilter
= FindTransitionName( xFilter
->getTransition(), xFilter
->getSubtype(), xFilter
->getDirection() );
1919 const OUString
aStr( OUString::createFromAscii( pFilter
) );
1920 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1922 exportAnimateTarget( rStrm
, xNode
);
1926 void AnimationExporter::exportAnimateMotion( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1928 Reference
< XAnimateMotion
> xMotion( xNode
, UNO_QUERY
);
1931 EscherExContainer
aAnimateMotion( rStrm
, DFF_msofbtAnimateMotion
);
1933 { //SJ: Ignored from import filter
1934 EscherExAtom
aAnimateMotionData( rStrm
, DFF_msofbtAnimateMotionData
);
1935 sal_uInt32 nBits
= 0x98;
1936 sal_uInt32 nOrigin
= 0x2;
1937 float fByX
= 100.0; // nBits&1
1938 float fByY
= 100.0; // nBits&1
1939 float fFromX
= 0.0; // nBits&2
1940 float fFromY
= 0.0; // nBits&2
1941 float fToX
= 100.0; // nBits&4
1942 float fToY
= 100.0; // nBits&4
1943 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nOrigin
);
1947 if ( xMotion
->getPath() >>= aStr
)
1949 if ( !aStr
.isEmpty() )
1950 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1952 exportAnimateTarget( rStrm
, xNode
);
1957 void AnimationExporter::exportAnimateTransform( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1959 Reference
< XAnimateTransform
> xTransform( xNode
, UNO_QUERY
);
1960 if ( xTransform
.is() )
1962 if ( xTransform
->getTransformType() == AnimationTransformType::SCALE
)
1964 EscherExContainer
aAnimateScale( rStrm
, DFF_msofbtAnimateScale
);
1966 EscherExAtom
aAnimateScaleData( rStrm
, DFF_msofbtAnimateScaleData
);
1967 sal_uInt32 nBits
= 0;
1968 sal_uInt32 nZoomContents
= 1;
1976 double fX
= 0.0, fY
= 0.0;
1978 if ( xTransform
->getBy() >>= aPair
)
1980 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1983 fByX
= (float)( fX
* 100 );
1984 fByY
= (float)( fY
* 100 );
1987 if ( xTransform
->getFrom() >>= aPair
)
1989 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1992 fFromX
= (float)( fX
* 100 );
1993 fFromY
= (float)( fY
* 100 );
1996 if( xTransform
->getTo() >>= aPair
)
1998 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
2001 fToX
= (float)( fX
* 100 );
2002 fToY
= (float)( fY
* 100 );
2006 // TODO: ZoomContents:
2008 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
2010 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nZoomContents
);
2012 exportAnimateTarget( rStrm
, xNode
);
2014 else if ( xTransform
->getTransformType() == AnimationTransformType::ROTATE
)
2016 EscherExContainer
aAnimateRotation( rStrm
, DFF_msofbtAnimateRotation
);
2018 EscherExAtom
aAnimateRotationData( rStrm
, DFF_msofbtAnimateRotationData
);
2019 sal_uInt32 nBits
= 0;
2026 if ( xTransform
->getBy() >>= fVal
)
2031 if ( xTransform
->getFrom() >>= fVal
)
2034 fFrom
= (float)fVal
;
2036 if ( xTransform
->getTo() >>= fVal
)
2041 rStrm
.WriteUInt32( nBits
).WriteFloat( fBy
).WriteFloat( fFrom
).WriteFloat( fTo
).WriteUInt32( nU1
);
2043 exportAnimateTarget( rStrm
, xNode
, 1 );
2048 bool AnimationExporter::getColorAny( const Any
& rAny
, const sal_Int16 nColorSpace
, sal_Int32
& rMode
, sal_Int32
& rA
, sal_Int32
& rB
, sal_Int32
& rC
)
2050 bool bIsColor
= true;
2053 if ( nColorSpace
== AnimationColorSpace::HSL
)
2056 sal_Int32 nColor
= 0;
2057 Sequence
< double > aHSL( 3 );
2058 if ( rAny
>>= nColor
) // RGB color
2060 rA
= (sal_uInt8
)( nColor
>> 16 );
2061 rB
= (sal_uInt8
)( nColor
>> 8 );
2062 rC
= (sal_uInt8
)( nColor
);
2064 else if ( rAny
>>= aHSL
) // HSL
2066 rA
= (sal_Int32
) ( aHSL
[ 0 ] * 255.0 / 360.0 );
2067 rB
= (sal_Int32
) ( aHSL
[ 1 ] * 255.0 );
2068 rC
= (sal_Int32
) ( aHSL
[ 2 ] * 255.0 );
2075 void AnimationExporter::exportAnimateColor( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
2077 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
2080 EscherExContainer
aAnimateColor( rStrm
, DFF_msofbtAnimateColor
);
2082 EscherExAtom
aAnimateColorData( rStrm
, DFF_msofbtAnimateColorData
);
2083 sal_uInt32 nBits
= 8;
2085 sal_Int32 nByMode
, nByA
, nByB
, nByC
;
2086 nByMode
= nByA
= nByB
= nByC
= 0;
2088 sal_Int32 nFromMode
, nFromA
, nFromB
, nFromC
;
2089 nFromMode
= nFromA
= nFromB
= nFromC
= 0;
2091 sal_Int32 nToMode
, nToA
, nToB
, nToC
;
2092 nToMode
= nToA
= nToB
= nToC
= 0;
2094 sal_Int16 nColorSpace
= xColor
->getColorInterpolation();
2096 Any
aAny( xColor
->getBy() );
2097 if ( aAny
.hasValue() )
2099 if ( getColorAny( aAny
, nColorSpace
, nByMode
, nByA
, nByB
, nByC
) )
2102 aAny
= xColor
->getFrom();
2103 if ( aAny
.hasValue() )
2105 if ( getColorAny( aAny
, nColorSpace
, nFromMode
, nFromA
, nFromB
, nFromC
) )
2108 aAny
= xColor
->getTo();
2109 if ( aAny
.hasValue() )
2111 if ( getColorAny( aAny
, nColorSpace
, nToMode
, nToA
, nToB
, nToC
) )
2114 rStrm
.WriteUInt32( nBits
)
2115 .WriteInt32( nByMode
).WriteInt32( nByA
).WriteInt32( nByB
).WriteInt32( nByC
)
2116 .WriteInt32( nFromMode
).WriteInt32( nFromA
).WriteInt32( nFromB
).WriteInt32( nFromC
)
2117 .WriteInt32( nToMode
).WriteInt32( nToA
).WriteInt32( nToB
).WriteInt32( nToC
);
2119 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
2123 void AnimationExporter::exportIterate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
2125 Reference
< XIterateContainer
> xIterate( xNode
, UNO_QUERY
);
2126 if ( xIterate
.is() )
2128 EscherExAtom
aAnimIteration( rStrm
, DFF_msofbtAnimIteration
);
2130 float fInterval
= 10.0;
2131 sal_Int32 nTextUnitEffect
= 0;
2134 sal_Int32 nU3
= 0xe;
2136 sal_Int16 nIterateType
= xIterate
->getIterateType();
2137 switch( nIterateType
)
2139 case TextAnimationType::BY_WORD
: nTextUnitEffect
= 1; break;
2140 case TextAnimationType::BY_LETTER
: nTextUnitEffect
= 2; break;
2143 fInterval
= (float)xIterate
->getIterateInterval();
2145 // convert interval from absolute to percentage
2146 double fDuration
= 0.0;
2148 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
2149 if( xEnumerationAccess
.is() )
2151 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), UNO_QUERY
);
2152 if( xEnumeration
.is() )
2154 while( xEnumeration
->hasMoreElements() )
2156 Reference
< XAnimate
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
2157 if( xChildNode
.is() )
2159 double fChildBegin
= 0.0;
2160 double fChildDuration
= 0.0;
2161 xChildNode
->getBegin() >>= fChildBegin
;
2162 xChildNode
->getDuration() >>= fChildDuration
;
2164 fChildDuration
+= fChildBegin
;
2165 if( fChildDuration
> fDuration
)
2166 fDuration
= fChildDuration
;
2173 fInterval
= (float)(100.0 * fInterval
/ fDuration
);
2175 rStrm
.WriteFloat( fInterval
).WriteInt32( nTextUnitEffect
).WriteInt32( nU1
).WriteInt32( nU2
).WriteInt32( nU3
);
2176 aTarget
= xIterate
->getTarget();
2182 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */