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