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
= rPresetSubType
.toUInt32();
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 const NamedValue
* p
= std::find_if(aUserData
.begin(), aUserData
.end(),
377 [](const NamedValue
& rProp
) { return rProp
.Name
== "master-element"; });
379 if (p
!= aUserData
.end())
380 p
->Value
>>= xMaster
;
382 AfterEffectNodePtr
pAfterEffectNode( new AfterEffectNode( xChildNode3
, xMaster
) );
383 maAfterEffectNodes
.push_back( pAfterEffectNode
);
395 OSL_FAIL( "(@CL)AnimationExporter::processAfterEffectNodes(), exception caught!" );
399 bool AnimationExporter::isAfterEffectNode( const Reference
< XAnimationNode
>& xNode
) const
401 return std::any_of(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
402 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxNode
== xNode
; });
405 bool AnimationExporter::hasAfterEffectNode( const Reference
< XAnimationNode
>& xNode
, Reference
< XAnimationNode
>& xAfterEffectNode
) const
407 auto aIter
= std::find_if(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
408 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxMaster
== xNode
; });
409 if (aIter
!= maAfterEffectNodes
.end())
411 xAfterEffectNode
= (*aIter
)->mxNode
;
418 // check if this group only contain empty groups. this may happen when
419 // after effect nodes are not exported at their original position
420 bool AnimationExporter::isEmptyNode( const Reference
< XAnimationNode
>& xNode
) const
422 if( xNode
.is() ) switch( xNode
->getType() )
424 case AnimationNodeType::PAR
:
425 case AnimationNodeType::SEQ
:
426 case AnimationNodeType::ITERATE
:
428 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
429 if( xEnumerationAccess
.is() )
431 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
432 if( xEnumeration
.is() )
434 while( xEnumeration
->hasMoreElements() )
436 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
437 if( xChildNode
.is() && !isEmptyNode( xChildNode
) )
445 case AnimationNodeType::SET
:
446 case AnimationNodeType::ANIMATECOLOR
:
447 return isAfterEffectNode( xNode
);
455 void AnimationExporter::exportNode( SvStream
& rStrm
, Reference
< XAnimationNode
> const & xNode_in
, const sal_uInt16 nContainerRecType
,
456 const sal_uInt16 nInstance
, const sal_Int32 nGroupLevel
, const bool bTakeBackInteractiveSequenceTiming
, const sal_Int16 nFDef
)
458 auto xNode
= xNode_in
;
460 if( (nGroupLevel
== 4) && isEmptyNode( xNode
) )
463 if ( ( nContainerRecType
== DFF_msofbtAnimGroup
) && ( nGroupLevel
== 2 ) && isEmptyNode( xNode
) )
466 if( nContainerRecType
== DFF_msofbtAnimGroup
)
469 bool bTakeBackInteractiveSequenceTimingForChild
= false;
470 sal_Int16 nFillDefault
= GetFillMode( xNode
, nFDef
);
472 Reference
< XAnimationNode
> xAudioNode
;
473 static sal_uInt32 nAudioGroup
;
476 bool bSkipChildren
= false;
477 EscherExContainer
aContainer( rStrm
, nContainerRecType
, nInstance
);
478 switch( xNode
->getType() )
480 case AnimationNodeType::CUSTOM
:
482 exportAnimNode( rStrm
, xNode
, nFillDefault
);
483 exportAnimPropertySet( rStrm
, xNode
);
484 exportAnimEvent( rStrm
, xNode
);
485 exportAnimValue( rStrm
, xNode
, false );
489 case AnimationNodeType::PAR
:
491 exportAnimNode( rStrm
, xNode
, nFillDefault
);
492 exportAnimPropertySet( rStrm
, xNode
);
493 sal_Int32 nFlags
= nGroupLevel
== 2 ? 0x10 : 0;
494 if ( bTakeBackInteractiveSequenceTiming
)
496 exportAnimEvent( rStrm
, xNode
, nFlags
);
497 exportAnimValue( rStrm
, xNode
, nGroupLevel
== 4 );
501 case AnimationNodeType::SEQ
:
503 exportAnimNode( rStrm
, xNode
, nFillDefault
);
504 sal_Int16 nNodeType
= exportAnimPropertySet( rStrm
, xNode
);
505 sal_Int32 nFlags
= 12;
506 if ( ( nGroupLevel
== 1 ) && ( nNodeType
== css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
) )
509 bTakeBackInteractiveSequenceTimingForChild
= true;
511 exportAnimAction( rStrm
, xNode
);
512 exportAnimEvent( rStrm
, xNode
, nFlags
);
513 exportAnimValue( rStrm
, xNode
, false );
517 case AnimationNodeType::ITERATE
:
520 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
522 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
523 aAnim
.mnNodeType
= 1;
525 switch( xNode
->getRestart() )
528 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
529 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
530 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
531 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
534 switch( xNode
->getFill() )
537 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
538 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
539 case AnimationFill::FREEZE
: aAnim
.mnFill
= 2; break;
540 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
541 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
543 WriteAnimationNode( rStrm
, aAnim
);
545 exportIterate( rStrm
, xNode
);
546 exportAnimPropertySet( rStrm
, xNode
);
547 exportAnimEvent( rStrm
, xNode
);
548 exportAnimValue( rStrm
, xNode
, false );
552 case AnimationNodeType::ANIMATE
:
554 exportAnimNode( rStrm
, xNode
, nFillDefault
);
555 exportAnimPropertySet( rStrm
, xNode
);
556 exportAnimEvent( rStrm
, xNode
);
557 exportAnimValue( rStrm
, xNode
, false );
558 exportAnimate( rStrm
, xNode
);
562 case AnimationNodeType::SET
:
564 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
565 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
567 exportAnimNode( rStrm
, xNode
, nFillDefault
);
568 exportAnimPropertySet( rStrm
, xNode
);
569 exportAnimateSet( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_SET
: AFTEREFFECT_NONE
);
570 exportAnimEvent( rStrm
, xNode
);
571 exportAnimValue( rStrm
, xNode
, false );
575 bSkipChildren
= true;
580 case AnimationNodeType::ANIMATEMOTION
:
582 exportAnimNode( rStrm
, xNode
, nFillDefault
);
583 exportAnimPropertySet( rStrm
, xNode
);
584 exportAnimateMotion( rStrm
, xNode
);
585 exportAnimEvent( rStrm
, xNode
);
586 exportAnimValue( rStrm
, xNode
, false );
590 case AnimationNodeType::ANIMATECOLOR
:
592 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
593 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
595 if( bIsAfterEffectNode
)
596 xNode
= createAfterEffectNodeClone( xNode
);
598 exportAnimNode( rStrm
, xNode
, nFillDefault
);
599 exportAnimPropertySet( rStrm
, xNode
);
600 exportAnimateColor( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_COLOR
: AFTEREFFECT_NONE
);
601 exportAnimEvent( rStrm
, xNode
);
602 exportAnimValue( rStrm
, xNode
, false );
606 bSkipChildren
= true;
611 case AnimationNodeType::ANIMATETRANSFORM
:
613 exportAnimNode( rStrm
, xNode
, nFillDefault
);
614 exportAnimPropertySet( rStrm
, xNode
);
615 exportAnimateTransform( rStrm
, xNode
);
616 exportAnimEvent( rStrm
, xNode
);
617 exportAnimValue( rStrm
, xNode
, false );
621 case AnimationNodeType::TRANSITIONFILTER
:
623 exportAnimNode( rStrm
, xNode
, nFillDefault
);
624 exportAnimPropertySet( rStrm
, xNode
);
625 exportAnimEvent( rStrm
, xNode
);
626 exportAnimValue( rStrm
, xNode
, false );
627 exportTransitionFilter( rStrm
, xNode
);
631 case AnimationNodeType::AUDIO
: // #i58428#
633 exportAnimNode( rStrm
, xNode
, nFillDefault
);
634 exportAnimPropertySet( rStrm
, xNode
);
636 Reference
< XAudio
> xAudio( xNode
, UNO_QUERY
);
639 Any
aAny( xAudio
->getSource() );
642 if ( ( aAny
>>= aURL
) && !aURL
.isEmpty() )
645 sal_Int32 nTrigger
= 3;
646 sal_Int32 nU3
= nAudioGroup
;
647 sal_Int32 nBegin
= 0;
649 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 1 );
651 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
652 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
659 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 2 );
661 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
662 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
665 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
667 sal_uInt32
const nRefMode
= 3;
668 sal_uInt32
const nRefType
= 2;
669 sal_uInt32 nRefId
= mrExSoundCollection
.GetId( aURL
);
670 sal_Int32
const begin
= -1;
671 sal_Int32
const end
= -1;
673 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
674 rStrm
.WriteUInt32( nRefMode
).WriteUInt32( nRefType
).WriteUInt32( nRefId
).WriteInt32( begin
).WriteInt32( end
);
678 exportAnimValue( rStrm
, xNode
, false );
684 // export after effect node if one exists for this node
685 Reference
< XAnimationNode
> xAfterEffectNode
;
686 if( hasAfterEffectNode( xNode
, xAfterEffectNode
) )
688 exportNode( rStrm
, xAfterEffectNode
, DFF_msofbtAnimSubGoup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
691 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
692 if( xEnumerationAccess
.is() )
694 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
695 if( xEnumeration
.is() )
697 while( xEnumeration
->hasMoreElements() )
699 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
700 if( xChildNode
.is() )
702 if ( xChildNode
->getType() == AnimationNodeType::AUDIO
)
704 xAudioNode
= xChildNode
;
705 nAudioGroup
= mnCurrentGroup
;
708 exportNode( rStrm
, xChildNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
715 if ( xAudioNode
.is() )
716 exportNode( rStrm
, xAudioNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
718 if( xNode
->getType() == AnimationNodeType::ITERATE
)
722 Reference
< XAnimationNode
> AnimationExporter::createAfterEffectNodeClone( const Reference
< XAnimationNode
>& xNode
)
726 Reference
< css::util::XCloneable
> xClonable( xNode
, UNO_QUERY_THROW
);
727 Reference
< XAnimationNode
> xCloneNode( xClonable
->createClone(), UNO_QUERY_THROW
);
730 xCloneNode
->setBegin( aEmpty
);
736 OSL_FAIL("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
741 bool AnimationExporter::GetNodeType( const Reference
< XAnimationNode
>& xNode
, sal_Int16
& nType
)
743 // trying to get the nodetype
744 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
745 for( const NamedValue
& rProp
: aUserData
)
747 if ( rProp
.Name
== "node-type" )
749 if ( rProp
.Value
>>= nType
)
757 void AnimationExporter::exportAnimNode( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
,
758 const sal_Int16 nFillDefault
)
760 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
764 switch( xNode
->getRestart() )
767 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
768 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
769 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
770 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
773 switch( nFillDefault
)
776 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
777 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
778 case AnimationFill::FREEZE
:
779 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
780 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
782 // attribute Duration
783 double fDuration
= 0.0;
784 css::animations::Timing eTiming
;
785 if ( xNode
->getDuration() >>= eTiming
)
787 if ( eTiming
== Timing_INDEFINITE
)
788 aAnim
.mnDuration
= -1;
790 else if ( xNode
->getDuration() >>= fDuration
)
792 aAnim
.mnDuration
= static_cast<sal_Int32
>( fDuration
* 1000.0 );
795 aAnim
.mnDuration
= -1;
797 // NodeType, NodeGroup
798 aAnim
.mnNodeType
= 1;
799 aAnim
.mnGroupType
= mso_Anim_GroupType_SEQ
;
800 switch( xNode
->getType() )
802 case AnimationNodeType::PAR
:
803 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
805 case AnimationNodeType::SEQ
:
808 if( GetNodeType( xNode
, nType
) )
811 case css::presentation::EffectNodeType::TIMING_ROOT
: aAnim
.mnNodeType
= 0x12; break;
812 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: aAnim
.mnNodeType
= 0x18; break;
817 case AnimationNodeType::ANIMATE
:
818 case AnimationNodeType::SET
:
820 case AnimationNodeType::CUSTOM
:
821 case AnimationNodeType::ITERATE
:
822 case AnimationNodeType::ANIMATEMOTION
:
823 case AnimationNodeType::ANIMATECOLOR
:
824 case AnimationNodeType::ANIMATETRANSFORM
:
826 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
827 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
831 case AnimationNodeType::AUDIO
:
833 aAnim
.mnGroupType
= mso_Anim_GroupType_MEDIA
;
834 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
838 case AnimationNodeType::TRANSITIONFILTER
:
840 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
841 aAnim
.mnNodeType
= mso_Anim_Behaviour_FILTER
;
846 WriteAnimationNode( rStrm
, aAnim
);
849 void AnimationExporter::GetUserData( const Sequence
< NamedValue
>& rUserData
, const Any
** pAny
, std::size_t nLen
)
851 // storing user data into pAny, to allow direct access later
852 memset( pAny
, 0, nLen
);
853 if ( !rUserData
.hasElements() )
856 for( const NamedValue
& rProp
: rUserData
)
858 if ( rProp
.Name
== "node-type" )
860 pAny
[ DFF_ANIM_NODE_TYPE
] = &(rProp
.Value
);
862 else if ( rProp
.Name
== "preset-class" )
864 pAny
[ DFF_ANIM_PRESET_CLASS
] = &(rProp
.Value
);
866 else if ( rProp
.Name
== "preset-id" )
868 pAny
[ DFF_ANIM_PRESET_ID
] = &(rProp
.Value
);
870 else if ( rProp
.Name
== "preset-sub-type" )
872 pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] = &(rProp
.Value
);
874 else if ( rProp
.Name
== "master-element" )
876 pAny
[ DFF_ANIM_AFTEREFFECT
] = &(rProp
.Value
);
881 sal_uInt32
AnimationExporter::GetPresetID( const OUString
& rPreset
, sal_uInt32 nAPIPresetClass
, bool& bPresetId
)
883 sal_uInt32 nPresetId
= 0;
886 if ( rPreset
.match("ppt_", 0) )
888 sal_Int32 nLast
= rPreset
.lastIndexOf( '_' );
889 if ( ( nLast
!= -1 ) && ( ( nLast
+ 1 ) < rPreset
.getLength() ) )
891 OUString
aNumber( rPreset
.copy( nLast
+ 1 ) );
892 nPresetId
= aNumber
.toUInt32();
898 const oox::ppt::preset_mapping
* p
= oox::ppt::preset_mapping::getList();
899 while( p
->mpStrPresetId
&& ((p
->mnPresetClass
!= static_cast<sal_Int32
>(nAPIPresetClass
)) || !rPreset
.equalsAscii( p
->mpStrPresetId
)) )
902 if( p
->mpStrPresetId
)
904 nPresetId
= p
->mnPresetId
;
912 sal_Int16
AnimationExporter::exportAnimPropertySet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
914 sal_Int16 nNodeType
= css::presentation::EffectNodeType::DEFAULT
;
916 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
918 Reference
< XAnimationNode
> xMaster
;
920 Any aMasterRel
, aOverride
, aRunTimeContext
;
922 // storing user data into pAny, to allow direct access later
923 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
924 const css::uno::Any
* pAny
[ DFF_ANIM_PROPERTY_ID_COUNT
];
925 GetUserData( aUserData
, pAny
, sizeof( pAny
) );
927 if( pAny
[ DFF_ANIM_AFTEREFFECT
] )
928 ( *pAny
[ DFF_ANIM_AFTEREFFECT
] ) >>= xMaster
;
930 // calculate master-rel
933 sal_Int32 nMasterRel
= 2;
934 if( xNode
.is() && xMaster
.is() && (xNode
->getParent() == xMaster
->getParent() ) )
937 aMasterRel
<<= nMasterRel
;
939 pAny
[ DFF_ANIM_MASTERREL
] = &aMasterRel
;
941 aOverride
<<= sal_Int32(1);
942 pAny
[ DFF_ANIM_OVERRIDE
] = &aOverride
;
944 aRunTimeContext
<<= sal_Int32(1);
945 pAny
[ DFF_ANIM_RUNTIMECONTEXT
] = &aRunTimeContext
;
948 // the order is important
949 if ( pAny
[ DFF_ANIM_NODE_TYPE
] )
951 if ( *pAny
[ DFF_ANIM_NODE_TYPE
] >>= nNodeType
)
953 sal_uInt32 nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
;
956 case css::presentation::EffectNodeType::ON_CLICK
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
; break;
957 case css::presentation::EffectNodeType::WITH_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_WITH_PREVIOUS
; break;
958 case css::presentation::EffectNodeType::AFTER_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS
; break;
959 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE
; break;
960 case css::presentation::EffectNodeType::TIMING_ROOT
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_TIMING_ROOT
; break;
961 case css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ
; break;
963 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_NODE_TYPE
, nPPTNodeType
);
966 sal_uInt32 nPresetId
= 0;
967 sal_uInt32 nPresetSubType
= 0;
968 sal_uInt32 nAPIPresetClass
= EffectPresetClass::CUSTOM
;
969 sal_uInt32 nPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
970 bool bPresetClass
, bPresetId
, bPresetSubType
;
971 bPresetId
= bPresetClass
= bPresetSubType
= false;
973 if ( pAny
[ DFF_ANIM_PRESET_CLASS
] )
975 if ( *pAny
[ DFF_ANIM_PRESET_CLASS
] >>= nAPIPresetClass
)
977 sal_uInt8 nPPTPresetClass
;
978 switch( nAPIPresetClass
)
980 case EffectPresetClass::ENTRANCE
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_ENTRANCE
; break;
981 case EffectPresetClass::EXIT
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EXIT
; break;
982 case EffectPresetClass::EMPHASIS
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EMPHASIS
; break;
983 case EffectPresetClass::MOTIONPATH
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MOTIONPATH
; break;
984 case EffectPresetClass::OLEACTION
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_OLE_ACTION
; break;
985 case EffectPresetClass::MEDIACALL
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MEDIACALL
; break;
987 nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
989 nPresetClass
= nPPTPresetClass
;
993 if ( pAny
[ DFF_ANIM_PRESET_ID
] )
996 if ( *pAny
[ DFF_ANIM_PRESET_ID
] >>= sPreset
)
997 nPresetId
= GetPresetID( sPreset
, nAPIPresetClass
, bPresetId
);
1000 if ( pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] )
1002 OUString sPresetSubType
;
1003 if ( *pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] >>= sPresetSubType
)
1005 nPresetSubType
= TranslatePresetSubType( nPresetClass
, nPresetId
, sPresetSubType
);
1006 bPresetSubType
= true;
1010 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_ID
, nPresetId
);
1011 if ( bPresetSubType
)
1012 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_SUB_TYPE
, nPresetSubType
);
1014 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_CLASS
, nPresetClass
);
1016 if ( pAny
[ DFF_ANIM_ID
] )
1021 if ( pAny
[ DFF_ANIM_AFTEREFFECT
] )
1023 bool bAfterEffect
= false;
1024 if ( *pAny
[ DFF_ANIM_AFTEREFFECT
] >>= bAfterEffect
)
1025 exportAnimPropertyByte( rStrm
, DFF_ANIM_AFTEREFFECT
, int(bAfterEffect
) );
1028 if ( pAny
[ DFF_ANIM_RUNTIMECONTEXT
] )
1030 sal_Int32 nRunTimeContext
= 0;
1031 if ( *pAny
[ DFF_ANIM_RUNTIMECONTEXT
] >>= nRunTimeContext
)
1032 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_RUNTIMECONTEXT
, nRunTimeContext
);
1034 if ( pAny
[ DFF_ANIM_PATH_EDIT_MODE
] )
1041 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
1045 bool bDirection
= !xColor
->getDirection();
1046 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_DIRECTION
, bDirection
? 1 : 0 );
1050 if ( pAny
[ DFF_ANIM_OVERRIDE
] )
1052 sal_Int32 nOverride
= 0;
1053 if ( *pAny
[ DFF_ANIM_OVERRIDE
] >>= nOverride
)
1054 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_OVERRIDE
, nOverride
);
1057 if ( pAny
[ DFF_ANIM_MASTERREL
] )
1059 sal_Int32 nMasterRel
= 0;
1060 if ( *pAny
[ DFF_ANIM_MASTERREL
] >>= nMasterRel
)
1061 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_MASTERREL
, nMasterRel
);
1065 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1068 sal_Int16 nEndAfterSlide = 0;
1069 nEndAfterSlide = xAudio->getEndAfterSlide();
1070 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1073 Reference
< XAnimate
> xAnim( xNode
, UNO_QUERY
);
1076 // TODO: DFF_ANIM_TIMEFILTER
1078 if ( pAny
[ DFF_ANIM_EVENT_FILTER
] )
1080 // TODO DFF_ANIM_EVENT_FILTER
1082 if ( pAny
[ DFF_ANIM_VOLUME
] )
1084 // TODO DFF_ANIM_VOLUME
1089 bool AnimationExporter::exportAnimProperty( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const css::uno::Any
& rAny
, const TranslateMode eTranslateMode
)
1092 if ( rAny
.hasValue() )
1094 switch( rAny
.getValueType().getTypeClass() )
1096 case css::uno::TypeClass_UNSIGNED_SHORT
:
1097 case css::uno::TypeClass_SHORT
:
1098 case css::uno::TypeClass_UNSIGNED_LONG
:
1099 case css::uno::TypeClass_LONG
:
1102 if ( rAny
>>= nVal
)
1104 exportAnimPropertyuInt32( rStrm
, nPropertyId
, nVal
);
1110 case css::uno::TypeClass_DOUBLE
:
1113 if ( rAny
>>= fVal
)
1115 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1120 case css::uno::TypeClass_FLOAT
:
1123 if ( rAny
>>= fVal
)
1125 if ( eTranslateMode
& TRANSLATE_NUMBER_TO_STRING
)
1127 OUString
aNumber( OUString::number( fVal
) );
1128 exportAnimPropertyString( rStrm
, nPropertyId
, aNumber
, eTranslateMode
);
1132 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1138 case css::uno::TypeClass_STRING
:
1141 if ( rAny
>>= aStr
)
1143 exportAnimPropertyString( rStrm
, nPropertyId
, aStr
, eTranslateMode
);
1154 void AnimationExporter::exportAnimPropertyString( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const OUString
& rVal
, const TranslateMode eTranslateMode
)
1156 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1157 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_UNISTRING
);
1158 OUString
aStr( rVal
);
1159 if ( eTranslateMode
!= TRANSLATE_NONE
)
1160 ImplTranslateAttribute( aStr
, eTranslateMode
);
1161 writeZString( rStrm
, aStr
);
1164 void AnimationExporter::exportAnimPropertyFloat( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const double& rVal
)
1166 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1167 float fFloat
= static_cast<float>(rVal
);
1168 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_FLOAT
)
1169 .WriteFloat( fFloat
);
1172 void AnimationExporter::exportAnimPropertyuInt32( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt32 nVal
)
1174 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1175 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_INT32
)
1176 .WriteUInt32( nVal
);
1179 void AnimationExporter::exportAnimPropertyByte( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt8 nVal
)
1181 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1182 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_BYTE
)
1183 .WriteUChar( nVal
);
1186 void AnimationExporter::writeZString( SvStream
& rStrm
, const OUString
& rVal
)
1189 for ( i
= 0; i
< rVal
.getLength(); i
++ )
1190 rStrm
.WriteUInt16( rVal
[ i
] );
1191 rStrm
.WriteUInt16( 0 );
1194 void AnimationExporter::exportAnimAction( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1196 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAction
);
1198 sal_Int32
const nConcurrent
= 1;
1199 sal_Int32
const nNextAction
= 1;
1200 sal_Int32 nEndSync
= 0;
1201 sal_Int32
const nU4
= 0;
1202 sal_Int32
const nU5
= 3;
1204 sal_Int16 nAnimationEndSync
= 0;
1205 if ( xNode
->getEndSync() >>= nAnimationEndSync
)
1207 if ( nAnimationEndSync
== AnimationEndSync::ALL
)
1210 rStrm
.WriteInt32( nConcurrent
)
1211 .WriteInt32( nNextAction
)
1212 .WriteInt32( nEndSync
)
1218 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1219 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1220 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
1221 void AnimationExporter::exportAnimEvent( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_Int32 nFlags
)
1224 for ( i
= 0; i
< 4; i
++ )
1227 sal_Int32 nTrigger
= 0;
1229 sal_Int32 nBegin
= 0;
1231 bool bCreateEvent
= false;
1241 css::animations::Timing eTiming
;
1244 if ( nFlags
& 0x20 )
1246 // taking the first child
1247 Reference
< XEnumerationAccess
> xEA( xNode
, UNO_QUERY_THROW
);
1248 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), css::uno::UNO_SET_THROW
);
1249 if ( xE
->hasMoreElements() )
1251 Reference
< XAnimationNode
> xClickNode( xE
->nextElement(), UNO_QUERY
);
1252 aAny
= xClickNode
->getBegin();
1255 else if ( nFlags
& 0x40 )
1257 // begin has to be replaced with void, so don't do anything
1261 aAny
= xNode
->getBegin();
1262 if ( nFlags
& 0x10 ) // replace ON_NEXT with INDEFINITE
1264 if ( ( aAny
>>= aEvent
) && ( aEvent
.Trigger
== EventTrigger::ON_NEXT
) )
1266 eTiming
= Timing_INDEFINITE
;
1273 aAny
= xNode
->getEnd();
1275 double fTiming
= 0.0;
1276 if ( aAny
>>= aEvent
)
1278 bCreateEvent
= true;
1279 switch( aEvent
.Trigger
)
1281 case EventTrigger::NONE
: nTrigger
= 0; break;
1282 case EventTrigger::ON_BEGIN
: nTrigger
= 1; break;
1283 case EventTrigger::ON_END
: nTrigger
= 2; break;
1284 case EventTrigger::BEGIN_EVENT
: nTrigger
= 3; break;
1285 case EventTrigger::END_EVENT
: nTrigger
= 4; nU1
= 2; nU3
= mnCurrentGroup
; break;
1286 case EventTrigger::ON_CLICK
: nTrigger
= 5; break;
1287 case EventTrigger::ON_DBL_CLICK
: nTrigger
= 6; break;
1288 case EventTrigger::ON_MOUSE_ENTER
: nTrigger
= 7; break;
1289 case EventTrigger::ON_MOUSE_LEAVE
: nTrigger
= 8; break;
1290 case EventTrigger::ON_NEXT
: nTrigger
= 9; break;
1291 case EventTrigger::ON_PREV
: nTrigger
= 10; break;
1292 case EventTrigger::ON_STOP_AUDIO
: nTrigger
= 11; break;
1294 if ( aEvent
.Offset
.hasValue() )
1296 if ( aEvent
.Offset
>>= eTiming
)
1298 if ( eTiming
== Timing_INDEFINITE
)
1301 else if ( aEvent
.Offset
>>= fTiming
)
1302 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1304 aSource
= aEvent
.Source
;
1306 else if ( aAny
>>= eTiming
)
1308 bCreateEvent
= true;
1309 if ( eTiming
== Timing_INDEFINITE
)
1312 else if ( aAny
>>= fTiming
)
1314 bCreateEvent
= true;
1315 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1322 if ( nFlags
& ( 1 << i
) )
1324 bCreateEvent
= true;
1332 if ( nFlags
& ( 1 << i
) )
1334 bCreateEvent
= true;
1343 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, i
+ 1 );
1345 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
1346 rStrm
.WriteInt32( nU1
)
1347 .WriteInt32( nTrigger
)
1349 .WriteInt32( nBegin
);
1351 exportAnimateTargetElement( rStrm
, aSource
, ( nFlags
& ( 1 << i
) ) != 0 );
1356 Any
AnimationExporter::convertAnimateValue( const Any
& rSourceValue
, const OUString
& rAttributeName
)
1359 if ( rAttributeName
== "X"
1360 || rAttributeName
== "Y"
1361 || rAttributeName
== "Width"
1362 || rAttributeName
== "Height"
1366 if ( rSourceValue
>>= aStr
)
1368 ImplTranslateAttribute( aStr
, TRANSLATE_MEASURE
);
1372 else if ( rAttributeName
== "Rotate" // "r" or "style.rotation" ?
1373 || rAttributeName
== "Opacity"
1374 || rAttributeName
== "CharHeight"
1375 || rAttributeName
== "SkewX"
1378 double fNumber
= 0.0;
1379 if ( rSourceValue
>>= fNumber
)
1380 aDest
+= OUString::number( fNumber
);
1382 else if ( rAttributeName
== "Color"
1383 || rAttributeName
== "FillColor" // "Fillcolor" or "FillColor" ?
1384 || rAttributeName
== "LineColor"
1385 || rAttributeName
== "CharColor"
1388 sal_Int32 nColor
= 0;
1389 Sequence
< double > aHSL( 3 );
1391 if ( rSourceValue
>>= aHSL
)
1394 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 0 ] / ( 360.0 / 255 ) ) )
1396 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 ) )
1398 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 ) )
1401 else if ( rSourceValue
>>= nColor
)
1404 + OUString::number( static_cast<sal_Int8
>(nColor
) )
1406 + OUString::number( static_cast<sal_Int8
>( nColor
>> 8 ) )
1408 + OUString::number( static_cast<sal_Int8
>( nColor
>> 16 ) )
1412 else if ( rAttributeName
== "FillStyle" )
1414 css::drawing::FillStyle eFillStyle
;
1415 if ( rSourceValue
>>= eFillStyle
)
1417 if ( eFillStyle
== css::drawing::FillStyle_NONE
)
1418 aDest
+= "none"; // ?
1423 else if (rAttributeName
== "FillOn")
1426 if ( rSourceValue
>>= bFillOn
)
1434 else if ( rAttributeName
== "LineStyle" )
1436 css::drawing::LineStyle eLineStyle
;
1437 if ( rSourceValue
>>= eLineStyle
)
1439 if ( eLineStyle
== css::drawing::LineStyle_NONE
)
1445 else if ( rAttributeName
== "CharWeight" )
1447 float fFontWeight
= 0.0;
1448 if ( rSourceValue
>>= fFontWeight
)
1450 if ( fFontWeight
== css::awt::FontWeight::BOLD
)
1456 else if ( rAttributeName
== "CharUnderline" )
1458 sal_Int16 nFontUnderline
= 0;
1459 if ( rSourceValue
>>= nFontUnderline
)
1461 if ( nFontUnderline
== css::awt::FontUnderline::NONE
)
1467 else if ( rAttributeName
== "CharPosture" )
1469 css::awt::FontSlant eFontSlant
;
1470 if ( rSourceValue
>>= eFontSlant
)
1472 if ( eFontSlant
== css::awt::FontSlant_ITALIC
)
1475 aDest
+= "normal"; // ?
1478 else if ( rAttributeName
== "Visibility" )
1480 bool bVisible
= true;
1481 if ( rSourceValue
>>= bVisible
)
1490 if ( !aDest
.isEmpty() )
1493 aRet
= rSourceValue
;
1497 void AnimationExporter::exportAnimateSet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
1499 Reference
< XAnimateSet
> xSet( xNode
, UNO_QUERY
);
1503 EscherExContainer
aAnimateSet( rStrm
, DFF_msofbtAnimateSet
, 0 );
1505 EscherExAtom
aAnimateSetData( rStrm
, DFF_msofbtAnimateSetData
);
1506 sal_uInt32
const nId1
= 1; // ??
1507 sal_uInt32
const nId2
= 1; // ??
1508 rStrm
.WriteUInt32( nId1
).WriteUInt32( nId2
);
1510 Any
aConvertedValue( convertAnimateValue( xSet
->getTo(), xSet
->getAttributeName() ) );
1511 if ( aConvertedValue
.hasValue() )
1512 exportAnimProperty( rStrm
, 1, aConvertedValue
, TRANSLATE_NONE
);
1513 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
1516 sal_uInt32
AnimationExporter::GetValueTypeForAttributeName( const OUString
& rAttributeName
)
1518 sal_uInt32 nValueType
= 0;
1522 const sal_Char
* pName
;
1525 static const Entry lcl_attributeMap
[] =
1528 { "charfontname", 0 },
1529 { "charheight", 1 },
1530 { "charposture", 0 },
1531 // TODO(Q1): This should prolly be changed in PPT import
1532 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1533 { "charrotation", 1 },
1534 { "charunderline", 0 },
1535 { "charweight", 0 },
1547 { "visibility", 1 },
1553 const Entry
* pPtr
= &lcl_attributeMap
[ 0 ];
1554 while( pPtr
->pName
)
1556 if ( rAttributeName
.equalsIgnoreAsciiCaseAscii( pPtr
->pName
) )
1558 nValueType
= pPtr
->nType
;
1563 DBG_ASSERT( pPtr
->pName
, "GetValueTypeForAttributeName, unknown property value!" );
1567 void AnimationExporter::exportAnimate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1569 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1570 if ( !xAnimate
.is() )
1573 Any
aBy ( xAnimate
->getBy() );
1574 Any
aFrom( xAnimate
->getFrom() );
1575 Any
aTo ( xAnimate
->getTo() );
1577 EscherExContainer
aContainer( rStrm
, DFF_msofbtAnimate
, 0 );
1579 EscherExAtom
aAnimateData( rStrm
, DFF_msofbtAnimateData
);
1580 sal_uInt32 nBits
= 0x38;
1581 sal_Int16 nTmp
= xAnimate
->getCalcMode();
1582 sal_uInt32 nCalcMode
= /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp
== AnimationCalcMode::LINEAR
) ? 1 : 0;
1583 sal_uInt32 nValueType
= GetValueTypeForAttributeName( xAnimate
->getAttributeName() );
1585 if ( aBy
.hasValue() )
1587 if ( aFrom
.hasValue() )
1589 if ( aTo
.hasValue() )
1592 rStrm
.WriteUInt32( nCalcMode
)
1593 .WriteUInt32( nBits
)
1594 .WriteUInt32( nValueType
);
1596 if ( aBy
.hasValue() )
1597 exportAnimProperty( rStrm
, 1, aBy
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1598 if ( aFrom
.hasValue() )
1599 exportAnimProperty( rStrm
, 2, aFrom
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1600 if ( aTo
.hasValue() )
1601 exportAnimProperty( rStrm
, 3, aTo
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1603 exportAnimateKeyPoints( rStrm
, xAnimate
);
1604 exportAnimateTarget( rStrm
, xNode
);
1607 void AnimationExporter::exportAnimateTarget( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_uInt32 nForceAttributeNames
, int nAfterEffectType
)
1609 EscherExContainer
aAnimateTarget( rStrm
, DFF_msofbtAnimateTarget
, 0 );
1610 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1611 if ( !xAnimate
.is() )
1615 EscherExAtom
aAnimateTargetSettings( rStrm
, DFF_msofbtAnimateTargetSettings
, 0 );
1616 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1617 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1618 // nAccumulate 0 = none, 1 = always
1619 // nTransformType 0: "property" else "image"
1620 sal_uInt32 nBits
= 0;
1621 sal_uInt32 nAdditive
= 0;
1622 sal_uInt32 nAccumulate
= 0;
1623 sal_uInt32
const nTransformType
= 0;
1624 if ( xAnimate
.is() )
1626 if ( !xAnimate
->getAttributeName().isEmpty() )
1627 nBits
|= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1628 sal_Int16 nAdditiveMode
= xAnimate
->getAdditive();
1629 if ( nAdditiveMode
!= AnimationAdditiveMode::BASE
)
1632 switch( nAdditiveMode
)
1634 case AnimationAdditiveMode::SUM
: nAdditive
= 1; break;
1635 case AnimationAdditiveMode::REPLACE
: nAdditive
= 2; break;
1636 case AnimationAdditiveMode::MULTIPLY
: nAdditive
= 3; break;
1637 case AnimationAdditiveMode::NONE
: nAdditive
= 4; break;
1640 if ( xAnimate
->getAccumulate() )
1646 rStrm
.WriteUInt32( nBits
)
1647 .WriteUInt32( nAdditive
)
1648 .WriteUInt32( nAccumulate
)
1649 .WriteUInt32( nTransformType
);
1651 if ( !xAnimate
->getAttributeName().isEmpty() || nForceAttributeNames
)
1653 EscherExContainer
aAnimateAttributeNames( rStrm
, DFF_msofbtAnimateAttributeNames
, 1 );
1654 OUString
aAttributeName( xAnimate
->getAttributeName() );
1655 if ( nForceAttributeNames
)
1657 if( nForceAttributeNames
== 1 )
1659 aAttributeName
= "r";
1662 sal_Int32 nIndex
= 0;
1665 OUString
aToken( aAttributeName
.getToken( 0, ';', nIndex
) );
1666 exportAnimPropertyString( rStrm
, 0, aToken
, TRANSLATE_ATTRIBUTE
);
1668 while ( nIndex
>= 0 );
1671 if( nAfterEffectType
!= AFTEREFFECT_NONE
)
1673 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
1674 exportAnimPropertyuInt32( rStrm
, 6, 1 );
1675 if( nAfterEffectType
== AFTEREFFECT_COLOR
)
1677 exportAnimPropertyuInt32( rStrm
, 4, 0 );
1678 exportAnimPropertyuInt32( rStrm
, 5, 0 );
1681 exportAnimateTargetElement( rStrm
, aTarget
.hasValue() ? aTarget
: xAnimate
->getTarget(), false );
1684 Reference
< XShape
> AnimationExporter::getTargetElementShape( const Any
& rAny
, sal_Int32
& rBegin
, sal_Int32
& rEnd
, bool& rParagraphTarget
)
1686 Reference
< XShape
> xShape
;
1689 rParagraphTarget
= false;
1693 ParagraphTarget aParaTarget
;
1694 if( rAny
>>= aParaTarget
)
1695 xShape
= aParaTarget
.Shape
;
1698 // now calculating the character range for the paragraph
1699 sal_Int16 nParagraph
= aParaTarget
.Paragraph
;
1700 Reference
< XSimpleText
> xText( xShape
, UNO_QUERY
);
1703 rParagraphTarget
= true;
1704 Reference
< XEnumerationAccess
> xTextParagraphEnumerationAccess( xText
, UNO_QUERY
);
1705 if ( xTextParagraphEnumerationAccess
.is() )
1707 Reference
< XEnumeration
> xTextParagraphEnumeration( xTextParagraphEnumerationAccess
->createEnumeration() );
1708 if ( xTextParagraphEnumeration
.is() )
1710 sal_Int16 nCurrentParagraph
;
1711 rBegin
= rEnd
= nCurrentParagraph
= 0;
1712 while ( xTextParagraphEnumeration
->hasMoreElements() )
1714 Reference
< XTextRange
> xTextRange( xTextParagraphEnumeration
->nextElement(), UNO_QUERY
);
1715 if ( xTextRange
.is() )
1717 OUString
aParaText( xTextRange
->getString() );
1718 sal_Int32 nLength
= aParaText
.getLength() + 1;
1720 if ( nCurrentParagraph
== nParagraph
)
1722 nCurrentParagraph
++;
1735 void AnimationExporter::exportAnimateTargetElement( SvStream
& rStrm
, const Any
& rAny
, const bool bCreate2b01Atom
)
1737 sal_uInt32 nRefMode
= 0; // nRefMode == 2 -> Paragraph
1738 sal_Int32 begin
= -1;
1740 bool bParagraphTarget
;
1742 Reference
< XShape
> xShape
= getTargetElementShape(rAny
, begin
, end
, bParagraphTarget
);
1744 if( bParagraphTarget
)
1747 if ( !(xShape
.is() || bCreate2b01Atom
) )
1750 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
1753 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
1755 sal_uInt32
const nRefType
= 1; // TODO: nRefType == 2 -> Sound;
1756 sal_uInt32 nRefId
= mrSolverContainer
.GetShapeId( xShape
);
1758 rStrm
.WriteUInt32( nRefMode
)
1759 .WriteUInt32( nRefType
)
1760 .WriteUInt32( nRefId
)
1761 .WriteInt32( begin
)
1764 if ( bCreate2b01Atom
)
1766 EscherExAtom
a2b01Atom( rStrm
, 0x2b01 );
1767 rStrm
.WriteUInt32( 1 ); // ?
1771 void AnimationExporter::exportAnimateKeyPoints( SvStream
& rStrm
, const Reference
< XAnimate
>& xAnimate
)
1773 Sequence
< double > aKeyTimes( xAnimate
->getKeyTimes() );
1774 Sequence
< Any
> aValues( xAnimate
->getValues() );
1775 OUString
aFormula( xAnimate
->getFormula() );
1776 if ( !aKeyTimes
.hasElements() )
1779 EscherExContainer
aAnimKeyPoints( rStrm
, DFF_msofbtAnimKeyPoints
);
1781 for ( i
= 0; i
< aKeyTimes
.getLength(); i
++ )
1784 EscherExAtom
aAnimKeyTime( rStrm
, DFF_msofbtAnimKeyTime
);
1785 sal_Int32 nKeyTime
= static_cast<sal_Int32
>( aKeyTimes
[ i
] * 1000.0 );
1786 rStrm
.WriteInt32( nKeyTime
);
1789 if ( aValues
[ i
].hasValue() )
1792 if ( aValues
[ i
] >>= aPair
)
1794 aAny
[ 0 ] = convertAnimateValue( aPair
.First
, xAnimate
->getAttributeName() );
1795 aAny
[ 1 ] = convertAnimateValue( aPair
.Second
, xAnimate
->getAttributeName() );
1799 aAny
[ 0 ] = convertAnimateValue( aValues
[ i
], xAnimate
->getAttributeName() );
1801 if ( !i
&& !aFormula
.isEmpty() )
1803 ImplTranslateAttribute( aFormula
, TRANSLATE_MEASURE
);
1804 aAny
[ 1 ] <<= aFormula
;
1806 exportAnimProperty( rStrm
, 0, aAny
[ 0 ], TRANSLATE_NONE
);
1807 exportAnimProperty( rStrm
, 1, aAny
[ 1 ], TRANSLATE_NONE
);
1812 void AnimationExporter::exportAnimValue( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const bool bExportAlways
)
1816 double fRepeat
= 0.0;
1817 float fRepeatCount
= 0.0;
1818 css::animations::Timing eTiming
;
1819 aAny
= xNode
->getRepeatCount();
1820 if ( aAny
>>= eTiming
)
1822 if ( eTiming
== Timing_INDEFINITE
)
1823 fRepeatCount
= (float(3.40282346638528860e+38));
1825 else if ( aAny
>>= fRepeat
)
1826 fRepeatCount
= static_cast<float>(fRepeat
);
1827 if ( fRepeatCount
!= 0.0 )
1829 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1830 sal_uInt32
const nType
= 0;
1831 rStrm
.WriteUInt32( nType
)
1832 .WriteFloat( fRepeatCount
);
1835 float fAccelerate
= static_cast<float>(xNode
->getAcceleration());
1836 if ( bExportAlways
|| ( fAccelerate
!= 0.0 ) )
1838 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1839 sal_uInt32
const nType
= 3;
1840 rStrm
.WriteUInt32( nType
)
1841 .WriteFloat( fAccelerate
);
1845 float fDecelerate
= static_cast<float>(xNode
->getDecelerate());
1846 if ( bExportAlways
|| ( fDecelerate
!= 0.0 ) )
1848 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1849 sal_uInt32
const nType
= 4;
1850 rStrm
.WriteUInt32( nType
)
1851 .WriteFloat( fDecelerate
);
1855 bool bAutoReverse
= xNode
->getAutoReverse();
1856 if ( bExportAlways
|| bAutoReverse
)
1858 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1859 sal_uInt32
const nType
= 5;
1860 sal_uInt32 nVal
= bAutoReverse
? 1 : 0;
1861 rStrm
.WriteUInt32( nType
)
1862 .WriteUInt32( nVal
);
1866 void AnimationExporter::exportTransitionFilter( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1868 Reference
< XTransitionFilter
> xFilter( xNode
, UNO_QUERY
);
1869 if ( !xFilter
.is() )
1872 EscherExContainer
aAnimateFilter( rStrm
, DFF_msofbtAnimateFilter
);
1874 EscherExAtom
aAnimateFilterData( rStrm
, DFF_msofbtAnimateFilterData
);
1875 sal_uInt32
const nBits
= 3; // bit 0 -> use AnimAttributeValue
1876 // bit 1 -> use nTransition
1878 sal_uInt32 nTransition
= xFilter
->getMode() ? 0 : 1;
1879 rStrm
.WriteUInt32( nBits
)
1880 .WriteUInt32( nTransition
);
1882 const sal_Char
* pFilter
= FindTransitionName( xFilter
->getTransition(), xFilter
->getSubtype(), xFilter
->getDirection() );
1885 const OUString
aStr( OUString::createFromAscii( pFilter
) );
1886 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1888 exportAnimateTarget( rStrm
, xNode
);
1891 void AnimationExporter::exportAnimateMotion( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1893 Reference
< XAnimateMotion
> xMotion( xNode
, UNO_QUERY
);
1894 if ( !xMotion
.is() )
1897 EscherExContainer
aAnimateMotion( rStrm
, DFF_msofbtAnimateMotion
);
1899 { //SJ: Ignored from import filter
1900 EscherExAtom
aAnimateMotionData( rStrm
, DFF_msofbtAnimateMotionData
);
1901 sal_uInt32
const nBits
= 0x98;
1902 sal_uInt32
const nOrigin
= 0x2;
1903 float const fByX
= 100.0; // nBits&1
1904 float const fByY
= 100.0; // nBits&1
1905 float const fFromX
= 0.0; // nBits&2
1906 float const fFromY
= 0.0; // nBits&2
1907 float const fToX
= 100.0; // nBits&4
1908 float const fToY
= 100.0; // nBits&4
1909 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nOrigin
);
1913 if ( xMotion
->getPath() >>= aStr
)
1915 if ( !aStr
.isEmpty() )
1916 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1918 exportAnimateTarget( rStrm
, xNode
);
1922 void AnimationExporter::exportAnimateTransform( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1924 Reference
< XAnimateTransform
> xTransform( xNode
, UNO_QUERY
);
1925 if ( !xTransform
.is() )
1928 if ( xTransform
->getTransformType() == AnimationTransformType::SCALE
)
1930 EscherExContainer
aAnimateScale( rStrm
, DFF_msofbtAnimateScale
);
1932 EscherExAtom
aAnimateScaleData( rStrm
, DFF_msofbtAnimateScaleData
);
1933 sal_uInt32 nBits
= 0;
1934 sal_uInt32
const nZoomContents
= 1;
1942 double fX
= 0.0, fY
= 0.0;
1944 if ( xTransform
->getBy() >>= aPair
)
1946 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1949 fByX
= static_cast<float>( fX
* 100 );
1950 fByY
= static_cast<float>( fY
* 100 );
1953 if ( xTransform
->getFrom() >>= aPair
)
1955 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1958 fFromX
= static_cast<float>( fX
* 100 );
1959 fFromY
= static_cast<float>( fY
* 100 );
1962 if( xTransform
->getTo() >>= aPair
)
1964 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1967 fToX
= static_cast<float>( fX
* 100 );
1968 fToY
= static_cast<float>( fY
* 100 );
1972 // TODO: ZoomContents:
1974 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
1976 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nZoomContents
);
1978 exportAnimateTarget( rStrm
, xNode
);
1980 else if ( xTransform
->getTransformType() == AnimationTransformType::ROTATE
)
1982 EscherExContainer
aAnimateRotation( rStrm
, DFF_msofbtAnimateRotation
);
1984 EscherExAtom
aAnimateRotationData( rStrm
, DFF_msofbtAnimateRotationData
);
1985 sal_uInt32 nBits
= 0;
1986 sal_uInt32
const nU1
= 0;
1992 if ( xTransform
->getBy() >>= fVal
)
1995 fBy
= static_cast<float>(fVal
);
1997 if ( xTransform
->getFrom() >>= fVal
)
2000 fFrom
= static_cast<float>(fVal
);
2002 if ( xTransform
->getTo() >>= fVal
)
2005 fTo
= static_cast<float>(fVal
);
2007 rStrm
.WriteUInt32( nBits
).WriteFloat( fBy
).WriteFloat( fFrom
).WriteFloat( fTo
).WriteUInt32( nU1
);
2009 exportAnimateTarget( rStrm
, xNode
, 1 );
2013 bool AnimationExporter::getColorAny( const Any
& rAny
, const sal_Int16 nColorSpace
, sal_Int32
& rMode
, sal_Int32
& rA
, sal_Int32
& rB
, sal_Int32
& rC
)
2015 bool bIsColor
= true;
2018 if ( nColorSpace
== AnimationColorSpace::HSL
)
2021 sal_Int32 nColor
= 0;
2022 Sequence
< double > aHSL( 3 );
2023 if ( rAny
>>= nColor
) // RGB color
2025 rA
= static_cast<sal_uInt8
>( nColor
>> 16 );
2026 rB
= static_cast<sal_uInt8
>( nColor
>> 8 );
2027 rC
= static_cast<sal_uInt8
>(nColor
);
2029 else if ( rAny
>>= aHSL
) // HSL
2031 rA
= static_cast<sal_Int32
>( aHSL
[ 0 ] * 255.0 / 360.0 );
2032 rB
= static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 );
2033 rC
= static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 );
2040 void AnimationExporter::exportAnimateColor( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
2042 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
2046 EscherExContainer
aAnimateColor( rStrm
, DFF_msofbtAnimateColor
);
2048 EscherExAtom
aAnimateColorData( rStrm
, DFF_msofbtAnimateColorData
);
2049 sal_uInt32 nBits
= 8;
2051 sal_Int32 nByMode
, nByA
, nByB
, nByC
;
2052 nByMode
= nByA
= nByB
= nByC
= 0;
2054 sal_Int32 nFromMode
, nFromA
, nFromB
, nFromC
;
2055 nFromMode
= nFromA
= nFromB
= nFromC
= 0;
2057 sal_Int32 nToMode
, nToA
, nToB
, nToC
;
2058 nToMode
= nToA
= nToB
= nToC
= 0;
2060 sal_Int16 nColorSpace
= xColor
->getColorInterpolation();
2062 Any
aAny( xColor
->getBy() );
2063 if ( aAny
.hasValue() )
2065 if ( getColorAny( aAny
, nColorSpace
, nByMode
, nByA
, nByB
, nByC
) )
2068 aAny
= xColor
->getFrom();
2069 if ( aAny
.hasValue() )
2071 if ( getColorAny( aAny
, nColorSpace
, nFromMode
, nFromA
, nFromB
, nFromC
) )
2074 aAny
= xColor
->getTo();
2075 if ( aAny
.hasValue() )
2077 if ( getColorAny( aAny
, nColorSpace
, nToMode
, nToA
, nToB
, nToC
) )
2080 rStrm
.WriteUInt32( nBits
)
2081 .WriteInt32( nByMode
).WriteInt32( nByA
).WriteInt32( nByB
).WriteInt32( nByC
)
2082 .WriteInt32( nFromMode
).WriteInt32( nFromA
).WriteInt32( nFromB
).WriteInt32( nFromC
)
2083 .WriteInt32( nToMode
).WriteInt32( nToA
).WriteInt32( nToB
).WriteInt32( nToC
);
2085 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
2088 void AnimationExporter::exportIterate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
2090 Reference
< XIterateContainer
> xIterate( xNode
, UNO_QUERY
);
2091 if ( !xIterate
.is() )
2094 EscherExAtom
aAnimIteration( rStrm
, DFF_msofbtAnimIteration
);
2096 float fInterval
= 10.0;
2097 sal_Int32 nTextUnitEffect
= 0;
2098 sal_Int32
const nU1
= 1;
2099 sal_Int32
const nU2
= 1;
2100 sal_Int32
const nU3
= 0xe;
2102 sal_Int16 nIterateType
= xIterate
->getIterateType();
2103 switch( nIterateType
)
2105 case TextAnimationType::BY_WORD
: nTextUnitEffect
= 1; break;
2106 case TextAnimationType::BY_LETTER
: nTextUnitEffect
= 2; break;
2109 fInterval
= static_cast<float>(xIterate
->getIterateInterval());
2111 // convert interval from absolute to percentage
2112 double fDuration
= 0.0;
2114 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
2115 if( xEnumerationAccess
.is() )
2117 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
2118 if( xEnumeration
.is() )
2120 while( xEnumeration
->hasMoreElements() )
2122 Reference
< XAnimate
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
2123 if( xChildNode
.is() )
2125 double fChildBegin
= 0.0;
2126 double fChildDuration
= 0.0;
2127 xChildNode
->getBegin() >>= fChildBegin
;
2128 xChildNode
->getDuration() >>= fChildDuration
;
2130 fChildDuration
+= fChildBegin
;
2131 if( fChildDuration
> fDuration
)
2132 fDuration
= fChildDuration
;
2139 fInterval
= static_cast<float>(100.0 * fInterval
/ fDuration
);
2141 rStrm
.WriteFloat( fInterval
).WriteInt32( nTextUnitEffect
).WriteInt32( nU1
).WriteInt32( nU2
).WriteInt32( nU3
);
2142 aTarget
= xIterate
->getTarget();
2147 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */