bump product version to 4.1.6.2
[LibreOffice.git] / sd / source / filter / eppt / pptexanimations.cxx
blobd112fb48b7982b76747fe174d1041f15e42ee59c
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.compareToAscii( p->mpAPIName ) == 0 )
102 break;
103 p++;
105 if( p->mpMSName )
107 if ( eTranslateMode & TRANSLATE_VALUE )
109 rString = OUString( (sal_Unicode)'#' );
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.getStr()[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 sal_Bool bTranslated = sal_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 = sal_True;
166 else if ( rPresetSubType == "across" )
168 nPresetSubType = 10;
169 bTranslated = sal_True;
172 break;
173 case 17 :
175 if ( rPresetSubType == "across" )
177 nPresetSubType = 10;
178 bTranslated = sal_True;
181 break;
182 case 18 :
184 if ( rPresetSubType == "right-to-top" )
186 nPresetSubType = 3;
187 bTranslated = sal_True;
189 else if ( rPresetSubType == "right-to-bottom" )
191 nPresetSubType = 6;
192 bTranslated = sal_True;
194 else if ( rPresetSubType == "left-to-top" )
196 nPresetSubType = 9;
197 bTranslated = sal_True;
199 else if ( rPresetSubType == "left-to-bottom" )
201 nPresetSubType = 12;
202 bTranslated = sal_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 = sal_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 sal_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& operator<<(SvStream& rOut, AnimationNode& rNode )
257 rOut << rNode.mnU1;
258 rOut << rNode.mnRestart;
259 rOut << rNode.mnGroupType;
260 rOut << rNode.mnFill;
261 rOut << rNode.mnU3;
262 rOut << rNode.mnU4;
263 rOut << rNode.mnDuration;
264 rOut << rNode.mnNodeType;
266 return rOut;
269 AnimationExporter::AnimationExporter( const EscherSolverContainer& rSolverContainer, ppt::ExSoundCollection& rExSoundCollection ) :
270 mrSolverContainer ( rSolverContainer ),
271 mrExSoundCollection ( rExSoundCollection ),
272 mnCurrentGroup(0)
276 // --------------------------------------------------------------------
278 sal_Int16 AnimationExporter::GetFillMode( const Reference< XAnimationNode >& xNode, const sal_Int16 nFillDefault )
280 sal_Int16 nFill = xNode->getFill();
281 //#i119699 <Animation> The animation effect "Emphasis->FlashBulb" play incorrectly in Aoo saves a .ppt to another .ppt and plays the saved one.
282 //#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.
283 if ((xNode->getType() == AnimationNodeType::ANIMATE)
284 ||(xNode->getType() == AnimationNodeType::SET)
285 ||(xNode->getType() == AnimationNodeType::TRANSITIONFILTER))
287 if ( nFill == AnimationFill::DEFAULT )
288 return nFill;
291 if ( ( nFill == AnimationFill::DEFAULT ) ||
292 ( nFill == AnimationFill::INHERIT ) )
294 if ( nFill != AnimationFill::AUTO )
295 nFill = nFillDefault;
297 if( nFill == AnimationFill::AUTO )
299 nFill = AnimationFill::REMOVE;
300 sal_Bool bIsIndefiniteTiming = sal_True;
301 Any aAny = xNode->getDuration();
302 if( aAny.hasValue() )
304 Timing eTiming;
305 if( aAny >>= eTiming )
306 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
308 if ( bIsIndefiniteTiming )
310 aAny = xNode->getEnd();
311 if( aAny.hasValue() )
313 Timing eTiming;
314 if( aAny >>= eTiming )
315 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
317 if ( bIsIndefiniteTiming )
319 if ( !xNode->getRepeatCount().hasValue() )
321 aAny = xNode->getRepeatDuration();
322 if( aAny.hasValue() )
324 Timing eTiming;
325 if( aAny >>= eTiming )
326 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
328 if ( bIsIndefiniteTiming )
329 nFill = AnimationFill::FREEZE;
334 return nFill;
337 void AnimationExporter::doexport( const Reference< XDrawPage >& xPage, SvStream& rStrm )
339 Reference< XAnimationNodeSupplier > xNodeSupplier( xPage, UNO_QUERY );
340 if( xNodeSupplier.is() )
342 const Reference< XAnimationNode > xRootNode( xNodeSupplier->getAnimationNode() );
343 if( xRootNode.is() )
345 processAfterEffectNodes( xRootNode );
346 exportNode( rStrm, xRootNode, NULL, DFF_msofbtAnimGroup, 1, 0, sal_False, AnimationFill::AUTO );
351 void AnimationExporter::processAfterEffectNodes( const Reference< XAnimationNode >& xRootNode )
355 Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
356 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
357 while( xEnumeration->hasMoreElements() )
359 Reference< XAnimationNode > xNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
361 Reference< XEnumerationAccess > xEnumerationAccess2( xNode, UNO_QUERY );
362 if ( xEnumerationAccess2.is() )
364 Reference< XEnumeration > xEnumeration2( xEnumerationAccess2->createEnumeration(), UNO_QUERY_THROW );
365 while( xEnumeration2->hasMoreElements() )
367 Reference< XAnimationNode > xChildNode( xEnumeration2->nextElement(), UNO_QUERY_THROW );
369 Reference< XEnumerationAccess > xEnumerationAccess3( xChildNode, UNO_QUERY_THROW );
370 Reference< XEnumeration > xEnumeration3( xEnumerationAccess3->createEnumeration(), UNO_QUERY_THROW );
371 while( xEnumeration3->hasMoreElements() )
373 Reference< XAnimationNode > xChildNode2( xEnumeration3->nextElement(), UNO_QUERY_THROW );
375 Reference< XEnumerationAccess > xEnumerationAccess4( xChildNode2, UNO_QUERY_THROW );
376 Reference< XEnumeration > xEnumeration4( xEnumerationAccess4->createEnumeration(), UNO_QUERY_THROW );
377 while( xEnumeration4->hasMoreElements() )
379 Reference< XAnimationNode > xChildNode3( xEnumeration4->nextElement(), UNO_QUERY_THROW );
381 switch( xChildNode3->getType() )
383 // found an after effect
384 case AnimationNodeType::SET:
385 case AnimationNodeType::ANIMATECOLOR:
387 Reference< XAnimationNode > xMaster;
389 Sequence< NamedValue > aUserData( xChildNode3->getUserData() );
390 sal_Int32 nLength = aUserData.getLength();
391 const NamedValue* p = aUserData.getConstArray();
393 while( nLength-- )
395 if ( p->Name == "master-element" )
397 p->Value >>= xMaster;
398 break;
400 p++;
403 AfterEffectNodePtr pAfterEffectNode( new AfterEffectNode( xChildNode3, xMaster ) );
404 maAfterEffectNodes.push_back( pAfterEffectNode );
406 break;
414 catch( Exception& )
416 OSL_FAIL( "(@CL)AnimationExporter::processAfterEffectNodes(), exception cought!" );
420 bool AnimationExporter::isAfterEffectNode( const Reference< XAnimationNode >& xNode ) const
422 const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
423 for (std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
424 aIter != aEnd ; ++aIter)
426 if( (*aIter)->mxNode == xNode )
427 return true;
429 return false;
432 bool AnimationExporter::hasAfterEffectNode( const Reference< XAnimationNode >& xNode, Reference< XAnimationNode >& xAfterEffectNode ) const
434 const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
435 for (std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
436 aIter != aEnd ; ++aIter)
438 if( (*aIter)->mxMaster == xNode )
440 xAfterEffectNode = (*aIter)->mxNode;
441 return true;
445 return false;
448 // check if this group only contain empty groups. this may happen when
449 // after effect nodes are not exported at theire original position
450 bool AnimationExporter::isEmptyNode( const Reference< XAnimationNode >& xNode ) const
452 if( xNode.is() ) switch( xNode->getType() )
454 case AnimationNodeType::PAR :
455 case AnimationNodeType::SEQ :
456 case AnimationNodeType::ITERATE :
458 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
459 if( xEnumerationAccess.is() )
461 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
462 if( xEnumeration.is() )
464 while( xEnumeration->hasMoreElements() )
466 Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
467 if( xChildNode.is() && !isEmptyNode( xChildNode ) )
468 return false;
473 break;
475 case AnimationNodeType::SET :
476 case AnimationNodeType::ANIMATECOLOR :
477 return isAfterEffectNode( xNode );
478 default:
479 return false;
482 return true;
485 void AnimationExporter::exportNode( SvStream& rStrm, Reference< XAnimationNode > xNode, const Reference< XAnimationNode >* pParent, const sal_uInt16 nContainerRecType,
486 const sal_uInt16 nInstance, const sal_Int32 nGroupLevel, const sal_Bool bTakeBackInteractiveSequenceTiming, const sal_Int16 nFDef )
488 if( (nGroupLevel == 4) && isEmptyNode( xNode ) )
489 return;
491 if ( ( nContainerRecType == DFF_msofbtAnimGroup ) && ( nGroupLevel == 2 ) && isEmptyNode( xNode ) )
492 return;
494 if( nContainerRecType == DFF_msofbtAnimGroup )
495 mnCurrentGroup++;
497 sal_Bool bTakeBackInteractiveSequenceTimingForChild = sal_False;
498 sal_Int16 nFillDefault = GetFillMode( xNode, nFDef );
500 bool bSkipChildren = false;
502 Reference< XAnimationNode > xAudioNode;
503 static sal_uInt32 nAudioGroup;
506 EscherExContainer aContainer( rStrm, nContainerRecType, nInstance );
507 switch( xNode->getType() )
509 case AnimationNodeType::CUSTOM :
511 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
512 exportAnimPropertySet( rStrm, xNode );
513 exportAnimEvent( rStrm, xNode, 0 );
514 exportAnimValue( rStrm, xNode, sal_False );
516 break;
518 case AnimationNodeType::PAR :
520 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
521 exportAnimPropertySet( rStrm, xNode );
522 sal_Int32 nFlags = nGroupLevel == 2 ? 0x10 : 0;
523 if ( bTakeBackInteractiveSequenceTiming )
524 nFlags |= 0x40;
525 exportAnimEvent( rStrm, xNode, nFlags );
526 exportAnimValue( rStrm, xNode, nGroupLevel == 4 );
528 break;
530 case AnimationNodeType::SEQ :
532 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
533 sal_Int16 nNodeType = exportAnimPropertySet( rStrm, xNode );
534 sal_Int32 nFlags = 12;
535 if ( ( nGroupLevel == 1 ) && ( nNodeType == ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE ) )
537 nFlags |= 0x20;
538 bTakeBackInteractiveSequenceTimingForChild = sal_True;
540 exportAnimAction( rStrm, xNode );
541 exportAnimEvent( rStrm, xNode, nFlags );
542 exportAnimValue( rStrm, xNode, sal_False );
544 break;
546 case AnimationNodeType::ITERATE :
549 EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
550 AnimationNode aAnim;
551 memset( &aAnim, 0, sizeof( aAnim ) );
552 aAnim.mnGroupType = mso_Anim_GroupType_PAR;
553 aAnim.mnNodeType = 1;
554 // attribute Restart
555 switch( xNode->getRestart() )
557 default:
558 case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
559 case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
560 case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
561 case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
563 // attribute Fill
564 switch( xNode->getFill() )
566 default:
567 case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
568 case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
569 case AnimationFill::FREEZE : aAnim.mnFill = 2; break;
570 case AnimationFill::HOLD : aAnim.mnFill = 3; break;
571 case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
573 rStrm << aAnim;
575 exportIterate( rStrm, xNode );
576 exportAnimPropertySet( rStrm, xNode );
577 exportAnimEvent( rStrm, xNode, 0 );
578 exportAnimValue( rStrm, xNode, sal_False );
580 break;
582 case AnimationNodeType::ANIMATE :
584 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
585 exportAnimPropertySet( rStrm, xNode );
586 exportAnimEvent( rStrm, xNode, 0 );
587 exportAnimValue( rStrm, xNode, sal_False );
588 exportAnimate( rStrm, xNode );
590 break;
592 case AnimationNodeType::SET :
594 bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
595 if( (nGroupLevel != 4) || !bIsAfterEffectNode )
597 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
598 exportAnimPropertySet( rStrm, xNode );
599 exportAnimateSet( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_SET : AFTEREFFECT_NONE );
600 exportAnimEvent( rStrm, xNode, 0 );
601 exportAnimValue( rStrm, xNode, sal_False );
603 else
605 bSkipChildren = true;
608 break;
610 case AnimationNodeType::ANIMATEMOTION :
612 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
613 exportAnimPropertySet( rStrm, xNode );
614 exportAnimateMotion( rStrm, xNode );
615 exportAnimEvent( rStrm, xNode, 0 );
616 exportAnimValue( rStrm, xNode, sal_False );
618 break;
620 case AnimationNodeType::ANIMATECOLOR :
622 bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
623 if( (nGroupLevel != 4) || !bIsAfterEffectNode )
625 if( bIsAfterEffectNode )
626 xNode = createAfterEffectNodeClone( xNode );
628 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
629 exportAnimPropertySet( rStrm, xNode );
630 exportAnimateColor( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_COLOR : AFTEREFFECT_NONE );
631 exportAnimEvent( rStrm, xNode, 0 );
632 exportAnimValue( rStrm, xNode, sal_False );
634 else
636 bSkipChildren = true;
639 break;
641 case AnimationNodeType::ANIMATETRANSFORM :
643 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
644 exportAnimPropertySet( rStrm, xNode );
645 exportAnimateTransform( rStrm, xNode );
646 exportAnimEvent( rStrm, xNode, 0 );
647 exportAnimValue( rStrm, xNode, sal_False );
649 break;
651 case AnimationNodeType::TRANSITIONFILTER :
653 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
654 exportAnimPropertySet( rStrm, xNode );
655 exportAnimEvent( rStrm, xNode, 0 );
656 exportAnimValue( rStrm, xNode, sal_False );
657 exportTransitionFilter( rStrm, xNode );
659 break;
661 case AnimationNodeType::AUDIO : // #i58428#
663 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
664 exportAnimPropertySet( rStrm, xNode );
666 Reference< XAudio > xAudio( xNode, UNO_QUERY );
667 if( xAudio.is() )
669 Any aAny( xAudio->getSource() );
670 OUString aURL;
672 if ( ( aAny >>= aURL) && !aURL.isEmpty() )
674 sal_Int32 nU1 = 2;
675 sal_Int32 nTrigger = 3;
676 sal_Int32 nU3 = nAudioGroup;
677 sal_Int32 nBegin = 0;
679 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 1 );
681 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
682 rStrm << nU1 << nTrigger << nU3 << nBegin;
685 nU1 = 1;
686 nTrigger = 0xb;
687 nU3 = 0;
689 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 2 );
691 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
692 rStrm << nU1 << nTrigger << nU3 << nBegin;
695 EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
697 sal_uInt32 nRefMode = 3;
698 sal_uInt32 nRefType = 2;
699 sal_uInt32 nRefId = mrExSoundCollection.GetId( aURL );
700 sal_Int32 begin = -1;
701 sal_Int32 end = -1;
703 EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
704 rStrm << nRefMode << nRefType << nRefId << begin << end;
708 exportAnimValue( rStrm, xNode, sal_False );
710 break;
712 if( !bSkipChildren )
714 // export after effect node if one exists for this node
715 Reference< XAnimationNode > xAfterEffectNode;
716 if( hasAfterEffectNode( xNode, xAfterEffectNode ) )
718 exportNode( rStrm, xAfterEffectNode, &xNode, DFF_msofbtAnimSubGoup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
721 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
722 if( xEnumerationAccess.is() )
724 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
725 if( xEnumeration.is() )
727 while( xEnumeration->hasMoreElements() )
729 Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
730 if( xChildNode.is() )
732 if ( xChildNode->getType() == AnimationNodeType::AUDIO )
734 xAudioNode = xChildNode;
735 nAudioGroup = mnCurrentGroup;
737 else
738 exportNode( rStrm, xChildNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
745 if ( xAudioNode.is() )
746 exportNode( rStrm, xAudioNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
748 if( xNode->getType() == AnimationNodeType::ITERATE )
749 aTarget = Any();
752 Reference< XAnimationNode > AnimationExporter::createAfterEffectNodeClone( const Reference< XAnimationNode >& xNode ) const
756 Reference< ::com::sun::star::util::XCloneable > xClonable( xNode, UNO_QUERY_THROW );
757 Reference< XAnimationNode > xCloneNode( xClonable->createClone(), UNO_QUERY_THROW );
759 Any aEmpty;
760 xCloneNode->setBegin( aEmpty );
762 return xCloneNode;
764 catch( Exception& )
766 OSL_FAIL("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
768 return xNode;
771 sal_Bool AnimationExporter::GetNodeType( const Reference< XAnimationNode >& xNode, sal_Int16& nType )
773 // trying to get the nodetype
774 Sequence< NamedValue > aUserData = xNode->getUserData();
775 if ( aUserData.getLength() )
777 const NamedValue* p = aUserData.getConstArray();
778 sal_Int32 nLength = aUserData.getLength();
779 while( nLength-- )
781 if ( p->Name == "node-type" )
783 if ( p->Value >>= nType )
784 return sal_True;
789 return sal_False;
792 void AnimationExporter::exportAnimNode( SvStream& rStrm, const Reference< XAnimationNode >& xNode,
793 const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >*, const sal_Int32, const sal_Int16 nFillDefault )
795 EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
796 AnimationNode aAnim;
797 memset( &aAnim, 0, sizeof( aAnim ) );
799 // attribute Restart
800 switch( xNode->getRestart() )
802 default:
803 case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
804 case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
805 case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
806 case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
809 switch( nFillDefault )
811 default:
812 case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
813 case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
814 case AnimationFill::FREEZE :
815 case AnimationFill::HOLD : aAnim.mnFill = 3; break;
816 case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
818 // attribute Duration
819 double fDuration = 0.0;
820 com::sun::star::animations::Timing eTiming;
821 if ( xNode->getDuration() >>= eTiming )
823 if ( eTiming == Timing_INDEFINITE )
824 aAnim.mnDuration = -1;
826 else if ( xNode->getDuration() >>= fDuration )
828 aAnim.mnDuration = (sal_Int32)( fDuration * 1000.0 );
830 else
831 aAnim.mnDuration = -1;
833 // NodeType, NodeGroup
834 aAnim.mnNodeType = 1;
835 aAnim.mnGroupType = mso_Anim_GroupType_SEQ;
836 switch( xNode->getType() )
838 case AnimationNodeType::PAR : // PASSTROUGH!!! (as it was intended)
839 aAnim.mnGroupType = mso_Anim_GroupType_PAR;
840 case AnimationNodeType::SEQ :
842 sal_Int16 nType = 0;
843 if( GetNodeType( xNode, nType ) )
844 switch( nType )
846 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : aAnim.mnNodeType = 0x12; break;
847 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : aAnim.mnNodeType = 0x18; break;
850 break;
852 case AnimationNodeType::ANIMATE :
853 case AnimationNodeType::SET :
855 case AnimationNodeType::CUSTOM :
856 case AnimationNodeType::ITERATE :
857 case AnimationNodeType::ANIMATEMOTION :
858 case AnimationNodeType::ANIMATECOLOR :
859 case AnimationNodeType::ANIMATETRANSFORM :
861 aAnim.mnGroupType = mso_Anim_GroupType_NODE;
862 aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
864 break;
866 case AnimationNodeType::AUDIO :
868 aAnim.mnGroupType = mso_Anim_GroupType_MEDIA;
869 aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
871 break;
873 case AnimationNodeType::TRANSITIONFILTER :
875 aAnim.mnGroupType = mso_Anim_GroupType_NODE;
876 aAnim.mnNodeType = mso_Anim_Behaviour_FILTER;
878 break;
881 rStrm << aAnim;
884 void AnimationExporter::GetUserData( const Sequence< NamedValue >& rUserData, const Any ** pAny, sal_Size nLen )
886 // storing user data into pAny, to allow direct access later
887 memset( pAny, 0, nLen );
888 if ( rUserData.getLength() )
890 const NamedValue* p = rUserData.getConstArray();
891 sal_Int32 nLength = rUserData.getLength();
892 while( nLength-- )
894 if ( p->Name == "node-type" )
896 pAny[ DFF_ANIM_NODE_TYPE ] = &(p->Value);
898 else if ( p->Name == "preset-class" )
900 pAny[ DFF_ANIM_PRESET_CLASS ] = &(p->Value);
902 else if ( p->Name == "preset-id" )
904 pAny[ DFF_ANIM_PRESET_ID ] = &(p->Value);
906 else if ( p->Name == "preset-sub-type" )
908 pAny[ DFF_ANIM_PRESET_SUB_TYPE ] = &(p->Value);
910 else if ( p->Name == "master-element" )
912 pAny[ DFF_ANIM_AFTEREFFECT ] = &(p->Value);;
914 p++;
919 sal_uInt32 AnimationExporter::GetPresetID( const OUString& rPreset, sal_uInt32 nAPIPresetClass, sal_Bool& bPresetId )
921 sal_uInt32 nPresetId = 0;
922 bPresetId = sal_False;
924 if ( rPreset.match( OUString( "ppt_" ), 0 ) )
926 sal_Int32 nLast = rPreset.lastIndexOf( '_' );
927 if ( ( nLast != -1 ) && ( ( nLast + 1 ) < rPreset.getLength() ) )
929 OUString aNumber( rPreset.copy( nLast + 1 ) );
930 nPresetId = aNumber.toInt32();
931 bPresetId = sal_True;
934 else
936 const preset_maping* p = gPresetMaping;
937 while( p->mpStrPresetId && ((p->mnPresetClass != (sal_Int32)nAPIPresetClass) || !rPreset.equalsAscii( p->mpStrPresetId )) )
938 p++;
940 if( p->mpStrPresetId )
942 nPresetId = p->mnPresetId;
943 bPresetId = sal_True;
947 return nPresetId;
950 sal_Int16 AnimationExporter::exportAnimPropertySet( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
952 sal_Int16 nNodeType = ::com::sun::star::presentation::EffectNodeType::DEFAULT;
954 EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
956 Reference< XAnimationNode > xMaster;
958 Any aMasterRel, aOverride, aRunTimeContext;
960 // storing user data into pAny, to allow direct access later
961 const Sequence< NamedValue > aUserData = xNode->getUserData();
962 const ::com::sun::star::uno::Any* pAny[ DFF_ANIM_PROPERTY_ID_COUNT ];
963 GetUserData( aUserData, pAny, sizeof( pAny ) );
965 if( pAny[ DFF_ANIM_AFTEREFFECT ] )
966 ( *pAny[ DFF_ANIM_AFTEREFFECT ] ) >>= xMaster;
968 // calculate master-rel
969 if( xMaster.is() )
971 sal_Int32 nMasterRel = 2;
972 Reference< XChild > xNodeChild( xNode, UNO_QUERY );
973 Reference< XChild > xMasterChild( xMaster, UNO_QUERY );
974 if( xNodeChild.is() && xMasterChild.is() && (xNodeChild->getParent() == xMasterChild->getParent() ) )
975 nMasterRel = 0;
977 aMasterRel <<= nMasterRel;
979 pAny[ DFF_ANIM_MASTERREL ] = &aMasterRel;
981 aOverride <<= (sal_Int32)1;
982 pAny[ DFF_ANIM_OVERRIDE ] = &aOverride;
984 aRunTimeContext <<= (sal_Int32)1;
985 pAny[ DFF_ANIM_RUNTIMECONTEXT ] = &aRunTimeContext;
988 // the order is important
989 if ( pAny[ DFF_ANIM_NODE_TYPE ] )
991 if ( *pAny[ DFF_ANIM_NODE_TYPE ] >>= nNodeType )
993 sal_uInt32 nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK;
994 switch( nNodeType )
996 case ::com::sun::star::presentation::EffectNodeType::ON_CLICK : nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK; break;
997 case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_WITH_PREVIOUS; break;
998 case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS; break;
999 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : nPPTNodeType = DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE; break;
1000 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : nPPTNodeType = DFF_ANIM_NODE_TYPE_TIMING_ROOT; break;
1001 case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE: nPPTNodeType = DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ; break;
1003 exportAnimPropertyuInt32( rStrm, DFF_ANIM_NODE_TYPE, nPPTNodeType, TRANSLATE_NONE );
1006 sal_uInt32 nPresetId = 0;
1007 sal_uInt32 nPresetSubType = 0;
1008 sal_uInt32 nAPIPresetClass = EffectPresetClass::CUSTOM;
1009 sal_uInt32 nPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
1010 sal_Bool bPresetClass, bPresetId, bPresetSubType;
1011 bPresetId = bPresetClass = bPresetSubType = sal_False;
1013 if ( pAny[ DFF_ANIM_PRESET_CLASS ] )
1015 if ( *pAny[ DFF_ANIM_PRESET_CLASS ] >>= nAPIPresetClass )
1017 sal_uInt8 nPPTPresetClass;
1018 switch( nAPIPresetClass )
1020 case EffectPresetClass::ENTRANCE : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_ENTRANCE; break;
1021 case EffectPresetClass::EXIT : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EXIT; break;
1022 case EffectPresetClass::EMPHASIS : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EMPHASIS; break;
1023 case EffectPresetClass::MOTIONPATH : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MOTIONPATH; break;
1024 case EffectPresetClass::OLEACTION : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_OLE_ACTION; break;
1025 case EffectPresetClass::MEDIACALL : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MEDIACALL; break;
1026 default :
1027 nPPTPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
1029 nPresetClass = nPPTPresetClass;
1030 bPresetClass = sal_True;
1033 if ( pAny[ DFF_ANIM_PRESET_ID ] )
1035 OUString sPreset;
1036 if ( *pAny[ DFF_ANIM_PRESET_ID ] >>= sPreset )
1037 nPresetId = GetPresetID( sPreset, nAPIPresetClass, bPresetId );
1040 if ( pAny[ DFF_ANIM_PRESET_SUB_TYPE ] )
1042 OUString sPresetSubType;
1043 if ( *pAny[ DFF_ANIM_PRESET_SUB_TYPE ] >>= sPresetSubType )
1045 nPresetSubType = TranslatePresetSubType( nPresetClass, nPresetId, sPresetSubType );
1046 bPresetSubType = sal_True;
1049 if ( bPresetId )
1050 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_ID, nPresetId, TRANSLATE_NONE );
1051 if ( bPresetSubType )
1052 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_SUB_TYPE, nPresetSubType, TRANSLATE_NONE );
1053 if ( bPresetClass )
1054 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_CLASS, nPresetClass, TRANSLATE_NONE );
1056 if ( pAny[ DFF_ANIM_ID ] )
1058 // TODO DFF_ANIM_ID
1061 if ( pAny[ DFF_ANIM_AFTEREFFECT ] )
1063 sal_Bool bAfterEffect = sal_False;
1064 if ( *pAny[ DFF_ANIM_AFTEREFFECT ] >>= bAfterEffect )
1065 exportAnimPropertyByte( rStrm, DFF_ANIM_AFTEREFFECT, bAfterEffect, TRANSLATE_NONE );
1068 if ( pAny[ DFF_ANIM_RUNTIMECONTEXT ] )
1070 sal_Int32 nRunTimeContext = 0;
1071 if ( *pAny[ DFF_ANIM_RUNTIMECONTEXT ] >>= nRunTimeContext )
1072 exportAnimPropertyuInt32( rStrm, DFF_ANIM_RUNTIMECONTEXT, nRunTimeContext, TRANSLATE_NONE );
1074 if ( pAny[ DFF_ANIM_PATH_EDIT_MODE ] )
1076 // TODO DFF_ANIM_ID
1079 if( !xMaster.is() )
1081 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
1082 if( xColor.is() )
1085 sal_Bool bDirection = !xColor->getDirection();
1086 exportAnimPropertyuInt32( rStrm, DFF_ANIM_DIRECTION, bDirection, TRANSLATE_NONE );
1090 if ( pAny[ DFF_ANIM_OVERRIDE ] )
1092 sal_Int32 nOverride = 0;
1093 if ( *pAny[ DFF_ANIM_OVERRIDE ] >>= nOverride )
1094 exportAnimPropertyuInt32( rStrm, DFF_ANIM_OVERRIDE, nOverride, TRANSLATE_NONE );
1097 if ( pAny[ DFF_ANIM_MASTERREL ] )
1099 sal_Int32 nMasterRel = 0;
1100 if ( *pAny[ DFF_ANIM_MASTERREL ] >>= nMasterRel )
1101 exportAnimPropertyuInt32( rStrm, DFF_ANIM_MASTERREL, nMasterRel, TRANSLATE_NONE );
1104 /* todo
1105 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1106 if( xAudio.is() )
1108 sal_Int16 nEndAfterSlide = 0;
1109 nEndAfterSlide = xAudio->getEndAfterSlide();
1110 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1113 Reference< XAnimate > xAnim( xNode, UNO_QUERY );
1114 if( xAnim.is() )
1116 // TODO: DFF_ANIM_TIMEFILTER
1118 if ( pAny[ DFF_ANIM_EVENT_FILTER ] )
1120 // TODO DFF_ANIM_EVENT_FILTER
1122 if ( pAny[ DFF_ANIM_VOLUME ] )
1124 // TODO DFF_ANIM_VOLUME
1126 return nNodeType;
1129 sal_Bool AnimationExporter::exportAnimProperty( SvStream& rStrm, const sal_uInt16 nPropertyId, const ::com::sun::star::uno::Any& rAny, const TranslateMode eTranslateMode )
1131 sal_Bool bRet = sal_False;
1132 if ( rAny.hasValue() )
1134 switch( rAny.getValueType().getTypeClass() )
1136 case ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT :
1137 case ::com::sun::star::uno::TypeClass_SHORT :
1138 case ::com::sun::star::uno::TypeClass_UNSIGNED_LONG :
1139 case ::com::sun::star::uno::TypeClass_LONG :
1141 sal_Int32 nVal = 0;
1142 if ( rAny >>= nVal )
1144 exportAnimPropertyuInt32( rStrm, nPropertyId, nVal, eTranslateMode );
1145 bRet = sal_True;
1148 break;
1150 case ::com::sun::star::uno::TypeClass_DOUBLE :
1152 double fVal = 0.0;
1153 if ( rAny >>= fVal )
1155 exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
1156 bRet = sal_True;
1159 break;
1160 case ::com::sun::star::uno::TypeClass_FLOAT :
1162 float fVal = 0.0;
1163 if ( rAny >>= fVal )
1165 if ( eTranslateMode & TRANSLATE_NUMBER_TO_STRING )
1167 Any aAny;
1168 OUString aNumber( OUString::valueOf( fVal ) );
1169 aAny <<= aNumber;
1170 exportAnimPropertyString( rStrm, nPropertyId, aNumber, eTranslateMode );
1172 else
1174 exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
1175 bRet = sal_True;
1179 break;
1180 case ::com::sun::star::uno::TypeClass_STRING :
1182 OUString aStr;
1183 if ( rAny >>= aStr )
1185 exportAnimPropertyString( rStrm, nPropertyId, aStr, eTranslateMode );
1186 bRet = sal_True;
1189 break;
1190 default:
1191 break;
1194 return bRet;
1196 void AnimationExporter::exportAnimPropertyString( SvStream& rStrm, const sal_uInt16 nPropertyId, const OUString& rVal, const TranslateMode eTranslateMode )
1198 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1199 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_UNISTRING;
1200 rStrm << nType;
1201 OUString aStr( rVal );
1202 if ( eTranslateMode != TRANSLATE_NONE )
1203 ImplTranslateAttribute( aStr, eTranslateMode );
1204 writeZString( rStrm, aStr );
1207 void AnimationExporter::exportAnimPropertyFloat( SvStream& rStrm, const sal_uInt16 nPropertyId, const double& rVal, const TranslateMode )
1209 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1210 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_FLOAT;
1211 float fFloat = (float)rVal;
1212 rStrm << nType
1213 << fFloat;
1216 void AnimationExporter::exportAnimPropertyuInt32( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt32 nVal, const TranslateMode )
1218 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1219 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_INT32 ;
1220 rStrm << nType
1221 << nVal;
1224 void AnimationExporter::exportAnimPropertyByte( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt8 nVal, const TranslateMode )
1226 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1227 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_BYTE;
1228 rStrm << nType
1229 << nVal;
1232 void AnimationExporter::writeZString( SvStream& rStrm, const OUString& rVal )
1234 sal_Int32 i;
1235 for ( i = 0; i < rVal.getLength(); i++ )
1236 rStrm << rVal[ i ];
1237 rStrm << (sal_Unicode)0;
1240 void AnimationExporter::exportAnimAction( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1242 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAction );
1244 sal_Int32 nConcurrent = 1;
1245 sal_Int32 nNextAction = 1;
1246 sal_Int32 nEndSync = 0;
1247 sal_Int32 nU4 = 0;
1248 sal_Int32 nU5 = 3;
1250 sal_Int16 nAnimationEndSync = 0;
1251 if ( xNode->getEndSync() >>= nAnimationEndSync )
1253 if ( nAnimationEndSync == AnimationEndSync::ALL )
1254 nEndSync = 1;
1256 rStrm << nConcurrent
1257 << nNextAction
1258 << nEndSync
1259 << nU4
1260 << nU5;
1264 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1265 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1266 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
1267 void AnimationExporter::exportAnimEvent( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Int32 nFlags )
1269 sal_uInt16 i;
1270 for ( i = 0; i < 4; i++ )
1272 sal_Int32 nU1 = 0;
1273 sal_Int32 nTrigger = 0;
1274 sal_Int32 nU3 = 0;
1275 sal_Int32 nBegin = 0;
1277 sal_Bool bCreateEvent = sal_False;
1278 Any aSource;
1280 switch( i )
1282 case 0 :
1283 case 1 :
1285 Any aAny;
1286 Event aEvent;
1287 com::sun::star::animations::Timing eTiming;
1288 if ( i == 0 )
1290 if ( nFlags & 0x20 )
1292 // taking the first child
1293 Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
1294 Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
1295 if ( xE.is() && xE->hasMoreElements() )
1298 Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
1299 aAny = xClickNode->getBegin();
1303 else if ( nFlags & 0x40 )
1305 // begin has to be replaced with void, so don't do anything
1307 else
1309 aAny = xNode->getBegin();
1310 if ( nFlags & 0x10 ) // replace ON_NEXT with IDEFINITE
1312 if ( ( aAny >>= aEvent ) && ( aEvent.Trigger == EventTrigger::ON_NEXT ) )
1314 eTiming = Timing_INDEFINITE;
1315 aAny <<= eTiming;
1320 else
1321 aAny = xNode->getEnd();
1323 double fTiming = 0.0;
1324 if ( aAny >>= aEvent )
1326 bCreateEvent = sal_True;
1327 switch( aEvent.Trigger )
1329 case EventTrigger::NONE : nTrigger = 0; break;
1330 case EventTrigger::ON_BEGIN : nTrigger = 1; break;
1331 case EventTrigger::ON_END : nTrigger = 2; break;
1332 case EventTrigger::BEGIN_EVENT : nTrigger = 3; break;
1333 case EventTrigger::END_EVENT : nTrigger = 4; nU1 = 2; nU3 = mnCurrentGroup; break;
1334 case EventTrigger::ON_CLICK : nTrigger = 5; break;
1335 case EventTrigger::ON_DBL_CLICK : nTrigger = 6; break;
1336 case EventTrigger::ON_MOUSE_ENTER : nTrigger = 7; break;
1337 case EventTrigger::ON_MOUSE_LEAVE : nTrigger = 8; break;
1338 case EventTrigger::ON_NEXT : nTrigger = 9; break;
1339 case EventTrigger::ON_PREV : nTrigger = 10; break;
1340 case EventTrigger::ON_STOP_AUDIO : nTrigger = 11; break;
1342 if ( aEvent.Offset.hasValue() )
1344 if ( aEvent.Offset >>= eTiming )
1346 if ( eTiming == Timing_INDEFINITE )
1347 nBegin = -1;
1349 else if ( aEvent.Offset >>= fTiming )
1350 nBegin = (sal_Int32)( fTiming * 1000.0 );
1352 aSource = aEvent.Source;
1354 else if ( aAny >>= eTiming )
1356 bCreateEvent = sal_True;
1357 if ( eTiming == Timing_INDEFINITE )
1358 nBegin = -1;
1360 else if ( aAny >>= fTiming )
1362 bCreateEvent = sal_True;
1363 nBegin = (sal_Int32)( fTiming * 1000.0 );
1366 break;
1368 case 2 :
1370 if ( nFlags & ( 1 << i ) )
1372 bCreateEvent = sal_True;
1373 nU1 = 1;
1374 nTrigger = 9;
1377 break;
1378 case 3 :
1380 if ( nFlags & ( 1 << i ) )
1382 bCreateEvent = sal_True;
1383 nU1 = 1;
1384 nTrigger = 10;
1387 break;
1389 if ( bCreateEvent )
1391 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, i + 1 );
1393 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
1394 rStrm << nU1
1395 << nTrigger
1396 << nU3
1397 << nBegin;
1399 exportAnimateTargetElement( rStrm, aSource, ( nFlags & ( 1 << i ) ) != 0 );
1404 Any AnimationExporter::convertAnimateValue( const Any& rSourceValue, const OUString& rAttributeName )
1406 OUString aDest;
1407 if ( rAttributeName == "X"
1408 || rAttributeName == "Y"
1409 || rAttributeName == "Width"
1410 || rAttributeName == "Height"
1413 OUString aStr;
1414 if ( rSourceValue >>= aStr )
1416 ImplTranslateAttribute( aStr, TRANSLATE_MEASURE );
1417 aDest += aStr;
1420 else if ( rAttributeName == "Rotate" // "r" or "style.rotation" ?
1421 || rAttributeName == "SkewX"
1422 || rAttributeName == "Opacity"
1423 || rAttributeName == "CharHeight"
1426 double fNumber = 0.0;
1427 if ( rSourceValue >>= fNumber )
1428 aDest += OUString::valueOf( fNumber );
1430 else if ( rAttributeName == "Color"
1431 || rAttributeName == "FillColor" // "Fillcolor" or "FillColor" ?
1432 || rAttributeName == "LineColor"
1433 || rAttributeName == "CharColor"
1436 sal_Int32 nColor = 0;
1437 Sequence< double > aHSL( 3 );
1438 OUString aP( "," );
1439 if ( rSourceValue >>= aHSL )
1441 aDest += "hsl(";
1442 aDest += OUString::valueOf( (sal_Int32)( aHSL[ 0 ] / ( 360.0 / 255 ) ) );
1443 aDest += aP;
1444 aDest += OUString::valueOf( (sal_Int32)( aHSL[ 1 ] * 255.0 ) );
1445 aDest += aP;
1446 aDest += OUString::valueOf( (sal_Int32)( aHSL[ 2 ] * 255.0 ) );
1447 aDest += ")";
1449 else if ( rSourceValue >>= nColor )
1451 aDest += "rgb(";
1452 aDest += OUString::valueOf( (sal_Int32)( (sal_Int8)nColor ) );
1453 aDest += aP;
1454 aDest += OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 8 ) ) );
1455 aDest += aP;
1456 aDest += OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 16 ) ) );
1457 aDest += ")";
1460 else if ( rAttributeName == "FillStyle" )
1462 ::com::sun::star::drawing::FillStyle eFillStyle;
1463 if ( rSourceValue >>= eFillStyle )
1465 if ( eFillStyle == ::com::sun::star::drawing::FillStyle_NONE )
1466 aDest += "none"; // ?
1467 else
1468 aDest += "solid";
1471 else if ( rAttributeName == "LineStyle" )
1473 ::com::sun::star::drawing::LineStyle eLineStyle;
1474 if ( rSourceValue >>= eLineStyle )
1476 if ( eLineStyle == ::com::sun::star::drawing::LineStyle_NONE )
1477 aDest += "false";
1478 else
1479 aDest += "true";
1482 else if ( rAttributeName == "CharWeight" )
1484 float fFontWeight = 0.0;
1485 if ( rSourceValue >>= fFontWeight )
1487 if ( fFontWeight == com::sun::star::awt::FontWeight::BOLD )
1488 aDest += "bold";
1489 else
1490 aDest += "normal";
1493 else if ( rAttributeName == "CharUnderline" )
1495 sal_Int16 nFontUnderline = 0;
1496 if ( rSourceValue >>= nFontUnderline )
1498 if ( nFontUnderline == com::sun::star::awt::FontUnderline::NONE )
1499 aDest += "false";
1500 else
1501 aDest += "true";
1504 else if ( rAttributeName == "CharPosture" )
1506 ::com::sun::star::awt::FontSlant eFontSlant;
1507 if ( rSourceValue >>= eFontSlant )
1509 if ( eFontSlant == com::sun::star::awt::FontSlant_ITALIC )
1510 aDest += "italic";
1511 else
1512 aDest += "normal"; // ?
1515 else if ( rAttributeName == "Visibility" )
1517 sal_Bool bVisible = sal_True;
1518 if ( rSourceValue >>= bVisible )
1520 if ( bVisible )
1521 aDest += "visible";
1522 else
1523 aDest += "hidden";
1526 Any aRet;
1527 if ( !aDest.isEmpty() )
1528 aRet <<= aDest;
1529 else
1530 aRet = rSourceValue;
1531 return aRet;
1534 void AnimationExporter::exportAnimateSet( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
1536 Reference< XAnimateSet > xSet( xNode, UNO_QUERY );
1537 if( xSet.is() )
1539 EscherExContainer aAnimateSet( rStrm, DFF_msofbtAnimateSet, 0 );
1541 EscherExAtom aAnimateSetData( rStrm, DFF_msofbtAnimateSetData );
1542 sal_uInt32 nId1 = 1; // ??
1543 sal_uInt32 nId2 = 1; // ??
1544 rStrm << nId1 << nId2;
1546 Any aConvertedValue( convertAnimateValue( xSet->getTo(), xSet->getAttributeName() ) );
1547 if ( aConvertedValue.hasValue() )
1548 exportAnimProperty( rStrm, 1, aConvertedValue, TRANSLATE_NONE );
1549 exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
1553 sal_uInt32 AnimationExporter::GetValueTypeForAttributeName( const OUString& rAttributeName )
1555 sal_uInt32 nValueType = 0;
1557 struct Entry
1559 const sal_Char* pName;
1560 sal_uInt8 nType;
1562 static const Entry lcl_attributeMap[] =
1564 { "charcolor", 2 },
1565 { "charfontname", 0 },
1566 { "charheight", 1 },
1567 { "charposture", 0 },
1568 // TODO(Q1): This should prolly be changed in PPT import
1569 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1570 { "charrotation", 1 },
1571 { "charunderline", 0 },
1572 { "charweight", 0 },
1573 { "color", 2 },
1574 { "dimcolor", 2 },
1575 { "fillcolor", 2 },
1576 { "fillstyle", 0 },
1577 { "height", 1 },
1578 { "linecolor", 2 },
1579 { "linestyle", 0 },
1580 { "opacity", 0 },
1581 { "rotate", 1 },
1582 { "skewx", 1 },
1583 { "skewy", 1 },
1584 { "visibility", 1 },
1585 { "width", 1 },
1586 { "x", 1 },
1587 { "y", 1 },
1588 { NULL, 0 }
1590 const Entry* pPtr = &lcl_attributeMap[ 0 ];
1591 while( pPtr->pName )
1593 if ( rAttributeName.equalsIgnoreAsciiCaseAscii( pPtr->pName ) )
1595 nValueType = pPtr->nType;
1596 break;
1598 pPtr++;
1600 DBG_ASSERT( pPtr->pName, "GetValueTypeForAttributeName, unknown property value!" );
1601 return nValueType;
1604 void AnimationExporter::exportAnimate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1606 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
1607 if ( xAnimate.is() )
1609 Any aBy ( xAnimate->getBy() );
1610 Any aFrom( xAnimate->getFrom() );
1611 Any aTo ( xAnimate->getTo() );
1613 EscherExContainer aContainer( rStrm, DFF_msofbtAnimate, 0 );
1615 EscherExAtom aAnimateData( rStrm, DFF_msofbtAnimateData );
1616 sal_uInt32 nBits = 0x38;
1617 sal_Int16 nTmp = xAnimate->getCalcMode();
1618 sal_uInt32 nCalcMode = /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp == AnimationCalcMode::LINEAR) ? 1 : 0;
1619 nTmp = xAnimate->getValueType();
1620 sal_uInt32 nValueType = GetValueTypeForAttributeName( xAnimate->getAttributeName() );
1622 if ( aBy.hasValue() )
1623 nBits |= 1;
1624 if ( aFrom.hasValue() )
1625 nBits |= 2;
1626 if ( aTo.hasValue() )
1627 nBits |= 4;
1629 rStrm << nCalcMode
1630 << nBits
1631 << nValueType;
1633 if ( aBy.hasValue() )
1634 exportAnimProperty( rStrm, 1, aBy, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1635 if ( aFrom.hasValue() )
1636 exportAnimProperty( rStrm, 2, aFrom, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1637 if ( aTo.hasValue() )
1638 exportAnimProperty( rStrm, 3, aTo, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1640 exportAnimateKeyPoints( rStrm, xAnimate );
1641 exportAnimateTarget( rStrm, xNode );
1645 void AnimationExporter::exportAnimateTarget( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_uInt32 nForceAttributeNames, int nAfterEffectType )
1647 EscherExContainer aAnimateTarget( rStrm, DFF_msofbtAnimateTarget, 0 );
1648 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
1649 if ( xAnimate.is() )
1652 EscherExAtom aAnimateTargetSettings( rStrm, DFF_msofbtAnimateTargetSettings, 0 );
1653 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1654 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1655 // nAccumulate 0 = none, 1 = always
1656 // nTransformType 0: "property" else "image"
1657 sal_uInt32 nBits = 0;
1658 sal_uInt32 nAdditive = 0;
1659 sal_uInt32 nAccumulate = 0;
1660 sal_uInt32 nTransformType = 0;
1661 if ( xAnimate.is() )
1663 if ( !xAnimate->getAttributeName().isEmpty() )
1664 nBits |= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1665 sal_Int16 nAdditiveMode = xAnimate->getAdditive();
1666 if ( nAdditiveMode != AnimationAdditiveMode::BASE )
1668 nBits |= 1;
1669 switch( nAdditiveMode )
1671 case AnimationAdditiveMode::SUM : nAdditive = 1; break;
1672 case AnimationAdditiveMode::REPLACE : nAdditive = 2; break;
1673 case AnimationAdditiveMode::MULTIPLY : nAdditive = 3; break;
1674 case AnimationAdditiveMode::NONE : nAdditive = 4; break;
1677 if ( xAnimate->getAccumulate() )
1679 nBits |= 2;
1680 nAccumulate = 1;
1683 rStrm << nBits
1684 << nAdditive
1685 << nAccumulate
1686 << nTransformType;
1688 if ( !xAnimate->getAttributeName().isEmpty() || nForceAttributeNames )
1690 EscherExContainer aAnimateAttributeNames( rStrm, DFF_msofbtAnimateAttributeNames, 1 );
1691 OUString aAttributeName( xAnimate->getAttributeName() );
1692 if ( nForceAttributeNames )
1694 if( nForceAttributeNames == 1 )
1696 aAttributeName = "r";
1699 sal_Int32 nIndex = 0;
1702 OUString aToken( aAttributeName.getToken( 0, ';', nIndex ) );
1703 exportAnimPropertyString( rStrm, 0, aToken, TRANSLATE_ATTRIBUTE );
1705 while ( nIndex >= 0 );
1708 if( nAfterEffectType != AFTEREFFECT_NONE )
1710 EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
1711 exportAnimPropertyuInt32( rStrm, 6, 1, TRANSLATE_NONE );
1712 if( nAfterEffectType == AFTEREFFECT_COLOR )
1714 exportAnimPropertyuInt32( rStrm, 4, 0, TRANSLATE_NONE );
1715 exportAnimPropertyuInt32( rStrm, 5, 0, TRANSLATE_NONE );
1718 exportAnimateTargetElement( rStrm, aTarget.hasValue() ? aTarget : xAnimate->getTarget(), sal_False );
1722 Reference< XShape > AnimationExporter::getTargetElementShape( const Any& rAny, sal_Int32& rBegin, sal_Int32& rEnd, sal_Bool& rParagraphTarget )
1724 Reference< XShape > xShape;
1725 rAny >>= xShape;
1727 rParagraphTarget = sal_False;
1729 if( !xShape.is() )
1731 ParagraphTarget aParaTarget;
1732 if( rAny >>= aParaTarget )
1733 xShape = aParaTarget.Shape;
1734 if ( xShape.is() )
1736 // now calculating the character range for the paragraph
1737 sal_Int16 nParagraph = aParaTarget.Paragraph;
1738 Reference< XSimpleText > xText( xShape, UNO_QUERY );
1739 if ( xText.is() )
1741 rParagraphTarget = sal_True;
1742 Reference< XEnumerationAccess > xTextParagraphEnumerationAccess( xText, UNO_QUERY );
1743 if ( xTextParagraphEnumerationAccess.is() )
1745 Reference< XEnumeration > xTextParagraphEnumeration( xTextParagraphEnumerationAccess->createEnumeration() );
1746 if ( xTextParagraphEnumeration.is() )
1748 sal_Int16 nCurrentParagraph;
1749 rBegin = rEnd = nCurrentParagraph = 0;
1750 while ( xTextParagraphEnumeration->hasMoreElements() )
1752 Reference< XTextRange > xTextRange( xTextParagraphEnumeration->nextElement(), UNO_QUERY );
1753 if ( xTextRange.is() )
1755 OUString aParaText( xTextRange->getString() );
1756 sal_Int32 nLength = aParaText.getLength() + 1;
1757 rEnd += nLength;
1758 if ( nCurrentParagraph == nParagraph )
1759 break;
1760 nCurrentParagraph++;
1761 rBegin += nLength;
1770 return xShape;
1773 void AnimationExporter::exportAnimateTargetElement( SvStream& rStrm, const Any aAny, const sal_Bool bCreate2b01Atom )
1775 sal_uInt32 nRefMode = 0; // nRefMode == 2 -> Paragraph
1776 sal_Int32 begin = -1;
1777 sal_Int32 end = -1;
1778 sal_Bool bParagraphTarget;
1780 Reference< XShape > xShape = getTargetElementShape( aAny, begin, end, bParagraphTarget );
1782 if( bParagraphTarget )
1783 nRefMode = 2;
1785 if ( xShape.is() || bCreate2b01Atom )
1787 EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
1788 if ( xShape.is() )
1790 EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
1792 sal_uInt32 nRefType = 1; // TODO: nRefType == 2 -> Sound;
1793 sal_uInt32 nRefId = ((EscherSolverContainer&)mrSolverContainer).GetShapeId( xShape );
1795 rStrm << nRefMode
1796 << nRefType
1797 << nRefId
1798 << begin
1799 << end;
1801 if ( bCreate2b01Atom )
1803 EscherExAtom a2b01Atom( rStrm, 0x2b01 );
1804 rStrm << (sal_uInt32)1; // ?
1809 void AnimationExporter::exportAnimateKeyPoints( SvStream& rStrm, const Reference< XAnimate >& xAnimate )
1811 Sequence< double > aKeyTimes( xAnimate->getKeyTimes() );
1812 Sequence< Any > aValues( xAnimate->getValues() );
1813 OUString aFormula( xAnimate->getFormula() );
1814 if ( aKeyTimes.getLength() )
1816 EscherExContainer aAnimKeyPoints( rStrm, DFF_msofbtAnimKeyPoints );
1817 sal_Int32 i;
1818 for ( i = 0; i < aKeyTimes.getLength(); i++ )
1821 EscherExAtom aAnimKeyTime( rStrm, DFF_msofbtAnimKeyTime );
1822 sal_Int32 nKeyTime = (sal_Int32)( aKeyTimes[ i ] * 1000.0 );
1823 rStrm << nKeyTime;
1825 Any aAny[ 2 ];
1826 if ( aValues[ i ].hasValue() )
1828 ValuePair aPair;
1829 if ( aValues[ i ] >>= aPair )
1831 aAny[ 0 ] = convertAnimateValue( aPair.First, xAnimate->getAttributeName() );
1832 aAny[ 1 ] = convertAnimateValue( aPair.Second, xAnimate->getAttributeName() );
1834 else
1836 aAny[ 0 ] = convertAnimateValue( aValues[ i ], xAnimate->getAttributeName() );
1838 if ( !i && !aFormula.isEmpty() )
1840 ImplTranslateAttribute( aFormula, TRANSLATE_MEASURE );
1841 aAny[ 1 ] <<= aFormula;
1843 exportAnimProperty( rStrm, 0, aAny[ 0 ], TRANSLATE_NONE );
1844 exportAnimProperty( rStrm, 1, aAny[ 1 ], TRANSLATE_NONE );
1850 void AnimationExporter::exportAnimValue( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Bool bExportAlways )
1852 Any aAny;
1853 // repeat count (0)
1854 double fRepeat = 0.0;
1855 float fRepeatCount = 0.0;
1856 com::sun::star::animations::Timing eTiming;
1857 aAny = xNode->getRepeatCount();
1858 if ( aAny >>= eTiming )
1860 if ( eTiming == Timing_INDEFINITE )
1861 fRepeatCount = ((float)3.40282346638528860e+38);
1863 else if ( aAny >>= fRepeat )
1864 fRepeatCount = (float)fRepeat;
1865 if ( fRepeatCount != 0.0 )
1867 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1868 sal_uInt32 nType = 0;
1869 rStrm << nType
1870 << fRepeatCount;
1872 // accelerate (3)
1873 float fAccelerate = (float)xNode->getAcceleration();
1874 if ( bExportAlways || ( fAccelerate != 0.0 ) )
1876 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1877 sal_uInt32 nType = 3;
1878 rStrm << nType
1879 << fAccelerate;
1882 // decelerate (4)
1883 float fDecelerate = (float)xNode->getDecelerate();
1884 if ( bExportAlways || ( fDecelerate != 0.0 ) )
1886 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1887 sal_uInt32 nType = 4;
1888 rStrm << nType
1889 << fDecelerate;
1892 // autoreverse (5)
1893 sal_Bool bAutoReverse = xNode->getAutoReverse();
1894 if ( bExportAlways || bAutoReverse )
1896 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1897 sal_uInt32 nType = 5;
1898 sal_uInt32 nVal = bAutoReverse ? 1 : 0;
1899 rStrm << nType
1900 << nVal;
1904 void AnimationExporter::exportTransitionFilter( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1906 Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY );
1907 if ( xFilter.is() )
1909 EscherExContainer aAnimateFilter( rStrm, DFF_msofbtAnimateFilter );
1911 EscherExAtom aAnimateFilterData( rStrm, DFF_msofbtAnimateFilterData );
1912 sal_uInt32 nBits = 3; // bit 0 -> use AnimAttributeValue
1913 // bit 1 -> use nTransition
1915 sal_uInt32 nTransition = xFilter->getMode() ? 0 : 1;
1916 rStrm << nBits
1917 << nTransition;
1919 const sal_Char* pFilter = FindTransitionName( xFilter->getTransition(), xFilter->getSubtype(), xFilter->getDirection() );
1920 if ( pFilter )
1922 const OUString aStr( OUString::createFromAscii( pFilter ) );
1923 exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
1925 exportAnimateTarget( rStrm, xNode );
1929 void AnimationExporter::exportAnimateMotion( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1931 Reference< XAnimateMotion > xMotion( xNode, UNO_QUERY );
1932 if ( xMotion.is() )
1934 EscherExContainer aAnimateMotion( rStrm, DFF_msofbtAnimateMotion );
1936 { //SJ: Ignored from import filter
1937 EscherExAtom aAnimateMotionData( rStrm, DFF_msofbtAnimateMotionData );
1938 sal_uInt32 nBits = 0x98;
1939 sal_uInt32 nOrigin = 0x2;
1940 float fByX = 100.0; // nBits&1
1941 float fByY = 100.0; // nBits&1
1942 float fFromX = 0.0; // nBits&2
1943 float fFromY = 0.0; // nBits&2
1944 float fToX = 100.0; // nBits&4
1945 float fToY = 100.0; // nBits&4
1946 rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nOrigin;
1949 OUString aStr;
1950 if ( xMotion->getPath() >>= aStr )
1952 if ( !aStr.isEmpty() )
1953 exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
1955 exportAnimateTarget( rStrm, xNode );
1960 void AnimationExporter::exportAnimateTransform( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1962 Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY );
1963 if ( xTransform.is() )
1965 if ( xTransform->getTransformType() == AnimationTransformType::SCALE )
1967 EscherExContainer aAnimateScale( rStrm, DFF_msofbtAnimateScale );
1969 EscherExAtom aAnimateScaleData( rStrm, DFF_msofbtAnimateScaleData );
1970 sal_uInt32 nBits = 0;
1971 sal_uInt32 nZoomContents = 1;
1972 float fByX = 100.0;
1973 float fByY = 100.0;
1974 float fFromX = 0.0;
1975 float fFromY = 0.0;
1976 float fToX = 100.0;
1977 float fToY = 100.0;
1979 double fX = 0.0, fY = 0.0;
1980 ValuePair aPair;
1981 if ( xTransform->getBy() >>= aPair )
1983 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
1985 nBits |= 1;
1986 fByX = (float)( fX * 100 );
1987 fByY = (float)( fY * 100 );
1990 if ( xTransform->getFrom() >>= aPair )
1992 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
1994 nBits |= 2;
1995 fFromX = (float)( fX * 100 );
1996 fFromY = (float)( fY * 100 );
1999 if( xTransform->getTo() >>= aPair )
2001 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
2003 nBits |= 4;
2004 fToX = (float)( fX * 100 );
2005 fToY = (float)( fY * 100 );
2009 // TODO: ZoomContents:
2010 //if( nBits & 8 )
2011 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
2013 rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nZoomContents;
2015 exportAnimateTarget( rStrm, xNode );
2017 else if ( xTransform->getTransformType() == AnimationTransformType::ROTATE )
2019 EscherExContainer aAnimateRotation( rStrm, DFF_msofbtAnimateRotation );
2021 EscherExAtom aAnimateRotationData( rStrm, DFF_msofbtAnimateRotationData );
2022 sal_uInt32 nBits = 0;
2023 sal_uInt32 nU1 = 0;
2024 float fBy = 360.0;
2025 float fFrom = 0.0;
2026 float fTo = 360.0;
2028 double fVal = 0.0;
2029 if ( xTransform->getBy() >>= fVal )
2031 nBits |= 1;
2032 fBy = (float)fVal;
2034 if ( xTransform->getFrom() >>= fVal )
2036 nBits |= 2;
2037 fFrom = (float)fVal;
2039 if ( xTransform->getTo() >>= fVal )
2041 nBits |= 4;
2042 fTo = (float)fVal;
2044 rStrm << nBits << fBy << fFrom << fTo << nU1;
2046 exportAnimateTarget( rStrm, xNode, 1 );
2051 sal_Bool AnimationExporter::getColorAny( const Any& rAny, const sal_Int16 nColorSpace, sal_Int32& rMode, sal_Int32& rA, sal_Int32& rB, sal_Int32& rC ) const
2053 sal_Bool bIsColor = sal_True;
2055 rMode = 0;
2056 if ( nColorSpace == AnimationColorSpace::HSL )
2057 rMode = 1;
2059 sal_Int32 nColor = 0;
2060 Sequence< double > aHSL( 3 );
2061 if ( rAny >>= nColor ) // RGB color
2063 rA = (sal_uInt8)( nColor >> 16 );
2064 rB = (sal_uInt8)( nColor >> 8 );
2065 rC = (sal_uInt8)( nColor );
2067 else if ( rAny >>= aHSL ) // HSL
2069 rA = (sal_Int32) ( aHSL[ 0 ] * 255.0 / 360.0 );
2070 rB = (sal_Int32) ( aHSL[ 1 ] * 255.0 );
2071 rC = (sal_Int32) ( aHSL[ 2 ] * 255.0 );
2073 else
2074 bIsColor = sal_False;
2075 return bIsColor;
2078 void AnimationExporter::exportAnimateColor( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
2080 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
2081 if ( xColor.is() )
2083 EscherExContainer aAnimateColor( rStrm, DFF_msofbtAnimateColor );
2085 EscherExAtom aAnimateColorData( rStrm, DFF_msofbtAnimateColorData );
2086 sal_uInt32 nBits = 8;
2088 sal_Int32 nByMode, nByA, nByB, nByC;
2089 nByMode = nByA = nByB = nByC = 0;
2091 sal_Int32 nFromMode, nFromA, nFromB, nFromC;
2092 nFromMode = nFromA = nFromB = nFromC = 0;
2094 sal_Int32 nToMode, nToA, nToB, nToC;
2095 nToMode = nToA = nToB = nToC = 0;
2097 sal_Int16 nColorSpace = xColor->getColorInterpolation();
2099 Any aAny( xColor->getBy() );
2100 if ( aAny.hasValue() )
2102 if ( getColorAny( aAny, nColorSpace, nByMode, nByA, nByB, nByC ) )
2103 nBits |= 0x11;
2105 aAny = xColor->getFrom();
2106 if ( aAny.hasValue() )
2108 if ( getColorAny( aAny, nColorSpace, nFromMode, nFromA, nFromB, nFromC ) )
2109 nBits |= 0x12;
2111 aAny = xColor->getTo();
2112 if ( aAny.hasValue() )
2114 if ( getColorAny( aAny, nColorSpace, nToMode, nToA, nToB, nToC ) )
2115 nBits |= 0x14;
2117 rStrm << nBits
2118 << nByMode << nByA << nByB << nByC
2119 << nFromMode << nFromA << nFromB << nFromC
2120 << nToMode << nToA << nToB << nToC;
2122 exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
2126 void AnimationExporter::exportIterate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
2128 Reference< XIterateContainer > xIterate( xNode, UNO_QUERY );
2129 if ( xIterate.is() )
2131 EscherExAtom aAnimIteration( rStrm, DFF_msofbtAnimIteration );
2133 float fInterval = 10.0;
2134 sal_Int32 nTextUnitEffect = 0;
2135 sal_Int32 nU1 = 1;
2136 sal_Int32 nU2 = 1;
2137 sal_Int32 nU3 = 0xe;
2139 sal_Int16 nIterateType = xIterate->getIterateType();
2140 switch( nIterateType )
2142 case TextAnimationType::BY_WORD : nTextUnitEffect = 1; break;
2143 case TextAnimationType::BY_LETTER : nTextUnitEffect = 2; break;
2146 fInterval = (float)xIterate->getIterateInterval();
2148 // convert interval from absolute to percentage
2149 double fDuration = 0.0;
2151 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
2152 if( xEnumerationAccess.is() )
2154 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
2155 if( xEnumeration.is() )
2157 while( xEnumeration->hasMoreElements() )
2159 Reference< XAnimate > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
2160 if( xChildNode.is() )
2162 double fChildBegin = 0.0;
2163 double fChildDuration = 0.0;
2164 xChildNode->getBegin() >>= fChildBegin;
2165 xChildNode->getDuration() >>= fChildDuration;
2167 fChildDuration += fChildBegin;
2168 if( fChildDuration > fDuration )
2169 fDuration = fChildDuration;
2175 if( fDuration )
2176 fInterval = (float)(100.0 * fInterval / fDuration);
2178 rStrm << fInterval << nTextUnitEffect << nU1 << nU2 << nU3;
2179 aTarget = xIterate->getTarget();
2183 } // namespace ppt;
2185 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */