1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
21 #include <com/sun/star/animations/AnimationFill.hpp>
22 #include <com/sun/star/animations/AnimationRestart.hpp>
23 #include <com/sun/star/animations/Timing.hpp>
24 #include <com/sun/star/animations/Event.hpp>
25 #include <com/sun/star/animations/AnimationEndSync.hpp>
26 #include <com/sun/star/animations/EventTrigger.hpp>
27 #include <com/sun/star/presentation/EffectNodeType.hpp>
28 #include <com/sun/star/presentation/EffectPresetClass.hpp>
29 #include <com/sun/star/animations/AnimationNodeType.hpp>
30 #include <com/sun/star/animations/AnimationTransformType.hpp>
31 #include <com/sun/star/animations/AnimationCalcMode.hpp>
32 #include <com/sun/star/util/XCloneable.hpp>
33 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
34 #include <com/sun/star/animations/XAnimateSet.hpp>
35 #include <com/sun/star/animations/XAudio.hpp>
36 #include <com/sun/star/animations/XTransitionFilter.hpp>
37 #include <com/sun/star/animations/XAnimateColor.hpp>
38 #include <com/sun/star/animations/XAnimateMotion.hpp>
39 #include <com/sun/star/animations/XAnimateTransform.hpp>
40 #include <com/sun/star/animations/ValuePair.hpp>
41 #include <com/sun/star/animations/AnimationColorSpace.hpp>
42 #include <com/sun/star/drawing/FillStyle.hpp>
43 #include <com/sun/star/drawing/LineStyle.hpp>
44 #include <com/sun/star/drawing/XDrawPage.hpp>
45 #include <com/sun/star/awt/FontWeight.hpp>
46 #include <com/sun/star/awt/FontUnderline.hpp>
47 #include <com/sun/star/awt/FontSlant.hpp>
48 #include <com/sun/star/container/XEnumerationAccess.hpp>
49 #include <com/sun/star/presentation/ParagraphTarget.hpp>
50 #include <com/sun/star/text/XSimpleText.hpp>
51 #include <com/sun/star/animations/XIterateContainer.hpp>
52 #include <com/sun/star/presentation/TextAnimationType.hpp>
54 #include <oox/ppt/pptfilterhelpers.hxx>
55 #include "pptexanimations.hxx"
56 #include "pptexsoundcollection.hxx"
57 #include "../ppt/pptanimations.hxx"
58 #include <filter/msfilter/escherex.hxx>
59 #include <osl/diagnose.h>
60 #include <tools/debug.hxx>
64 using ::com::sun::star::uno::Any
;
65 using ::com::sun::star::util::XCloneable
;
66 using ::com::sun::star::uno::Reference
;
67 using ::com::sun::star::uno::UNO_QUERY
;
68 using ::com::sun::star::uno::UNO_QUERY_THROW
;
69 using ::com::sun::star::uno::Sequence
;
70 using ::com::sun::star::uno::Exception
;
71 using ::com::sun::star::beans::NamedValue
;
72 using ::com::sun::star::container::XEnumerationAccess
;
73 using ::com::sun::star::container::XEnumeration
;
75 using namespace ::com::sun::star::text
;
76 using namespace ::com::sun::star::drawing
;
77 using namespace ::com::sun::star::animations
;
78 using namespace ::com::sun::star::presentation
;
83 static void ImplTranslateAttribute( OUString
& rString
, const TranslateMode eTranslateMode
)
85 if ( eTranslateMode
== TRANSLATE_NONE
)
88 if ( ( eTranslateMode
& TRANSLATE_VALUE
) || ( eTranslateMode
& TRANSLATE_ATTRIBUTE
) )
90 const oox::ppt::ImplAttributeNameConversion
* p
= oox::ppt::getAttributeConversionList();
93 if( rString
.equalsAscii( p
->mpAPIName
) )
99 if ( eTranslateMode
& TRANSLATE_VALUE
)
102 rString
+= OUString::createFromAscii( p
->mpMSName
);
105 rString
= OUString::createFromAscii( p
->mpMSName
);
108 else if ( eTranslateMode
& TRANSLATE_MEASURE
)
110 const char* pDest
[] = { "#ppt_x", "#ppt_y", "#ppt_w", "#ppt_h", nullptr };
111 const char* pSource
[] = { "x", "y", "width", "height", nullptr };
112 sal_Int32 nIndex
= 0;
114 const char** ps
= pSource
;
115 const char** pd
= pDest
;
119 const OUString
aSearch( OUString::createFromAscii( *ps
) );
120 while( (nIndex
= rString
.indexOf( aSearch
, nIndex
)) != -1 )
122 sal_Int32 nLength
= aSearch
.getLength();
123 if( nIndex
&& ( rString
[nIndex
-1] == '#' ) )
129 const OUString
aNew( OUString::createFromAscii( *pd
) );
130 rString
= rString
.replaceAt( nIndex
, nLength
, aNew
);
131 nIndex
+= aNew
.getLength();
139 sal_uInt32
AnimationExporter::TranslatePresetSubType( const sal_uInt32 nPresetClass
, const sal_uInt32 nPresetId
, const OUString
& rPresetSubType
)
141 sal_uInt32 nPresetSubType
= 0;
142 bool bTranslated
= false;
144 if ( ( nPresetClass
== sal_uInt32(EffectPresetClass::ENTRANCE
) ) || ( nPresetClass
== sal_uInt32(EffectPresetClass::EXIT
) ) )
146 if ( nPresetId
!= 21 )
152 if ( rPresetSubType
== "downward" )
157 else if ( rPresetSubType
== "across" )
166 if ( rPresetSubType
== "across" )
175 if ( rPresetSubType
== "right-to-top" )
180 else if ( rPresetSubType
== "right-to-bottom" )
185 else if ( rPresetSubType
== "left-to-top" )
190 else if ( rPresetSubType
== "left-to-bottom" )
201 const oox::ppt::convert_subtype
* p
= oox::ppt::convert_subtype::getList();
202 while( p
->mpStrSubType
)
204 if ( rPresetSubType
.equalsAscii( p
->mpStrSubType
) )
206 nPresetSubType
= p
->mnID
;
215 nPresetSubType
= rPresetSubType
.toUInt32();
216 return nPresetSubType
;
219 const char* AnimationExporter::FindTransitionName( const sal_Int16 nType
, const sal_Int16 nSubType
, const bool bDirection
)
221 const char* pRet
= nullptr;
224 const oox::ppt::transition
* p
= oox::ppt::transition::getList();
228 if ( nType
== p
->mnType
)
230 if ( nSubType
== p
->mnSubType
)
232 if ( bDirection
== p
->mbDirection
)
239 if ( nFit
== 7 ) // maximum
246 SvStream
& WriteAnimationNode(SvStream
& rOut
, AnimationNode
const & rNode
)
248 rOut
.WriteInt32( rNode
.mnU1
);
249 rOut
.WriteInt32( rNode
.mnRestart
);
250 rOut
.WriteInt32( rNode
.mnGroupType
);
251 rOut
.WriteInt32( rNode
.mnFill
);
252 rOut
.WriteInt32( rNode
.mnU3
);
253 rOut
.WriteInt32( rNode
.mnU4
);
254 rOut
.WriteInt32( rNode
.mnDuration
);
255 rOut
.WriteInt32( rNode
.mnNodeType
);
260 AnimationExporter::AnimationExporter( const EscherSolverContainer
& rSolverContainer
, ppt::ExSoundCollection
& rExSoundCollection
) :
261 mrSolverContainer ( rSolverContainer
),
262 mrExSoundCollection ( rExSoundCollection
),
267 sal_Int16
AnimationExporter::GetFillMode( const Reference
< XAnimationNode
>& xNode
, const sal_Int16 nFillDefault
)
269 sal_Int16 nFill
= xNode
->getFill();
270 //#i119699 <Animation> The animation effect "Emphasis->FlashBulb" play incorrectly in Aoo saves a .ppt to another .ppt and plays the saved one.
271 //#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.
272 if ((xNode
->getType() == AnimationNodeType::ANIMATE
)
273 ||(xNode
->getType() == AnimationNodeType::SET
)
274 ||(xNode
->getType() == AnimationNodeType::TRANSITIONFILTER
))
276 if ( nFill
== AnimationFill::DEFAULT
)
280 if ( nFill
== AnimationFill::DEFAULT
)
282 nFill
= nFillDefault
;
284 if( nFill
== AnimationFill::AUTO
)
286 nFill
= AnimationFill::REMOVE
;
287 bool bIsIndefiniteTiming
= true;
288 Any aAny
= xNode
->getDuration();
289 if( aAny
.hasValue() )
292 if( aAny
>>= eTiming
)
293 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
295 if ( bIsIndefiniteTiming
)
297 aAny
= xNode
->getEnd();
298 if( aAny
.hasValue() )
301 if( aAny
>>= eTiming
)
302 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
304 if ( bIsIndefiniteTiming
)
306 if ( !xNode
->getRepeatCount().hasValue() )
308 aAny
= xNode
->getRepeatDuration();
309 if( aAny
.hasValue() )
312 if( aAny
>>= eTiming
)
313 bIsIndefiniteTiming
= eTiming
== Timing_INDEFINITE
;
315 if ( bIsIndefiniteTiming
)
316 nFill
= AnimationFill::FREEZE
;
324 void AnimationExporter::doexport( const Reference
< XDrawPage
>& xPage
, SvStream
& rStrm
)
326 Reference
< XAnimationNodeSupplier
> xNodeSupplier( xPage
, UNO_QUERY
);
327 if( xNodeSupplier
.is() )
329 const Reference
< XAnimationNode
> xRootNode( xNodeSupplier
->getAnimationNode() );
332 processAfterEffectNodes( xRootNode
);
333 exportNode( rStrm
, xRootNode
, DFF_msofbtAnimGroup
, 1, 0, false, AnimationFill::AUTO
);
338 void AnimationExporter::processAfterEffectNodes( const Reference
< XAnimationNode
>& xRootNode
)
342 Reference
< XEnumerationAccess
> xEnumerationAccess( xRootNode
, UNO_QUERY_THROW
);
343 Reference
< XEnumeration
> xEnumeration( xEnumerationAccess
->createEnumeration(), css::uno::UNO_SET_THROW
);
344 while( xEnumeration
->hasMoreElements() )
346 Reference
< XAnimationNode
> xNode( xEnumeration
->nextElement(), UNO_QUERY_THROW
);
348 Reference
< XEnumerationAccess
> xEnumerationAccess2( xNode
, UNO_QUERY
);
349 if ( xEnumerationAccess2
.is() )
351 Reference
< XEnumeration
> xEnumeration2( xEnumerationAccess2
->createEnumeration(), css::uno::UNO_SET_THROW
);
352 while( xEnumeration2
->hasMoreElements() )
354 Reference
< XAnimationNode
> xChildNode( xEnumeration2
->nextElement(), UNO_QUERY_THROW
);
356 Reference
< XEnumerationAccess
> xEnumerationAccess3( xChildNode
, UNO_QUERY_THROW
);
357 Reference
< XEnumeration
> xEnumeration3( xEnumerationAccess3
->createEnumeration(), css::uno::UNO_SET_THROW
);
358 while( xEnumeration3
->hasMoreElements() )
360 Reference
< XAnimationNode
> xChildNode2( xEnumeration3
->nextElement(), UNO_QUERY_THROW
);
362 Reference
< XEnumerationAccess
> xEnumerationAccess4( xChildNode2
, UNO_QUERY_THROW
);
363 Reference
< XEnumeration
> xEnumeration4( xEnumerationAccess4
->createEnumeration(), css::uno::UNO_SET_THROW
);
364 while( xEnumeration4
->hasMoreElements() )
366 Reference
< XAnimationNode
> xChildNode3( xEnumeration4
->nextElement(), UNO_QUERY_THROW
);
368 switch( xChildNode3
->getType() )
370 // found an after effect
371 case AnimationNodeType::SET
:
372 case AnimationNodeType::ANIMATECOLOR
:
374 Reference
< XAnimationNode
> xMaster
;
376 Sequence
< NamedValue
> aUserData( xChildNode3
->getUserData() );
377 const NamedValue
* p
= std::find_if(aUserData
.begin(), aUserData
.end(),
378 [](const NamedValue
& rProp
) { return rProp
.Name
== "master-element"; });
380 if (p
!= aUserData
.end())
381 p
->Value
>>= xMaster
;
383 AfterEffectNodePtr pAfterEffectNode
= std::make_shared
<AfterEffectNode
>( xChildNode3
, xMaster
);
384 maAfterEffectNodes
.push_back( pAfterEffectNode
);
396 OSL_FAIL( "(@CL)AnimationExporter::processAfterEffectNodes(), exception caught!" );
400 bool AnimationExporter::isAfterEffectNode( const Reference
< XAnimationNode
>& xNode
) const
402 return std::any_of(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
403 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxNode
== xNode
; });
406 bool AnimationExporter::hasAfterEffectNode( const Reference
< XAnimationNode
>& xNode
, Reference
< XAnimationNode
>& xAfterEffectNode
) const
408 auto aIter
= std::find_if(maAfterEffectNodes
.begin(), maAfterEffectNodes
.end(),
409 [&xNode
](const AfterEffectNodePtr
& rxNode
) { return rxNode
->mxMaster
== xNode
; });
410 if (aIter
!= maAfterEffectNodes
.end())
412 xAfterEffectNode
= (*aIter
)->mxNode
;
419 // check if this group only contain empty groups. this may happen when
420 // after effect nodes are not exported at their original position
421 bool AnimationExporter::isEmptyNode( const Reference
< XAnimationNode
>& xNode
) const
423 if( xNode
.is() ) switch( xNode
->getType() )
425 case AnimationNodeType::PAR
:
426 case AnimationNodeType::SEQ
:
427 case AnimationNodeType::ITERATE
:
429 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
430 if( xEnumerationAccess
.is() )
432 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
433 if( xEnumeration
.is() )
435 while( xEnumeration
->hasMoreElements() )
437 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
438 if( xChildNode
.is() && !isEmptyNode( xChildNode
) )
446 case AnimationNodeType::SET
:
447 case AnimationNodeType::ANIMATECOLOR
:
448 return isAfterEffectNode( xNode
);
456 void AnimationExporter::exportNode( SvStream
& rStrm
, Reference
< XAnimationNode
> const & xNode_in
, const sal_uInt16 nContainerRecType
,
457 const sal_uInt16 nInstance
, const sal_Int32 nGroupLevel
, const bool bTakeBackInteractiveSequenceTiming
, const sal_Int16 nFDef
)
459 auto xNode
= xNode_in
;
461 if( (nGroupLevel
== 4) && isEmptyNode( xNode
) )
464 if ( ( nContainerRecType
== DFF_msofbtAnimGroup
) && ( nGroupLevel
== 2 ) && isEmptyNode( xNode
) )
467 if( nContainerRecType
== DFF_msofbtAnimGroup
)
470 bool bTakeBackInteractiveSequenceTimingForChild
= false;
471 sal_Int16 nFillDefault
= GetFillMode( xNode
, nFDef
);
473 Reference
< XAnimationNode
> xAudioNode
;
474 static sal_uInt32 nAudioGroup
;
477 bool bSkipChildren
= false;
478 EscherExContainer
aContainer( rStrm
, nContainerRecType
, nInstance
);
479 switch( xNode
->getType() )
481 case AnimationNodeType::CUSTOM
:
483 exportAnimNode( rStrm
, xNode
, nFillDefault
);
484 exportAnimPropertySet( rStrm
, xNode
);
485 exportAnimEvent( rStrm
, xNode
);
486 exportAnimValue( rStrm
, xNode
, false );
490 case AnimationNodeType::PAR
:
492 exportAnimNode( rStrm
, xNode
, nFillDefault
);
493 exportAnimPropertySet( rStrm
, xNode
);
494 sal_Int32 nFlags
= nGroupLevel
== 2 ? 0x10 : 0;
495 if ( bTakeBackInteractiveSequenceTiming
)
497 exportAnimEvent( rStrm
, xNode
, nFlags
);
498 exportAnimValue( rStrm
, xNode
, nGroupLevel
== 4 );
502 case AnimationNodeType::SEQ
:
504 exportAnimNode( rStrm
, xNode
, nFillDefault
);
505 sal_Int16 nNodeType
= exportAnimPropertySet( rStrm
, xNode
);
506 sal_Int32 nFlags
= 12;
507 if ( ( nGroupLevel
== 1 ) && ( nNodeType
== css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
) )
510 bTakeBackInteractiveSequenceTimingForChild
= true;
512 exportAnimAction( rStrm
, xNode
);
513 exportAnimEvent( rStrm
, xNode
, nFlags
);
514 exportAnimValue( rStrm
, xNode
, false );
518 case AnimationNodeType::ITERATE
:
521 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
523 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
524 aAnim
.mnNodeType
= 1;
526 switch( xNode
->getRestart() )
529 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
530 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
531 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
532 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
535 switch( xNode
->getFill() )
538 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
539 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
540 case AnimationFill::FREEZE
: aAnim
.mnFill
= 2; break;
541 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
542 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
544 WriteAnimationNode( rStrm
, aAnim
);
546 exportIterate( rStrm
, xNode
);
547 exportAnimPropertySet( rStrm
, xNode
);
548 exportAnimEvent( rStrm
, xNode
);
549 exportAnimValue( rStrm
, xNode
, false );
553 case AnimationNodeType::ANIMATE
:
555 exportAnimNode( rStrm
, xNode
, nFillDefault
);
556 exportAnimPropertySet( rStrm
, xNode
);
557 exportAnimEvent( rStrm
, xNode
);
558 exportAnimValue( rStrm
, xNode
, false );
559 exportAnimate( rStrm
, xNode
);
563 case AnimationNodeType::SET
:
565 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
566 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
568 exportAnimNode( rStrm
, xNode
, nFillDefault
);
569 exportAnimPropertySet( rStrm
, xNode
);
570 exportAnimateSet( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_SET
: AFTEREFFECT_NONE
);
571 exportAnimEvent( rStrm
, xNode
);
572 exportAnimValue( rStrm
, xNode
, false );
576 bSkipChildren
= true;
581 case AnimationNodeType::ANIMATEMOTION
:
583 exportAnimNode( rStrm
, xNode
, nFillDefault
);
584 exportAnimPropertySet( rStrm
, xNode
);
585 exportAnimateMotion( rStrm
, xNode
);
586 exportAnimEvent( rStrm
, xNode
);
587 exportAnimValue( rStrm
, xNode
, false );
591 case AnimationNodeType::ANIMATECOLOR
:
593 bool bIsAfterEffectNode( isAfterEffectNode( xNode
) );
594 if( (nGroupLevel
!= 4) || !bIsAfterEffectNode
)
596 if( bIsAfterEffectNode
)
597 xNode
= createAfterEffectNodeClone( xNode
);
599 exportAnimNode( rStrm
, xNode
, nFillDefault
);
600 exportAnimPropertySet( rStrm
, xNode
);
601 exportAnimateColor( rStrm
, xNode
, bIsAfterEffectNode
? AFTEREFFECT_COLOR
: AFTEREFFECT_NONE
);
602 exportAnimEvent( rStrm
, xNode
);
603 exportAnimValue( rStrm
, xNode
, false );
607 bSkipChildren
= true;
612 case AnimationNodeType::ANIMATETRANSFORM
:
614 exportAnimNode( rStrm
, xNode
, nFillDefault
);
615 exportAnimPropertySet( rStrm
, xNode
);
616 exportAnimateTransform( rStrm
, xNode
);
617 exportAnimEvent( rStrm
, xNode
);
618 exportAnimValue( rStrm
, xNode
, false );
622 case AnimationNodeType::TRANSITIONFILTER
:
624 exportAnimNode( rStrm
, xNode
, nFillDefault
);
625 exportAnimPropertySet( rStrm
, xNode
);
626 exportAnimEvent( rStrm
, xNode
);
627 exportAnimValue( rStrm
, xNode
, false );
628 exportTransitionFilter( rStrm
, xNode
);
632 case AnimationNodeType::AUDIO
: // #i58428#
634 exportAnimNode( rStrm
, xNode
, nFillDefault
);
635 exportAnimPropertySet( rStrm
, xNode
);
637 Reference
< XAudio
> xAudio( xNode
, UNO_QUERY
);
640 Any
aAny( xAudio
->getSource() );
643 if ( ( aAny
>>= aURL
) && !aURL
.isEmpty() )
646 sal_Int32 nTrigger
= 3;
647 sal_Int32 nU3
= nAudioGroup
;
648 sal_Int32 nBegin
= 0;
650 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 1 );
652 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
653 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
660 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, 2 );
662 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
663 rStrm
.WriteInt32( nU1
).WriteInt32( nTrigger
).WriteInt32( nU3
).WriteInt32( nBegin
);
666 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
668 sal_uInt32
const nRefMode
= 3;
669 sal_uInt32
const nRefType
= 2;
670 sal_uInt32 nRefId
= mrExSoundCollection
.GetId( aURL
);
671 sal_Int32
const begin
= -1;
672 sal_Int32
const end
= -1;
674 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
675 rStrm
.WriteUInt32( nRefMode
).WriteUInt32( nRefType
).WriteUInt32( nRefId
).WriteInt32( begin
).WriteInt32( end
);
679 exportAnimValue( rStrm
, xNode
, false );
685 // export after effect node if one exists for this node
686 Reference
< XAnimationNode
> xAfterEffectNode
;
687 if( hasAfterEffectNode( xNode
, xAfterEffectNode
) )
689 exportNode( rStrm
, xAfterEffectNode
, DFF_msofbtAnimSubGoup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
692 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
693 if( xEnumerationAccess
.is() )
695 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
696 if( xEnumeration
.is() )
698 while( xEnumeration
->hasMoreElements() )
700 Reference
< XAnimationNode
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
701 if( xChildNode
.is() )
703 if ( xChildNode
->getType() == AnimationNodeType::AUDIO
)
705 xAudioNode
= xChildNode
;
706 nAudioGroup
= mnCurrentGroup
;
709 exportNode( rStrm
, xChildNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
+ 1, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
716 if ( xAudioNode
.is() )
717 exportNode( rStrm
, xAudioNode
, DFF_msofbtAnimGroup
, 1, nGroupLevel
, bTakeBackInteractiveSequenceTimingForChild
, nFillDefault
);
719 if( xNode
->getType() == AnimationNodeType::ITERATE
)
723 Reference
< XAnimationNode
> AnimationExporter::createAfterEffectNodeClone( const Reference
< XAnimationNode
>& xNode
)
727 Reference
< css::util::XCloneable
> xClonable( xNode
, UNO_QUERY_THROW
);
728 Reference
< XAnimationNode
> xCloneNode( xClonable
->createClone(), UNO_QUERY_THROW
);
731 xCloneNode
->setBegin( aEmpty
);
737 OSL_FAIL("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
742 bool AnimationExporter::GetNodeType( const Reference
< XAnimationNode
>& xNode
, sal_Int16
& nType
)
744 // trying to get the nodetype
745 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
746 for( const NamedValue
& rProp
: aUserData
)
748 if ( rProp
.Name
== "node-type" )
750 if ( rProp
.Value
>>= nType
)
758 void AnimationExporter::exportAnimNode( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
,
759 const sal_Int16 nFillDefault
)
761 EscherExAtom
aAnimNodeExAtom( rStrm
, DFF_msofbtAnimNode
);
765 switch( xNode
->getRestart() )
768 case AnimationRestart::DEFAULT
: aAnim
.mnRestart
= 0; break;
769 case AnimationRestart::ALWAYS
: aAnim
.mnRestart
= 1; break;
770 case AnimationRestart::WHEN_NOT_ACTIVE
: aAnim
.mnRestart
= 2; break;
771 case AnimationRestart::NEVER
: aAnim
.mnRestart
= 3; break;
774 switch( nFillDefault
)
777 case AnimationFill::DEFAULT
: aAnim
.mnFill
= 0; break;
778 case AnimationFill::REMOVE
: aAnim
.mnFill
= 1; break;
779 case AnimationFill::FREEZE
:
780 case AnimationFill::HOLD
: aAnim
.mnFill
= 3; break;
781 case AnimationFill::TRANSITION
: aAnim
.mnFill
= 4; break;
783 // attribute Duration
784 double fDuration
= 0.0;
785 css::animations::Timing eTiming
;
786 if ( xNode
->getDuration() >>= eTiming
)
788 if ( eTiming
== Timing_INDEFINITE
)
789 aAnim
.mnDuration
= -1;
791 else if ( xNode
->getDuration() >>= fDuration
)
793 aAnim
.mnDuration
= static_cast<sal_Int32
>( fDuration
* 1000.0 );
796 aAnim
.mnDuration
= -1;
798 // NodeType, NodeGroup
799 aAnim
.mnNodeType
= 1;
800 aAnim
.mnGroupType
= mso_Anim_GroupType_SEQ
;
801 switch( xNode
->getType() )
803 case AnimationNodeType::PAR
:
804 aAnim
.mnGroupType
= mso_Anim_GroupType_PAR
;
806 case AnimationNodeType::SEQ
:
809 if( GetNodeType( xNode
, nType
) )
812 case css::presentation::EffectNodeType::TIMING_ROOT
: aAnim
.mnNodeType
= 0x12; break;
813 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: aAnim
.mnNodeType
= 0x18; break;
818 case AnimationNodeType::ANIMATE
:
819 case AnimationNodeType::SET
:
821 case AnimationNodeType::CUSTOM
:
822 case AnimationNodeType::ITERATE
:
823 case AnimationNodeType::ANIMATEMOTION
:
824 case AnimationNodeType::ANIMATECOLOR
:
825 case AnimationNodeType::ANIMATETRANSFORM
:
827 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
828 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
832 case AnimationNodeType::AUDIO
:
834 aAnim
.mnGroupType
= mso_Anim_GroupType_MEDIA
;
835 aAnim
.mnNodeType
= mso_Anim_Behaviour_ANIMATION
;
839 case AnimationNodeType::TRANSITIONFILTER
:
841 aAnim
.mnGroupType
= mso_Anim_GroupType_NODE
;
842 aAnim
.mnNodeType
= mso_Anim_Behaviour_FILTER
;
847 WriteAnimationNode( rStrm
, aAnim
);
850 void AnimationExporter::GetUserData( const Sequence
< NamedValue
>& rUserData
, const Any
** pAny
, std::size_t nLen
)
852 // storing user data into pAny, to allow direct access later
853 memset( pAny
, 0, nLen
);
854 if ( !rUserData
.hasElements() )
857 for( const NamedValue
& rProp
: rUserData
)
859 if ( rProp
.Name
== "node-type" )
861 pAny
[ DFF_ANIM_NODE_TYPE
] = &(rProp
.Value
);
863 else if ( rProp
.Name
== "preset-class" )
865 pAny
[ DFF_ANIM_PRESET_CLASS
] = &(rProp
.Value
);
867 else if ( rProp
.Name
== "preset-id" )
869 pAny
[ DFF_ANIM_PRESET_ID
] = &(rProp
.Value
);
871 else if ( rProp
.Name
== "preset-sub-type" )
873 pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] = &(rProp
.Value
);
875 else if ( rProp
.Name
== "master-element" )
877 pAny
[ DFF_ANIM_AFTEREFFECT
] = &(rProp
.Value
);
882 sal_uInt32
AnimationExporter::GetPresetID( const OUString
& rPreset
, sal_uInt32 nAPIPresetClass
, bool& bPresetId
)
884 sal_uInt32 nPresetId
= 0;
887 if ( rPreset
.match("ppt_", 0) )
889 sal_Int32 nLast
= rPreset
.lastIndexOf( '_' );
890 if ( ( nLast
!= -1 ) && ( ( nLast
+ 1 ) < rPreset
.getLength() ) )
892 OUString
aNumber( rPreset
.copy( nLast
+ 1 ) );
893 nPresetId
= aNumber
.toUInt32();
899 const oox::ppt::preset_mapping
* p
= oox::ppt::preset_mapping::getList();
900 while( p
->mpStrPresetId
&& ((p
->mnPresetClass
!= static_cast<sal_Int32
>(nAPIPresetClass
)) || !rPreset
.equalsAscii( p
->mpStrPresetId
)) )
903 if( p
->mpStrPresetId
)
905 nPresetId
= p
->mnPresetId
;
913 sal_Int16
AnimationExporter::exportAnimPropertySet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
915 sal_Int16 nNodeType
= css::presentation::EffectNodeType::DEFAULT
;
917 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
919 Reference
< XAnimationNode
> xMaster
;
921 Any aMasterRel
, aOverride
, aRunTimeContext
;
923 // storing user data into pAny, to allow direct access later
924 const Sequence
< NamedValue
> aUserData
= xNode
->getUserData();
925 const css::uno::Any
* pAny
[ DFF_ANIM_PROPERTY_ID_COUNT
];
926 GetUserData( aUserData
, pAny
, sizeof( pAny
) );
928 if( pAny
[ DFF_ANIM_AFTEREFFECT
] )
929 ( *pAny
[ DFF_ANIM_AFTEREFFECT
] ) >>= xMaster
;
931 // calculate master-rel
934 sal_Int32 nMasterRel
= 2;
935 if( xNode
.is() && xMaster
.is() && (xNode
->getParent() == xMaster
->getParent() ) )
938 aMasterRel
<<= nMasterRel
;
940 pAny
[ DFF_ANIM_MASTERREL
] = &aMasterRel
;
942 aOverride
<<= sal_Int32(1);
943 pAny
[ DFF_ANIM_OVERRIDE
] = &aOverride
;
945 aRunTimeContext
<<= sal_Int32(1);
946 pAny
[ DFF_ANIM_RUNTIMECONTEXT
] = &aRunTimeContext
;
949 // the order is important
950 if ( pAny
[ DFF_ANIM_NODE_TYPE
] )
952 if ( *pAny
[ DFF_ANIM_NODE_TYPE
] >>= nNodeType
)
954 sal_uInt32 nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
;
957 case css::presentation::EffectNodeType::ON_CLICK
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_ON_CLICK
; break;
958 case css::presentation::EffectNodeType::WITH_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_WITH_PREVIOUS
; break;
959 case css::presentation::EffectNodeType::AFTER_PREVIOUS
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS
; break;
960 case css::presentation::EffectNodeType::MAIN_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE
; break;
961 case css::presentation::EffectNodeType::TIMING_ROOT
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_TIMING_ROOT
; break;
962 case css::presentation::EffectNodeType::INTERACTIVE_SEQUENCE
: nPPTNodeType
= DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ
; break;
964 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_NODE_TYPE
, nPPTNodeType
);
967 sal_uInt32 nPresetId
= 0;
968 sal_uInt32 nPresetSubType
= 0;
969 sal_uInt32 nAPIPresetClass
= EffectPresetClass::CUSTOM
;
970 sal_uInt32 nPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
971 bool bPresetClass
, bPresetId
, bPresetSubType
;
972 bPresetId
= bPresetClass
= bPresetSubType
= false;
974 if ( pAny
[ DFF_ANIM_PRESET_CLASS
] )
976 if ( *pAny
[ DFF_ANIM_PRESET_CLASS
] >>= nAPIPresetClass
)
978 sal_uInt8 nPPTPresetClass
;
979 switch( nAPIPresetClass
)
981 case EffectPresetClass::ENTRANCE
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_ENTRANCE
; break;
982 case EffectPresetClass::EXIT
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EXIT
; break;
983 case EffectPresetClass::EMPHASIS
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_EMPHASIS
; break;
984 case EffectPresetClass::MOTIONPATH
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MOTIONPATH
; break;
985 case EffectPresetClass::OLEACTION
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_OLE_ACTION
; break;
986 case EffectPresetClass::MEDIACALL
: nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_MEDIACALL
; break;
988 nPPTPresetClass
= DFF_ANIM_PRESS_CLASS_USER_DEFINED
;
990 nPresetClass
= nPPTPresetClass
;
994 if ( pAny
[ DFF_ANIM_PRESET_ID
] )
997 if ( *pAny
[ DFF_ANIM_PRESET_ID
] >>= sPreset
)
998 nPresetId
= GetPresetID( sPreset
, nAPIPresetClass
, bPresetId
);
1001 if ( pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] )
1003 OUString sPresetSubType
;
1004 if ( *pAny
[ DFF_ANIM_PRESET_SUB_TYPE
] >>= sPresetSubType
)
1006 nPresetSubType
= TranslatePresetSubType( nPresetClass
, nPresetId
, sPresetSubType
);
1007 bPresetSubType
= true;
1011 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_ID
, nPresetId
);
1012 if ( bPresetSubType
)
1013 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_SUB_TYPE
, nPresetSubType
);
1015 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_PRESET_CLASS
, nPresetClass
);
1017 if ( pAny
[ DFF_ANIM_ID
] )
1022 if ( pAny
[ DFF_ANIM_AFTEREFFECT
] )
1024 bool bAfterEffect
= false;
1025 if ( *pAny
[ DFF_ANIM_AFTEREFFECT
] >>= bAfterEffect
)
1026 exportAnimPropertyByte( rStrm
, DFF_ANIM_AFTEREFFECT
, int(bAfterEffect
) );
1029 if ( pAny
[ DFF_ANIM_RUNTIMECONTEXT
] )
1031 sal_Int32 nRunTimeContext
= 0;
1032 if ( *pAny
[ DFF_ANIM_RUNTIMECONTEXT
] >>= nRunTimeContext
)
1033 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_RUNTIMECONTEXT
, nRunTimeContext
);
1035 if ( pAny
[ DFF_ANIM_PATH_EDIT_MODE
] )
1042 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
1046 bool bDirection
= !xColor
->getDirection();
1047 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_DIRECTION
, bDirection
? 1 : 0 );
1051 if ( pAny
[ DFF_ANIM_OVERRIDE
] )
1053 sal_Int32 nOverride
= 0;
1054 if ( *pAny
[ DFF_ANIM_OVERRIDE
] >>= nOverride
)
1055 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_OVERRIDE
, nOverride
);
1058 if ( pAny
[ DFF_ANIM_MASTERREL
] )
1060 sal_Int32 nMasterRel
= 0;
1061 if ( *pAny
[ DFF_ANIM_MASTERREL
] >>= nMasterRel
)
1062 exportAnimPropertyuInt32( rStrm
, DFF_ANIM_MASTERREL
, nMasterRel
);
1066 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1069 sal_Int16 nEndAfterSlide = 0;
1070 nEndAfterSlide = xAudio->getEndAfterSlide();
1071 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1074 Reference
< XAnimate
> xAnim( xNode
, UNO_QUERY
);
1077 // TODO: DFF_ANIM_TIMEFILTER
1079 if ( pAny
[ DFF_ANIM_EVENT_FILTER
] )
1081 // TODO DFF_ANIM_EVENT_FILTER
1083 if ( pAny
[ DFF_ANIM_VOLUME
] )
1085 // TODO DFF_ANIM_VOLUME
1090 bool AnimationExporter::exportAnimProperty( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const css::uno::Any
& rAny
, const TranslateMode eTranslateMode
)
1093 if ( rAny
.hasValue() )
1095 switch( rAny
.getValueType().getTypeClass() )
1097 case css::uno::TypeClass_UNSIGNED_SHORT
:
1098 case css::uno::TypeClass_SHORT
:
1099 case css::uno::TypeClass_UNSIGNED_LONG
:
1100 case css::uno::TypeClass_LONG
:
1103 if ( rAny
>>= nVal
)
1105 exportAnimPropertyuInt32( rStrm
, nPropertyId
, nVal
);
1111 case css::uno::TypeClass_DOUBLE
:
1114 if ( rAny
>>= fVal
)
1116 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1121 case css::uno::TypeClass_FLOAT
:
1124 if ( rAny
>>= fVal
)
1126 if ( eTranslateMode
& TRANSLATE_NUMBER_TO_STRING
)
1128 OUString
aNumber( OUString::number( fVal
) );
1129 exportAnimPropertyString( rStrm
, nPropertyId
, aNumber
, eTranslateMode
);
1133 exportAnimPropertyFloat( rStrm
, nPropertyId
, fVal
);
1139 case css::uno::TypeClass_STRING
:
1142 if ( rAny
>>= aStr
)
1144 exportAnimPropertyString( rStrm
, nPropertyId
, aStr
, eTranslateMode
);
1155 void AnimationExporter::exportAnimPropertyString( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const OUString
& rVal
, const TranslateMode eTranslateMode
)
1157 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1158 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_UNISTRING
);
1159 OUString
aStr( rVal
);
1160 if ( eTranslateMode
!= TRANSLATE_NONE
)
1161 ImplTranslateAttribute( aStr
, eTranslateMode
);
1162 writeZString( rStrm
, aStr
);
1165 void AnimationExporter::exportAnimPropertyFloat( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const double& rVal
)
1167 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1168 float fFloat
= static_cast<float>(rVal
);
1169 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_FLOAT
)
1170 .WriteFloat( fFloat
);
1173 void AnimationExporter::exportAnimPropertyuInt32( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt32 nVal
)
1175 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1176 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_INT32
)
1177 .WriteUInt32( nVal
);
1180 void AnimationExporter::exportAnimPropertyByte( SvStream
& rStrm
, const sal_uInt16 nPropertyId
, const sal_uInt8 nVal
)
1182 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAttributeValue
, nPropertyId
);
1183 rStrm
.WriteUChar( DFF_ANIM_PROP_TYPE_BYTE
)
1184 .WriteUChar( nVal
);
1187 void AnimationExporter::writeZString( SvStream
& rStrm
, const OUString
& rVal
)
1190 for ( i
= 0; i
< rVal
.getLength(); i
++ )
1191 rStrm
.WriteUInt16( rVal
[ i
] );
1192 rStrm
.WriteUInt16( 0 );
1195 void AnimationExporter::exportAnimAction( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1197 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimAction
);
1199 sal_Int32
const nConcurrent
= 1;
1200 sal_Int32
const nNextAction
= 1;
1201 sal_Int32 nEndSync
= 0;
1202 sal_Int32
const nU4
= 0;
1203 sal_Int32
const nU5
= 3;
1205 sal_Int16 nAnimationEndSync
= 0;
1206 if ( xNode
->getEndSync() >>= nAnimationEndSync
)
1208 if ( nAnimationEndSync
== AnimationEndSync::ALL
)
1211 rStrm
.WriteInt32( nConcurrent
)
1212 .WriteInt32( nNextAction
)
1213 .WriteInt32( nEndSync
)
1219 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1220 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1221 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
1222 void AnimationExporter::exportAnimEvent( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_Int32 nFlags
)
1225 for ( i
= 0; i
< 4; i
++ )
1228 sal_Int32 nTrigger
= 0;
1230 sal_Int32 nBegin
= 0;
1232 bool bCreateEvent
= false;
1242 css::animations::Timing eTiming
;
1245 if ( nFlags
& 0x20 )
1247 // taking the first child
1248 Reference
< XEnumerationAccess
> xEA( xNode
, UNO_QUERY_THROW
);
1249 Reference
< XEnumeration
> xE( xEA
->createEnumeration(), css::uno::UNO_SET_THROW
);
1250 if ( xE
->hasMoreElements() )
1252 Reference
< XAnimationNode
> xClickNode( xE
->nextElement(), UNO_QUERY
);
1253 aAny
= xClickNode
->getBegin();
1256 else if ( nFlags
& 0x40 )
1258 // begin has to be replaced with void, so don't do anything
1262 aAny
= xNode
->getBegin();
1263 if ( nFlags
& 0x10 ) // replace ON_NEXT with INDEFINITE
1265 if ( ( aAny
>>= aEvent
) && ( aEvent
.Trigger
== EventTrigger::ON_NEXT
) )
1267 eTiming
= Timing_INDEFINITE
;
1274 aAny
= xNode
->getEnd();
1276 double fTiming
= 0.0;
1277 if ( aAny
>>= aEvent
)
1279 bCreateEvent
= true;
1280 switch( aEvent
.Trigger
)
1282 case EventTrigger::NONE
: nTrigger
= 0; break;
1283 case EventTrigger::ON_BEGIN
: nTrigger
= 1; break;
1284 case EventTrigger::ON_END
: nTrigger
= 2; break;
1285 case EventTrigger::BEGIN_EVENT
: nTrigger
= 3; break;
1286 case EventTrigger::END_EVENT
: nTrigger
= 4; nU1
= 2; nU3
= mnCurrentGroup
; break;
1287 case EventTrigger::ON_CLICK
: nTrigger
= 5; break;
1288 case EventTrigger::ON_DBL_CLICK
: nTrigger
= 6; break;
1289 case EventTrigger::ON_MOUSE_ENTER
: nTrigger
= 7; break;
1290 case EventTrigger::ON_MOUSE_LEAVE
: nTrigger
= 8; break;
1291 case EventTrigger::ON_NEXT
: nTrigger
= 9; break;
1292 case EventTrigger::ON_PREV
: nTrigger
= 10; break;
1293 case EventTrigger::ON_STOP_AUDIO
: nTrigger
= 11; break;
1295 if ( aEvent
.Offset
.hasValue() )
1297 if ( aEvent
.Offset
>>= eTiming
)
1299 if ( eTiming
== Timing_INDEFINITE
)
1302 else if ( aEvent
.Offset
>>= fTiming
)
1303 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1305 aSource
= aEvent
.Source
;
1307 else if ( aAny
>>= eTiming
)
1309 bCreateEvent
= true;
1310 if ( eTiming
== Timing_INDEFINITE
)
1313 else if ( aAny
>>= fTiming
)
1315 bCreateEvent
= true;
1316 nBegin
= static_cast<sal_Int32
>( fTiming
* 1000.0 );
1323 if ( nFlags
& ( 1 << i
) )
1325 bCreateEvent
= true;
1333 if ( nFlags
& ( 1 << i
) )
1335 bCreateEvent
= true;
1344 EscherExContainer
aAnimEvent( rStrm
, DFF_msofbtAnimEvent
, i
+ 1 );
1346 EscherExAtom
aAnimTrigger( rStrm
, DFF_msofbtAnimTrigger
);
1347 rStrm
.WriteInt32( nU1
)
1348 .WriteInt32( nTrigger
)
1350 .WriteInt32( nBegin
);
1352 exportAnimateTargetElement( rStrm
, aSource
, ( nFlags
& ( 1 << i
) ) != 0 );
1357 Any
AnimationExporter::convertAnimateValue( const Any
& rSourceValue
, const OUString
& rAttributeName
)
1360 if ( rAttributeName
== "X"
1361 || rAttributeName
== "Y"
1362 || rAttributeName
== "Width"
1363 || rAttributeName
== "Height"
1367 if ( rSourceValue
>>= aStr
)
1369 ImplTranslateAttribute( aStr
, TRANSLATE_MEASURE
);
1373 else if ( rAttributeName
== "Rotate" // "r" or "style.rotation" ?
1374 || rAttributeName
== "Opacity"
1375 || rAttributeName
== "CharHeight"
1376 || rAttributeName
== "SkewX"
1379 double fNumber
= 0.0;
1380 if ( rSourceValue
>>= fNumber
)
1381 aDest
+= OUString::number( fNumber
);
1383 else if ( rAttributeName
== "Color"
1384 || rAttributeName
== "FillColor" // "Fillcolor" or "FillColor" ?
1385 || rAttributeName
== "LineColor"
1386 || rAttributeName
== "CharColor"
1389 sal_Int32 nColor
= 0;
1390 Sequence
< double > aHSL( 3 );
1392 if ( rSourceValue
>>= aHSL
)
1395 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 0 ] / ( 360.0 / 255 ) ) )
1397 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 ) )
1399 + OUString::number( static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 ) )
1402 else if ( rSourceValue
>>= nColor
)
1405 + OUString::number( static_cast<sal_Int8
>(nColor
) )
1407 + OUString::number( static_cast<sal_Int8
>( nColor
>> 8 ) )
1409 + OUString::number( static_cast<sal_Int8
>( nColor
>> 16 ) )
1413 else if ( rAttributeName
== "FillStyle" )
1415 css::drawing::FillStyle eFillStyle
;
1416 if ( rSourceValue
>>= eFillStyle
)
1418 if ( eFillStyle
== css::drawing::FillStyle_NONE
)
1419 aDest
+= "none"; // ?
1424 else if (rAttributeName
== "FillOn")
1427 if ( rSourceValue
>>= bFillOn
)
1435 else if ( rAttributeName
== "LineStyle" )
1437 css::drawing::LineStyle eLineStyle
;
1438 if ( rSourceValue
>>= eLineStyle
)
1440 if ( eLineStyle
== css::drawing::LineStyle_NONE
)
1446 else if ( rAttributeName
== "CharWeight" )
1448 float fFontWeight
= 0.0;
1449 if ( rSourceValue
>>= fFontWeight
)
1451 if ( fFontWeight
== css::awt::FontWeight::BOLD
)
1457 else if ( rAttributeName
== "CharUnderline" )
1459 sal_Int16 nFontUnderline
= 0;
1460 if ( rSourceValue
>>= nFontUnderline
)
1462 if ( nFontUnderline
== css::awt::FontUnderline::NONE
)
1468 else if ( rAttributeName
== "CharPosture" )
1470 css::awt::FontSlant eFontSlant
;
1471 if ( rSourceValue
>>= eFontSlant
)
1473 if ( eFontSlant
== css::awt::FontSlant_ITALIC
)
1476 aDest
+= "normal"; // ?
1479 else if ( rAttributeName
== "Visibility" )
1481 bool bVisible
= true;
1482 if ( rSourceValue
>>= bVisible
)
1491 if ( !aDest
.isEmpty() )
1494 aRet
= rSourceValue
;
1498 void AnimationExporter::exportAnimateSet( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
1500 Reference
< XAnimateSet
> xSet( xNode
, UNO_QUERY
);
1504 EscherExContainer
aAnimateSet( rStrm
, DFF_msofbtAnimateSet
, 0 );
1506 EscherExAtom
aAnimateSetData( rStrm
, DFF_msofbtAnimateSetData
);
1507 sal_uInt32
const nId1
= 1; // ??
1508 sal_uInt32
const nId2
= 1; // ??
1509 rStrm
.WriteUInt32( nId1
).WriteUInt32( nId2
);
1511 Any
aConvertedValue( convertAnimateValue( xSet
->getTo(), xSet
->getAttributeName() ) );
1512 if ( aConvertedValue
.hasValue() )
1513 exportAnimProperty( rStrm
, 1, aConvertedValue
, TRANSLATE_NONE
);
1514 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
1517 sal_uInt32
AnimationExporter::GetValueTypeForAttributeName( const OUString
& rAttributeName
)
1519 sal_uInt32 nValueType
= 0;
1526 static const Entry lcl_attributeMap
[] =
1529 { "charfontname", 0 },
1530 { "charheight", 1 },
1531 { "charposture", 0 },
1532 // TODO(Q1): This should prolly be changed in PPT import
1533 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1534 { "charrotation", 1 },
1535 { "charunderline", 0 },
1536 { "charweight", 0 },
1548 { "visibility", 1 },
1554 const Entry
* pPtr
= &lcl_attributeMap
[ 0 ];
1555 while( pPtr
->pName
)
1557 if ( rAttributeName
.equalsIgnoreAsciiCaseAscii( pPtr
->pName
) )
1559 nValueType
= pPtr
->nType
;
1564 DBG_ASSERT( pPtr
->pName
, "GetValueTypeForAttributeName, unknown property value!" );
1568 void AnimationExporter::exportAnimate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1570 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1571 if ( !xAnimate
.is() )
1574 Any
aBy ( xAnimate
->getBy() );
1575 Any
aFrom( xAnimate
->getFrom() );
1576 Any
aTo ( xAnimate
->getTo() );
1578 EscherExContainer
aContainer( rStrm
, DFF_msofbtAnimate
, 0 );
1580 EscherExAtom
aAnimateData( rStrm
, DFF_msofbtAnimateData
);
1581 sal_uInt32 nBits
= 0x38;
1582 sal_Int16 nTmp
= xAnimate
->getCalcMode();
1583 sal_uInt32 nCalcMode
= /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp
== AnimationCalcMode::LINEAR
) ? 1 : 0;
1584 sal_uInt32 nValueType
= GetValueTypeForAttributeName( xAnimate
->getAttributeName() );
1586 if ( aBy
.hasValue() )
1588 if ( aFrom
.hasValue() )
1590 if ( aTo
.hasValue() )
1593 rStrm
.WriteUInt32( nCalcMode
)
1594 .WriteUInt32( nBits
)
1595 .WriteUInt32( nValueType
);
1597 if ( aBy
.hasValue() )
1598 exportAnimProperty( rStrm
, 1, aBy
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1599 if ( aFrom
.hasValue() )
1600 exportAnimProperty( rStrm
, 2, aFrom
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1601 if ( aTo
.hasValue() )
1602 exportAnimProperty( rStrm
, 3, aTo
, TRANSLATE_NUMBER_TO_STRING
| TRANSLATE_MEASURE
);
1604 exportAnimateKeyPoints( rStrm
, xAnimate
);
1605 exportAnimateTarget( rStrm
, xNode
);
1608 void AnimationExporter::exportAnimateTarget( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const sal_uInt32 nForceAttributeNames
, int nAfterEffectType
)
1610 EscherExContainer
aAnimateTarget( rStrm
, DFF_msofbtAnimateTarget
, 0 );
1611 Reference
< XAnimate
> xAnimate( xNode
, UNO_QUERY
);
1612 if ( !xAnimate
.is() )
1616 EscherExAtom
aAnimateTargetSettings( rStrm
, DFF_msofbtAnimateTargetSettings
, 0 );
1617 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1618 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1619 // nAccumulate 0 = none, 1 = always
1620 // nTransformType 0: "property" else "image"
1621 sal_uInt32 nBits
= 0;
1622 sal_uInt32 nAdditive
= 0;
1623 sal_uInt32 nAccumulate
= 0;
1624 sal_uInt32
const nTransformType
= 0;
1625 if ( xAnimate
.is() )
1627 if ( !xAnimate
->getAttributeName().isEmpty() )
1628 nBits
|= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1629 sal_Int16 nAdditiveMode
= xAnimate
->getAdditive();
1630 if ( nAdditiveMode
!= AnimationAdditiveMode::BASE
)
1633 switch( nAdditiveMode
)
1635 case AnimationAdditiveMode::SUM
: nAdditive
= 1; break;
1636 case AnimationAdditiveMode::REPLACE
: nAdditive
= 2; break;
1637 case AnimationAdditiveMode::MULTIPLY
: nAdditive
= 3; break;
1638 case AnimationAdditiveMode::NONE
: nAdditive
= 4; break;
1641 if ( xAnimate
->getAccumulate() )
1647 rStrm
.WriteUInt32( nBits
)
1648 .WriteUInt32( nAdditive
)
1649 .WriteUInt32( nAccumulate
)
1650 .WriteUInt32( nTransformType
);
1652 if ( !xAnimate
->getAttributeName().isEmpty() || nForceAttributeNames
)
1654 EscherExContainer
aAnimateAttributeNames( rStrm
, DFF_msofbtAnimateAttributeNames
, 1 );
1655 OUString
aAttributeName( xAnimate
->getAttributeName() );
1656 if ( nForceAttributeNames
)
1658 if( nForceAttributeNames
== 1 )
1660 aAttributeName
= "r";
1663 sal_Int32 nIndex
= 0;
1666 OUString
aToken( aAttributeName
.getToken( 0, ';', nIndex
) );
1667 exportAnimPropertyString( rStrm
, 0, aToken
, TRANSLATE_ATTRIBUTE
);
1669 while ( nIndex
>= 0 );
1672 if( nAfterEffectType
!= AFTEREFFECT_NONE
)
1674 EscherExContainer
aAnimPropertySet( rStrm
, DFF_msofbtAnimPropertySet
);
1675 exportAnimPropertyuInt32( rStrm
, 6, 1 );
1676 if( nAfterEffectType
== AFTEREFFECT_COLOR
)
1678 exportAnimPropertyuInt32( rStrm
, 4, 0 );
1679 exportAnimPropertyuInt32( rStrm
, 5, 0 );
1682 exportAnimateTargetElement( rStrm
, aTarget
.hasValue() ? aTarget
: xAnimate
->getTarget(), false );
1685 Reference
< XShape
> AnimationExporter::getTargetElementShape( const Any
& rAny
, sal_Int32
& rBegin
, sal_Int32
& rEnd
, bool& rParagraphTarget
)
1687 Reference
< XShape
> xShape
;
1690 rParagraphTarget
= false;
1694 ParagraphTarget aParaTarget
;
1695 if( rAny
>>= aParaTarget
)
1696 xShape
= aParaTarget
.Shape
;
1699 // now calculating the character range for the paragraph
1700 sal_Int16 nParagraph
= aParaTarget
.Paragraph
;
1701 Reference
< XSimpleText
> xText( xShape
, UNO_QUERY
);
1704 rParagraphTarget
= true;
1705 Reference
< XEnumerationAccess
> xTextParagraphEnumerationAccess( xText
, UNO_QUERY
);
1706 if ( xTextParagraphEnumerationAccess
.is() )
1708 Reference
< XEnumeration
> xTextParagraphEnumeration( xTextParagraphEnumerationAccess
->createEnumeration() );
1709 if ( xTextParagraphEnumeration
.is() )
1711 sal_Int16 nCurrentParagraph
;
1712 rBegin
= rEnd
= nCurrentParagraph
= 0;
1713 while ( xTextParagraphEnumeration
->hasMoreElements() )
1715 Reference
< XTextRange
> xTextRange( xTextParagraphEnumeration
->nextElement(), UNO_QUERY
);
1716 if ( xTextRange
.is() )
1718 OUString
aParaText( xTextRange
->getString() );
1719 sal_Int32 nLength
= aParaText
.getLength() + 1;
1721 if ( nCurrentParagraph
== nParagraph
)
1723 nCurrentParagraph
++;
1736 void AnimationExporter::exportAnimateTargetElement( SvStream
& rStrm
, const Any
& rAny
, const bool bCreate2b01Atom
)
1738 sal_uInt32 nRefMode
= 0; // nRefMode == 2 -> Paragraph
1739 sal_Int32 begin
= -1;
1741 bool bParagraphTarget
;
1743 Reference
< XShape
> xShape
= getTargetElementShape(rAny
, begin
, end
, bParagraphTarget
);
1745 if( bParagraphTarget
)
1748 if ( !(xShape
.is() || bCreate2b01Atom
) )
1751 EscherExContainer
aAnimateTargetElement( rStrm
, DFF_msofbtAnimateTargetElement
);
1754 EscherExAtom
aAnimReference( rStrm
, DFF_msofbtAnimReference
);
1756 sal_uInt32
const nRefType
= 1; // TODO: nRefType == 2 -> Sound;
1757 sal_uInt32 nRefId
= mrSolverContainer
.GetShapeId( xShape
);
1759 rStrm
.WriteUInt32( nRefMode
)
1760 .WriteUInt32( nRefType
)
1761 .WriteUInt32( nRefId
)
1762 .WriteInt32( begin
)
1765 if ( bCreate2b01Atom
)
1767 EscherExAtom
a2b01Atom( rStrm
, 0x2b01 );
1768 rStrm
.WriteUInt32( 1 ); // ?
1772 void AnimationExporter::exportAnimateKeyPoints( SvStream
& rStrm
, const Reference
< XAnimate
>& xAnimate
)
1774 Sequence
< double > aKeyTimes( xAnimate
->getKeyTimes() );
1775 Sequence
< Any
> aValues( xAnimate
->getValues() );
1776 OUString
aFormula( xAnimate
->getFormula() );
1777 if ( !aKeyTimes
.hasElements() )
1780 EscherExContainer
aAnimKeyPoints( rStrm
, DFF_msofbtAnimKeyPoints
);
1782 for ( i
= 0; i
< aKeyTimes
.getLength(); i
++ )
1785 EscherExAtom
aAnimKeyTime( rStrm
, DFF_msofbtAnimKeyTime
);
1786 sal_Int32 nKeyTime
= static_cast<sal_Int32
>( aKeyTimes
[ i
] * 1000.0 );
1787 rStrm
.WriteInt32( nKeyTime
);
1790 if ( aValues
[ i
].hasValue() )
1793 if ( aValues
[ i
] >>= aPair
)
1795 aAny
[ 0 ] = convertAnimateValue( aPair
.First
, xAnimate
->getAttributeName() );
1796 aAny
[ 1 ] = convertAnimateValue( aPair
.Second
, xAnimate
->getAttributeName() );
1800 aAny
[ 0 ] = convertAnimateValue( aValues
[ i
], xAnimate
->getAttributeName() );
1802 if ( !i
&& !aFormula
.isEmpty() )
1804 ImplTranslateAttribute( aFormula
, TRANSLATE_MEASURE
);
1805 aAny
[ 1 ] <<= aFormula
;
1807 exportAnimProperty( rStrm
, 0, aAny
[ 0 ], TRANSLATE_NONE
);
1808 exportAnimProperty( rStrm
, 1, aAny
[ 1 ], TRANSLATE_NONE
);
1813 void AnimationExporter::exportAnimValue( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, const bool bExportAlways
)
1817 double fRepeat
= 0.0;
1818 float fRepeatCount
= 0.0;
1819 css::animations::Timing eTiming
;
1820 aAny
= xNode
->getRepeatCount();
1821 if ( aAny
>>= eTiming
)
1823 if ( eTiming
== Timing_INDEFINITE
)
1824 fRepeatCount
= (float(3.40282346638528860e+38));
1826 else if ( aAny
>>= fRepeat
)
1827 fRepeatCount
= static_cast<float>(fRepeat
);
1828 if ( fRepeatCount
!= 0.0 )
1830 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1831 sal_uInt32
const nType
= 0;
1832 rStrm
.WriteUInt32( nType
)
1833 .WriteFloat( fRepeatCount
);
1836 float fAccelerate
= static_cast<float>(xNode
->getAcceleration());
1837 if ( bExportAlways
|| ( fAccelerate
!= 0.0 ) )
1839 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1840 sal_uInt32
const nType
= 3;
1841 rStrm
.WriteUInt32( nType
)
1842 .WriteFloat( fAccelerate
);
1846 float fDecelerate
= static_cast<float>(xNode
->getDecelerate());
1847 if ( bExportAlways
|| ( fDecelerate
!= 0.0 ) )
1849 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1850 sal_uInt32
const nType
= 4;
1851 rStrm
.WriteUInt32( nType
)
1852 .WriteFloat( fDecelerate
);
1856 bool bAutoReverse
= xNode
->getAutoReverse();
1857 if ( bExportAlways
|| bAutoReverse
)
1859 EscherExAtom
aExAtom( rStrm
, DFF_msofbtAnimValue
);
1860 sal_uInt32
const nType
= 5;
1861 sal_uInt32 nVal
= bAutoReverse
? 1 : 0;
1862 rStrm
.WriteUInt32( nType
)
1863 .WriteUInt32( nVal
);
1867 void AnimationExporter::exportTransitionFilter( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1869 Reference
< XTransitionFilter
> xFilter( xNode
, UNO_QUERY
);
1870 if ( !xFilter
.is() )
1873 EscherExContainer
aAnimateFilter( rStrm
, DFF_msofbtAnimateFilter
);
1875 EscherExAtom
aAnimateFilterData( rStrm
, DFF_msofbtAnimateFilterData
);
1876 sal_uInt32
const nBits
= 3; // bit 0 -> use AnimAttributeValue
1877 // bit 1 -> use nTransition
1879 sal_uInt32 nTransition
= xFilter
->getMode() ? 0 : 1;
1880 rStrm
.WriteUInt32( nBits
)
1881 .WriteUInt32( nTransition
);
1883 const char* pFilter
= FindTransitionName( xFilter
->getTransition(), xFilter
->getSubtype(), xFilter
->getDirection() );
1886 const OUString
aStr( OUString::createFromAscii( pFilter
) );
1887 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1889 exportAnimateTarget( rStrm
, xNode
);
1892 void AnimationExporter::exportAnimateMotion( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1894 Reference
< XAnimateMotion
> xMotion( xNode
, UNO_QUERY
);
1895 if ( !xMotion
.is() )
1898 EscherExContainer
aAnimateMotion( rStrm
, DFF_msofbtAnimateMotion
);
1900 { //SJ: Ignored from import filter
1901 EscherExAtom
aAnimateMotionData( rStrm
, DFF_msofbtAnimateMotionData
);
1902 sal_uInt32
const nBits
= 0x98;
1903 sal_uInt32
const nOrigin
= 0x2;
1904 float const fByX
= 100.0; // nBits&1
1905 float const fByY
= 100.0; // nBits&1
1906 float const fFromX
= 0.0; // nBits&2
1907 float const fFromY
= 0.0; // nBits&2
1908 float const fToX
= 100.0; // nBits&4
1909 float const fToY
= 100.0; // nBits&4
1910 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nOrigin
);
1914 if ( xMotion
->getPath() >>= aStr
)
1916 if ( !aStr
.isEmpty() )
1917 exportAnimPropertyString( rStrm
, 1, aStr
, TRANSLATE_NONE
);
1919 exportAnimateTarget( rStrm
, xNode
);
1923 void AnimationExporter::exportAnimateTransform( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
1925 Reference
< XAnimateTransform
> xTransform( xNode
, UNO_QUERY
);
1926 if ( !xTransform
.is() )
1929 if ( xTransform
->getTransformType() == AnimationTransformType::SCALE
)
1931 EscherExContainer
aAnimateScale( rStrm
, DFF_msofbtAnimateScale
);
1933 EscherExAtom
aAnimateScaleData( rStrm
, DFF_msofbtAnimateScaleData
);
1934 sal_uInt32 nBits
= 0;
1935 sal_uInt32
const nZoomContents
= 1;
1943 double fX
= 0.0, fY
= 0.0;
1945 if ( xTransform
->getBy() >>= aPair
)
1947 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1950 fByX
= static_cast<float>( fX
* 100 );
1951 fByY
= static_cast<float>( fY
* 100 );
1954 if ( xTransform
->getFrom() >>= aPair
)
1956 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1959 fFromX
= static_cast<float>( fX
* 100 );
1960 fFromY
= static_cast<float>( fY
* 100 );
1963 if( xTransform
->getTo() >>= aPair
)
1965 if ( ( aPair
.First
>>= fX
) && ( aPair
.Second
>>= fY
) )
1968 fToX
= static_cast<float>( fX
* 100 );
1969 fToY
= static_cast<float>( fY
* 100 );
1973 // TODO: ZoomContents:
1975 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
1977 rStrm
.WriteUInt32( nBits
).WriteFloat( fByX
).WriteFloat( fByY
).WriteFloat( fFromX
).WriteFloat( fFromY
).WriteFloat( fToX
).WriteFloat( fToY
).WriteUInt32( nZoomContents
);
1979 exportAnimateTarget( rStrm
, xNode
);
1981 else if ( xTransform
->getTransformType() == AnimationTransformType::ROTATE
)
1983 EscherExContainer
aAnimateRotation( rStrm
, DFF_msofbtAnimateRotation
);
1985 EscherExAtom
aAnimateRotationData( rStrm
, DFF_msofbtAnimateRotationData
);
1986 sal_uInt32 nBits
= 0;
1987 sal_uInt32
const nU1
= 0;
1993 if ( xTransform
->getBy() >>= fVal
)
1996 fBy
= static_cast<float>(fVal
);
1998 if ( xTransform
->getFrom() >>= fVal
)
2001 fFrom
= static_cast<float>(fVal
);
2003 if ( xTransform
->getTo() >>= fVal
)
2006 fTo
= static_cast<float>(fVal
);
2008 rStrm
.WriteUInt32( nBits
).WriteFloat( fBy
).WriteFloat( fFrom
).WriteFloat( fTo
).WriteUInt32( nU1
);
2010 exportAnimateTarget( rStrm
, xNode
, 1 );
2014 bool AnimationExporter::getColorAny( const Any
& rAny
, const sal_Int16 nColorSpace
, sal_Int32
& rMode
, sal_Int32
& rA
, sal_Int32
& rB
, sal_Int32
& rC
)
2016 bool bIsColor
= true;
2019 if ( nColorSpace
== AnimationColorSpace::HSL
)
2022 sal_Int32 nColor
= 0;
2023 Sequence
< double > aHSL( 3 );
2024 if ( rAny
>>= nColor
) // RGB color
2026 rA
= static_cast<sal_uInt8
>( nColor
>> 16 );
2027 rB
= static_cast<sal_uInt8
>( nColor
>> 8 );
2028 rC
= static_cast<sal_uInt8
>(nColor
);
2030 else if ( rAny
>>= aHSL
) // HSL
2032 rA
= static_cast<sal_Int32
>( aHSL
[ 0 ] * 255.0 / 360.0 );
2033 rB
= static_cast<sal_Int32
>( aHSL
[ 1 ] * 255.0 );
2034 rC
= static_cast<sal_Int32
>( aHSL
[ 2 ] * 255.0 );
2041 void AnimationExporter::exportAnimateColor( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
, int nAfterEffectType
)
2043 Reference
< XAnimateColor
> xColor( xNode
, UNO_QUERY
);
2047 EscherExContainer
aAnimateColor( rStrm
, DFF_msofbtAnimateColor
);
2049 EscherExAtom
aAnimateColorData( rStrm
, DFF_msofbtAnimateColorData
);
2050 sal_uInt32 nBits
= 8;
2052 sal_Int32 nByMode
, nByA
, nByB
, nByC
;
2053 nByMode
= nByA
= nByB
= nByC
= 0;
2055 sal_Int32 nFromMode
, nFromA
, nFromB
, nFromC
;
2056 nFromMode
= nFromA
= nFromB
= nFromC
= 0;
2058 sal_Int32 nToMode
, nToA
, nToB
, nToC
;
2059 nToMode
= nToA
= nToB
= nToC
= 0;
2061 sal_Int16 nColorSpace
= xColor
->getColorInterpolation();
2063 Any
aAny( xColor
->getBy() );
2064 if ( aAny
.hasValue() )
2066 if ( getColorAny( aAny
, nColorSpace
, nByMode
, nByA
, nByB
, nByC
) )
2069 aAny
= xColor
->getFrom();
2070 if ( aAny
.hasValue() )
2072 if ( getColorAny( aAny
, nColorSpace
, nFromMode
, nFromA
, nFromB
, nFromC
) )
2075 aAny
= xColor
->getTo();
2076 if ( aAny
.hasValue() )
2078 if ( getColorAny( aAny
, nColorSpace
, nToMode
, nToA
, nToB
, nToC
) )
2081 rStrm
.WriteUInt32( nBits
)
2082 .WriteInt32( nByMode
).WriteInt32( nByA
).WriteInt32( nByB
).WriteInt32( nByC
)
2083 .WriteInt32( nFromMode
).WriteInt32( nFromA
).WriteInt32( nFromB
).WriteInt32( nFromC
)
2084 .WriteInt32( nToMode
).WriteInt32( nToA
).WriteInt32( nToB
).WriteInt32( nToC
);
2086 exportAnimateTarget( rStrm
, xNode
, 0, nAfterEffectType
);
2089 void AnimationExporter::exportIterate( SvStream
& rStrm
, const Reference
< XAnimationNode
>& xNode
)
2091 Reference
< XIterateContainer
> xIterate( xNode
, UNO_QUERY
);
2092 if ( !xIterate
.is() )
2095 EscherExAtom
aAnimIteration( rStrm
, DFF_msofbtAnimIteration
);
2097 float fInterval
= 10.0;
2098 sal_Int32 nTextUnitEffect
= 0;
2099 sal_Int32
const nU1
= 1;
2100 sal_Int32
const nU2
= 1;
2101 sal_Int32
const nU3
= 0xe;
2103 sal_Int16 nIterateType
= xIterate
->getIterateType();
2104 switch( nIterateType
)
2106 case TextAnimationType::BY_WORD
: nTextUnitEffect
= 1; break;
2107 case TextAnimationType::BY_LETTER
: nTextUnitEffect
= 2; break;
2110 fInterval
= static_cast<float>(xIterate
->getIterateInterval());
2112 // convert interval from absolute to percentage
2113 double fDuration
= 0.0;
2115 Reference
< XEnumerationAccess
> xEnumerationAccess( xNode
, UNO_QUERY
);
2116 if( xEnumerationAccess
.is() )
2118 Reference
< XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
2119 if( xEnumeration
.is() )
2121 while( xEnumeration
->hasMoreElements() )
2123 Reference
< XAnimate
> xChildNode( xEnumeration
->nextElement(), UNO_QUERY
);
2124 if( xChildNode
.is() )
2126 double fChildBegin
= 0.0;
2127 double fChildDuration
= 0.0;
2128 xChildNode
->getBegin() >>= fChildBegin
;
2129 xChildNode
->getDuration() >>= fChildDuration
;
2131 fChildDuration
+= fChildBegin
;
2132 if( fChildDuration
> fDuration
)
2133 fDuration
= fChildDuration
;
2140 fInterval
= static_cast<float>(100.0 * fInterval
/ fDuration
);
2142 rStrm
.WriteFloat( fInterval
).WriteInt32( nTextUnitEffect
).WriteInt32( nU1
).WriteInt32( nU2
).WriteInt32( nU3
);
2143 aTarget
= xIterate
->getTarget();
2148 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */