merge the formfield patch from ooo-build
[ooovba.git] / sd / source / filter / eppt / pptexanimations.cxx
blob8b6818a30d1180253cb1ba65fa7fadc6b4cd080a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pptexanimations.cxx,v $
10 * $Revision: 1.15.108.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
33 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
34 #include <com/sun/star/animations/AnimationFill.hpp>
35 #include <com/sun/star/animations/AnimationRestart.hpp>
36 #include <com/sun/star/animations/Timing.hpp>
37 #include <com/sun/star/animations/Event.hpp>
38 #include <com/sun/star/animations/AnimationEndSync.hpp>
39 #include <com/sun/star/animations/EventTrigger.hpp>
40 #include <com/sun/star/presentation/EffectNodeType.hpp>
41 #include <com/sun/star/presentation/EffectPresetClass.hpp>
42 #include <com/sun/star/animations/AnimationNodeType.hpp>
43 #include <com/sun/star/animations/AnimationTransformType.hpp>
44 #include <com/sun/star/animations/AnimationCalcMode.hpp>
45 #include <com/sun/star/animations/AnimationValueType.hpp>
46 #include <com/sun/star/util/XCloneable.hpp>
47 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
48 #include <com/sun/star/animations/XAnimateSet.hpp>
49 #include <com/sun/star/animations/XAudio.hpp>
50 #include <com/sun/star/animations/XTransitionFilter.hpp>
51 #include <com/sun/star/animations/XAnimateColor.hpp>
52 #include <com/sun/star/animations/XAnimateMotion.hpp>
53 #include <com/sun/star/animations/XAnimateTransform.hpp>
54 #include <com/sun/star/animations/TransitionType.hpp>
55 #include <com/sun/star/animations/TransitionSubType.hpp>
56 #include <com/sun/star/animations/ValuePair.hpp>
57 #include <com/sun/star/animations/AnimationColorSpace.hpp>
58 #include <com/sun/star/beans/NamedValue.hpp>
59 #include <com/sun/star/drawing/FillStyle.hpp>
60 #include <com/sun/star/drawing/LineStyle.hpp>
61 #include <com/sun/star/awt/FontWeight.hpp>
62 #include <com/sun/star/awt/FontUnderline.hpp>
63 #include <com/sun/star/awt/FontSlant.hpp>
64 #include <com/sun/star/container/XEnumerationAccess.hpp>
65 #include <com/sun/star/presentation/ParagraphTarget.hpp>
66 #include <com/sun/star/text/XSimpleText.hpp>
67 #include <com/sun/star/animations/XIterateContainer.hpp>
68 #include <com/sun/star/presentation/TextAnimationType.hpp>
69 #include <com/sun/star/container/XChild.hpp>
70 #include <comphelper/processfactory.hxx>
71 #include <rtl/ustrbuf.hxx>
72 #ifndef _RTL_MEMORY_H_
73 #include <rtl/memory.hxx>
74 #endif
76 #include <vcl/vclenum.hxx>
77 #include <svx/svdotext.hxx>
78 #include <svx/outlobj.hxx>
79 #include <svx/editobj.hxx>
80 #include <pptexanimations.hxx>
81 #include <osl/endian.h>
83 #include <algorithm>
85 using ::std::map;
86 using ::rtl::OUString;
87 using ::rtl::OUStringBuffer;
88 using ::com::sun::star::uno::Any;
89 using ::com::sun::star::container::XChild;
90 using ::com::sun::star::util::XCloneable;
91 using ::com::sun::star::uno::Reference;
92 using ::com::sun::star::uno::UNO_QUERY;
93 using ::com::sun::star::uno::UNO_QUERY_THROW;
94 using ::com::sun::star::uno::Sequence;
95 using ::com::sun::star::uno::makeAny;
96 using ::com::sun::star::uno::Exception;
97 using ::com::sun::star::uno::XInterface;
98 using ::com::sun::star::beans::NamedValue;
99 using ::com::sun::star::container::XEnumerationAccess;
100 using ::com::sun::star::container::XEnumeration;
101 using ::com::sun::star::lang::XMultiServiceFactory;
103 using namespace ::com::sun::star::text;
104 using namespace ::com::sun::star::drawing;
105 using namespace ::com::sun::star::animations;
106 using namespace ::com::sun::star::presentation;
108 namespace ppt
111 void ImplTranslateAttribute( rtl::OUString& rString, const TranslateMode eTranslateMode )
113 if ( eTranslateMode != TRANSLATE_NONE )
115 if ( ( eTranslateMode & TRANSLATE_VALUE ) || ( eTranslateMode & TRANSLATE_ATTRIBUTE ) )
117 const ImplAttributeNameConversion* p = gImplConversionList;
118 while( p->mpAPIName )
120 if( rString.compareToAscii( p->mpAPIName ) == 0 )
121 break;
122 p++;
124 if( p->mpMSName )
126 if ( eTranslateMode & TRANSLATE_VALUE )
128 rString = rtl::OUString( (sal_Unicode)'#' );
129 rString += OUString::createFromAscii( p->mpMSName );
131 else
132 rString = OUString::createFromAscii( p->mpMSName );
135 else if ( eTranslateMode & TRANSLATE_MEASURE )
137 const sal_Char* pDest[] = { "#ppt_x", "#ppt_y", "#ppt_w", "#ppt_h", NULL };
138 const sal_Char* pSource[] = { "x", "y", "width", "height", NULL };
139 sal_Int32 nIndex = 0;
141 const sal_Char** ps = pSource;
142 const sal_Char** pd = pDest;
144 while( *ps )
146 const OUString aSearch( OUString::createFromAscii( *ps ) );
147 while( (nIndex = rString.indexOf( aSearch, nIndex )) != -1 )
149 sal_Int32 nLength = aSearch.getLength();
150 if( nIndex && (rString.getStr()[nIndex-1] == '#' ) )
152 nIndex--;
153 nLength++;
156 const OUString aNew( OUString::createFromAscii( *pd ) );
157 rString = rString.replaceAt( nIndex, nLength, aNew );
158 nIndex += aNew.getLength();
160 ps++;
161 pd++;
167 sal_uInt32 ImplTranslatePresetSubType( const sal_uInt32 nPresetClass, const sal_uInt32 nPresetId, const rtl::OUString& rPresetSubType )
169 sal_uInt32 nPresetSubType = 0;
170 sal_Bool bTranslated = sal_False;
172 if ( ( nPresetClass == (sal_uInt32)EffectPresetClass::ENTRANCE ) || ( nPresetClass == (sal_uInt32)EffectPresetClass::EXIT ) )
174 if ( nPresetId != 21 )
176 switch( nPresetId )
178 case 5 :
180 if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "downward" ) ) )
182 nPresetSubType = 5;
183 bTranslated = sal_True;
185 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "across" ) ) )
187 nPresetSubType = 10;
188 bTranslated = sal_True;
191 break;
192 case 17 :
194 if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "across" ) ) )
196 nPresetSubType = 10;
197 bTranslated = sal_True;
200 break;
201 case 18 :
203 if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "right-to-top" ) ) )
205 nPresetSubType = 3;
206 bTranslated = sal_True;
208 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "right-to-bottom" ) ) )
210 nPresetSubType = 6;
211 bTranslated = sal_True;
213 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "left-to-top" ) ) )
215 nPresetSubType = 9;
216 bTranslated = sal_True;
218 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "left-to-bottom" ) ) )
220 nPresetSubType = 12;
221 bTranslated = sal_True;
224 break;
227 if ( !bTranslated )
229 const convert_subtype* p = gConvertArray;
230 while( p->mpStrSubType )
232 if ( rPresetSubType.equalsAscii( p->mpStrSubType ) )
234 nPresetSubType = p->mnID;
235 bTranslated = sal_True;
236 break;
238 p++;
242 if ( !bTranslated )
243 nPresetSubType = (sal_uInt32)rPresetSubType.toInt32();
244 return nPresetSubType;
247 const sal_Char* transition::find( const sal_Int16 nType, const sal_Int16 nSubType, const sal_Bool bDirection )
249 const sal_Char* pRet = NULL;
250 int nFit = 0;
252 const transition* p = gTransitions;
253 while( p->mpName )
255 int nF = 0;
256 if ( nType == p->mnType )
257 nF += 4;
258 if ( nSubType == p->mnSubType )
259 nF += 2;
260 if ( bDirection == p->mbDirection )
261 nF += 1;
262 if ( nF > nFit )
264 pRet = p->mpName;
265 nFit = nF;
267 if ( nFit == 7 ) // maximum
268 break;
269 p++;
271 return pRet;
274 SvStream& operator<<(SvStream& rOut, AnimationNode& rNode )
276 rOut << rNode.mnU1;
277 rOut << rNode.mnRestart;
278 rOut << rNode.mnGroupType;
279 rOut << rNode.mnFill;
280 rOut << rNode.mnU3;
281 rOut << rNode.mnU4;
282 rOut << rNode.mnDuration;
283 rOut << rNode.mnNodeType;
285 return rOut;
288 AnimationExporter::AnimationExporter( const EscherSolverContainer& rSolverContainer, ppt::ExSoundCollection& rExSoundCollection ) :
289 mrSolverContainer ( rSolverContainer ),
290 mrExSoundCollection ( rExSoundCollection ),
291 mnCurrentGroup(0)
295 // --------------------------------------------------------------------
297 static sal_Int16 GetFillMode( const Reference< XAnimationNode >& xNode, const sal_Int16 nFillDefault )
299 sal_Int16 nFill = xNode->getFill();
300 if ( ( nFill == AnimationFill::DEFAULT ) ||
301 ( nFill == AnimationFill::INHERIT ) )
303 if ( nFill != AnimationFill::AUTO )
304 nFill = nFillDefault;
306 if( nFill == AnimationFill::AUTO )
308 nFill = AnimationFill::REMOVE;
309 sal_Bool bIsIndefiniteTiming = sal_True;
310 Any aAny = xNode->getDuration();
311 if( aAny.hasValue() )
313 Timing eTiming;
314 if( aAny >>= eTiming )
315 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
317 if ( bIsIndefiniteTiming )
319 aAny = xNode->getEnd();
320 if( aAny.hasValue() )
322 Timing eTiming;
323 if( aAny >>= eTiming )
324 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
326 if ( bIsIndefiniteTiming )
328 if ( !xNode->getRepeatCount().hasValue() )
330 aAny = xNode->getRepeatDuration();
331 if( aAny.hasValue() )
333 Timing eTiming;
334 if( aAny >>= eTiming )
335 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
337 if ( bIsIndefiniteTiming )
338 nFill = AnimationFill::FREEZE;
343 return nFill;
346 void AnimationExporter::doexport( const Reference< XDrawPage >& xPage, SvStream& rStrm )
348 Reference< XAnimationNodeSupplier > xNodeSupplier( xPage, UNO_QUERY );
349 if( xNodeSupplier.is() )
351 const Reference< XAnimationNode > xRootNode( xNodeSupplier->getAnimationNode() );
352 if( xRootNode.is() )
354 processAfterEffectNodes( xRootNode );
355 exportNode( rStrm, xRootNode, NULL, DFF_msofbtAnimGroup, 1, 0, sal_False, AnimationFill::AUTO );
360 void AnimationExporter::processAfterEffectNodes( const Reference< XAnimationNode >& xRootNode )
364 Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
365 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
366 while( xEnumeration->hasMoreElements() )
368 Reference< XAnimationNode > xNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
370 Reference< XEnumerationAccess > xEnumerationAccess2( xNode, UNO_QUERY );
371 if ( xEnumerationAccess2.is() )
373 Reference< XEnumeration > xEnumeration2( xEnumerationAccess2->createEnumeration(), UNO_QUERY_THROW );
374 while( xEnumeration2->hasMoreElements() )
376 Reference< XAnimationNode > xChildNode( xEnumeration2->nextElement(), UNO_QUERY_THROW );
378 Reference< XEnumerationAccess > xEnumerationAccess3( xChildNode, UNO_QUERY_THROW );
379 Reference< XEnumeration > xEnumeration3( xEnumerationAccess3->createEnumeration(), UNO_QUERY_THROW );
380 while( xEnumeration3->hasMoreElements() )
382 Reference< XAnimationNode > xChildNode2( xEnumeration3->nextElement(), UNO_QUERY_THROW );
384 Reference< XEnumerationAccess > xEnumerationAccess4( xChildNode2, UNO_QUERY_THROW );
385 Reference< XEnumeration > xEnumeration4( xEnumerationAccess4->createEnumeration(), UNO_QUERY_THROW );
386 while( xEnumeration4->hasMoreElements() )
388 Reference< XAnimationNode > xChildNode3( xEnumeration4->nextElement(), UNO_QUERY_THROW );
390 switch( xChildNode3->getType() )
392 // found an after effect
393 case AnimationNodeType::SET:
394 case AnimationNodeType::ANIMATECOLOR:
396 Reference< XAnimationNode > xMaster;
398 Sequence< NamedValue > aUserData( xChildNode3->getUserData() );
399 sal_Int32 nLength = aUserData.getLength();
400 const NamedValue* p = aUserData.getConstArray();
402 while( nLength-- )
404 if( p->Name.equalsAscii( "master-element" ) )
406 p->Value >>= xMaster;
407 break;
409 p++;
412 AfterEffectNodePtr pAfterEffectNode( new AfterEffectNode( xChildNode3, xMaster ) );
413 maAfterEffectNodes.push_back( pAfterEffectNode );
415 break;
423 catch( Exception& e )
425 (void)e;
426 DBG_ERROR( "(@CL)AnimationExporter::processAfterEffectNodes(), exception cought!" );
430 bool AnimationExporter::isAfterEffectNode( const Reference< XAnimationNode >& xNode ) const
432 std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
433 const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
434 while( aIter != aEnd )
436 if( (*aIter)->mxNode == xNode )
437 return true;
438 aIter++;
441 return false;
444 bool AnimationExporter::hasAfterEffectNode( const Reference< XAnimationNode >& xNode, Reference< XAnimationNode >& xAfterEffectNode ) const
446 std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
447 const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
448 while( aIter != aEnd )
450 if( (*aIter)->mxMaster == xNode )
452 xAfterEffectNode = (*aIter)->mxNode;
453 return true;
455 aIter++;
458 return false;
461 // check if this group only contain empty groups. this may happen when
462 // after effect nodes are not exported at theire original position
463 bool AnimationExporter::isEmptyNode( const Reference< XAnimationNode >& xNode ) const
465 if( xNode.is() ) switch( xNode->getType() )
467 case AnimationNodeType::PAR :
468 case AnimationNodeType::SEQ :
469 case AnimationNodeType::ITERATE :
471 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
472 if( xEnumerationAccess.is() )
474 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
475 if( xEnumeration.is() )
477 while( xEnumeration->hasMoreElements() )
479 Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
480 if( xChildNode.is() && !isEmptyNode( xChildNode ) )
481 return false;
486 break;
488 case AnimationNodeType::SET :
489 case AnimationNodeType::ANIMATECOLOR :
490 return isAfterEffectNode( xNode );
491 default:
492 return false;
495 return true;
498 void AnimationExporter::exportNode( SvStream& rStrm, Reference< XAnimationNode > xNode, const Reference< XAnimationNode >* pParent, const sal_uInt16 nContainerRecType,
499 const sal_uInt16 nInstance, const sal_Int32 nGroupLevel, const sal_Bool bTakeBackInteractiveSequenceTiming, const sal_Int16 nFDef )
501 if( (nGroupLevel == 4) && isEmptyNode( xNode ) )
502 return;
504 if ( ( nContainerRecType == DFF_msofbtAnimGroup ) && ( nGroupLevel == 2 ) && isEmptyNode( xNode ) )
505 return;
507 if( nContainerRecType == DFF_msofbtAnimGroup )
508 mnCurrentGroup++;
510 sal_Bool bTakeBackInteractiveSequenceTimingForChild = sal_False;
511 sal_Int16 nFillDefault = GetFillMode( xNode, nFDef );
513 bool bSkipChildren = false;
515 Reference< XAnimationNode > xAudioNode;
516 static sal_uInt32 nAudioGroup;
519 EscherExContainer aContainer( rStrm, nContainerRecType, nInstance );
520 switch( xNode->getType() )
522 case AnimationNodeType::CUSTOM :
524 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
525 exportAnimPropertySet( rStrm, xNode );
526 exportAnimEvent( rStrm, xNode, 0 );
527 exportAnimValue( rStrm, xNode, sal_False );
529 break;
531 case AnimationNodeType::PAR :
533 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
534 exportAnimPropertySet( rStrm, xNode );
535 sal_Int32 nFlags = nGroupLevel == 2 ? 0x10 : 0;
536 if ( bTakeBackInteractiveSequenceTiming )
537 nFlags |= 0x40;
538 exportAnimEvent( rStrm, xNode, nFlags );
539 exportAnimValue( rStrm, xNode, nGroupLevel == 4 );
541 break;
543 case AnimationNodeType::SEQ :
545 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
546 sal_Int16 nNodeType = exportAnimPropertySet( rStrm, xNode );
547 sal_Int32 nFlags = 12;
548 if ( ( nGroupLevel == 1 ) && ( nNodeType == ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE ) )
550 nFlags |= 0x20;
551 bTakeBackInteractiveSequenceTimingForChild = sal_True;
553 exportAnimAction( rStrm, xNode );
554 exportAnimEvent( rStrm, xNode, nFlags );
555 exportAnimValue( rStrm, xNode, sal_False );
557 break;
559 case AnimationNodeType::ITERATE :
562 EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
563 AnimationNode aAnim;
564 rtl_zeroMemory( &aAnim, sizeof( aAnim ) );
565 aAnim.mnGroupType = mso_Anim_GroupType_PAR;
566 aAnim.mnNodeType = 1;
567 // attribute Restart
568 switch( xNode->getRestart() )
570 default:
571 case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
572 case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
573 case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
574 case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
576 // attribute Fill
577 switch( xNode->getFill() )
579 default:
580 case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
581 case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
582 case AnimationFill::FREEZE : aAnim.mnFill = 2; break;
583 case AnimationFill::HOLD : aAnim.mnFill = 3; break;
584 case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
586 rStrm << aAnim;
588 exportIterate( rStrm, xNode );
589 exportAnimPropertySet( rStrm, xNode );
590 exportAnimEvent( rStrm, xNode, 0 );
591 exportAnimValue( rStrm, xNode, sal_False );
594 EscherExContainer aContainer( rStrm, DFF_msofbtAnimGroup, 1 );
595 exportAnimNode( rStrm, xNode, pParent, nGroupLevel + 1, nFillDefault );
596 exportAnimPropertySet( rStrm, xNode );
597 exportAnimEvent( rStrm, xNode, 0 );
598 exportAnimValue( rStrm, xNode, sal_False );
601 break;
603 case AnimationNodeType::ANIMATE :
605 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
606 exportAnimPropertySet( rStrm, xNode );
607 exportAnimEvent( rStrm, xNode, 0 );
608 exportAnimValue( rStrm, xNode, sal_False );
609 exportAnimate( rStrm, xNode );
611 break;
613 case AnimationNodeType::SET :
615 bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
616 if( (nGroupLevel != 4) || !bIsAfterEffectNode )
618 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
619 exportAnimPropertySet( rStrm, xNode );
620 exportAnimateSet( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_SET : AFTEREFFECT_NONE );
621 exportAnimEvent( rStrm, xNode, 0 );
622 exportAnimValue( rStrm, xNode, sal_False );
624 else
626 bSkipChildren = true;
629 break;
631 case AnimationNodeType::ANIMATEMOTION :
633 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
634 exportAnimPropertySet( rStrm, xNode );
635 exportAnimateMotion( rStrm, xNode );
636 exportAnimEvent( rStrm, xNode, 0 );
637 exportAnimValue( rStrm, xNode, sal_False );
639 break;
641 case AnimationNodeType::ANIMATECOLOR :
643 bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
644 if( (nGroupLevel != 4) || !bIsAfterEffectNode )
646 if( bIsAfterEffectNode )
647 xNode = createAfterEffectNodeClone( xNode );
649 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
650 exportAnimPropertySet( rStrm, xNode );
651 exportAnimateColor( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_COLOR : AFTEREFFECT_NONE );
652 exportAnimEvent( rStrm, xNode, 0 );
653 exportAnimValue( rStrm, xNode, sal_False );
655 else
657 bSkipChildren = true;
660 break;
662 case AnimationNodeType::ANIMATETRANSFORM :
664 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
665 exportAnimPropertySet( rStrm, xNode );
666 exportAnimateTransform( rStrm, xNode );
667 exportAnimEvent( rStrm, xNode, 0 );
668 exportAnimValue( rStrm, xNode, sal_False );
670 break;
672 case AnimationNodeType::TRANSITIONFILTER :
674 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
675 exportAnimPropertySet( rStrm, xNode );
676 exportAnimEvent( rStrm, xNode, 0 );
677 exportAnimValue( rStrm, xNode, sal_False );
678 exportTransitionFilter( rStrm, xNode );
680 break;
682 case AnimationNodeType::AUDIO : // #i58428#
684 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
685 exportAnimPropertySet( rStrm, xNode );
687 Reference< XAudio > xAudio( xNode, UNO_QUERY );
688 if( xAudio.is() )
690 Any aAny( xAudio->getSource() );
691 rtl::OUString aURL;
693 if ( ( aAny >>= aURL ) && ( aURL.getLength() ) )
695 sal_Int32 nU1 = 2;
696 sal_Int32 nTrigger = 3;
697 sal_Int32 nU3 = nAudioGroup;
698 sal_Int32 nBegin = 0;
700 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 1 );
702 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
703 rStrm << nU1 << nTrigger << nU3 << nBegin;
706 nU1 = 1;
707 nTrigger = 0xb;
708 nU3 = 0;
710 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 2 );
712 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
713 rStrm << nU1 << nTrigger << nU3 << nBegin;
716 EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
718 sal_uInt32 nRefMode = 3;
719 sal_uInt32 nRefType = 2;
720 sal_uInt32 nRefId = mrExSoundCollection.GetId( aURL );
721 sal_Int32 begin = -1;
722 sal_Int32 end = -1;
724 EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
725 rStrm << nRefMode << nRefType << nRefId << begin << end;
729 exportAnimValue( rStrm, xNode, sal_False );
731 break;
733 if( !bSkipChildren )
735 // export after effect node if one exists for this node
736 Reference< XAnimationNode > xAfterEffectNode;
737 if( hasAfterEffectNode( xNode, xAfterEffectNode ) )
739 exportNode( rStrm, xAfterEffectNode, &xNode, DFF_msofbtAnimSubGoup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
742 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
743 if( xEnumerationAccess.is() )
745 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
746 if( xEnumeration.is() )
748 while( xEnumeration->hasMoreElements() )
750 Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
751 if( xChildNode.is() )
753 if ( xChildNode->getType() == AnimationNodeType::AUDIO )
755 xAudioNode = xChildNode;
756 nAudioGroup = mnCurrentGroup;
758 else
759 exportNode( rStrm, xChildNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
766 if ( xAudioNode.is() )
767 exportNode( rStrm, xAudioNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
769 if( xNode->getType() == AnimationNodeType::ITERATE )
770 aTarget = Any();
773 Reference< XAnimationNode > AnimationExporter::createAfterEffectNodeClone( const Reference< XAnimationNode >& xNode ) const
777 Reference< ::com::sun::star::util::XCloneable > xClonable( xNode, UNO_QUERY_THROW );
778 Reference< XAnimationNode > xCloneNode( xClonable->createClone(), UNO_QUERY_THROW );
780 Any aEmpty;
781 xCloneNode->setBegin( aEmpty );
784 return xCloneNode;
786 catch( Exception& e )
788 (void)e;
789 DBG_ERROR("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
791 return xNode;
794 void AnimationExporter::exportAnimNode( SvStream& rStrm, const Reference< XAnimationNode >& xNode,
795 const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >*, const sal_Int32, const sal_Int16 nFillDefault )
797 EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
798 AnimationNode aAnim;
799 rtl_zeroMemory( &aAnim, sizeof( aAnim ) );
801 // attribute Restart
802 switch( xNode->getRestart() )
804 default:
805 case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
806 case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
807 case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
808 case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
811 // attribute Fill
812 // aAnim.mnFill = GetFillMode( xNode, pParent );
813 switch( nFillDefault )
815 default:
816 case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
817 case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
818 case AnimationFill::FREEZE : // aAnim.mnFill = 2; break;
819 case AnimationFill::HOLD : aAnim.mnFill = 3; break;
820 case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
822 // attribute Duration
823 double fDuration = 0.0;
824 com::sun::star::animations::Timing eTiming;
825 if ( xNode->getDuration() >>= eTiming )
827 if ( eTiming == Timing_INDEFINITE )
828 aAnim.mnDuration = -1;
830 else if ( xNode->getDuration() >>= fDuration )
832 aAnim.mnDuration = (sal_Int32)( fDuration * 1000.0 );
834 else
835 aAnim.mnDuration = -1;
837 // NodeType, NodeGroup
838 aAnim.mnNodeType = 1;
839 aAnim.mnGroupType = mso_Anim_GroupType_SEQ;
840 switch( xNode->getType() )
842 case AnimationNodeType::PAR : // PASSTROUGH!!! (as it was intended)
843 aAnim.mnGroupType = mso_Anim_GroupType_PAR;
844 case AnimationNodeType::SEQ :
846 // trying to get the nodetype
847 Sequence< NamedValue > aUserData = xNode->getUserData();
848 if ( aUserData.getLength() )
850 const NamedValue* p = aUserData.getConstArray();
851 sal_Int32 nLength = aUserData.getLength();
852 while( nLength-- )
854 if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) )
856 sal_Int16 nType = 0;
857 if ( p->Value >>= nType )
859 switch( nType )
861 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : aAnim.mnNodeType = 0x12; break;
862 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : aAnim.mnNodeType = 0x18; break;
864 case ::com::sun::star::presentation::EffectNodeType::ON_CLICK :
865 case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS :
866 case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS :
867 case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE :
868 default:
872 break;
877 break;
879 case AnimationNodeType::ANIMATE :
880 case AnimationNodeType::SET :
882 case AnimationNodeType::CUSTOM :
883 case AnimationNodeType::ITERATE :
884 case AnimationNodeType::ANIMATEMOTION :
885 case AnimationNodeType::ANIMATECOLOR :
886 case AnimationNodeType::ANIMATETRANSFORM :
888 aAnim.mnGroupType = mso_Anim_GroupType_NODE;
889 aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
891 break;
893 case AnimationNodeType::AUDIO :
895 aAnim.mnGroupType = mso_Anim_GroupType_MEDIA;
896 aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
898 break;
900 case AnimationNodeType::TRANSITIONFILTER :
902 aAnim.mnGroupType = mso_Anim_GroupType_NODE;
903 aAnim.mnNodeType = mso_Anim_Behaviour_FILTER;
905 break;
907 rStrm << aAnim;
910 sal_Int16 AnimationExporter::exportAnimPropertySet( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
912 sal_Int16 nNodeType = ::com::sun::star::presentation::EffectNodeType::DEFAULT;
914 EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
915 const ::com::sun::star::uno::Any* pAny[ DFF_ANIM_PROPERTY_ID_COUNT ];
916 rtl_zeroMemory( pAny, sizeof( pAny ) );
918 Reference< XAnimationNode > xMaster;
920 const Any aTrue( makeAny( (sal_Bool)sal_True ) );
921 Any aMasterRel, aOverride, aRunTimeContext;
923 // storing user data into pAny, to allow direct access later
924 Sequence< NamedValue > aUserData = xNode->getUserData();
925 if ( aUserData.getLength() )
927 const NamedValue* p = aUserData.getConstArray();
928 sal_Int32 nLength = aUserData.getLength();
929 while( nLength-- )
931 if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) )
933 pAny[ DFF_ANIM_NODE_TYPE ] = &(p->Value);
935 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-class" ) ) )
937 pAny[ DFF_ANIM_PRESET_CLASS ] = &(p->Value);
939 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-id" ) ) )
941 pAny[ DFF_ANIM_PRESET_ID ] = &(p->Value);
943 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-sub-type" ) ) )
945 pAny[ DFF_ANIM_PRESET_SUB_TYPE ] = &(p->Value);
947 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "master-element" ) ) )
949 pAny[ DFF_ANIM_AFTEREFFECT ] = &aTrue;
950 p->Value >>= xMaster;
952 p++;
956 // calculate master-rel
957 if( xMaster.is() )
959 sal_Int32 nMasterRel = 2;
960 Reference< XChild > xNodeChild( xNode, UNO_QUERY );
961 Reference< XChild > xMasterChild( xMaster, UNO_QUERY );
962 if( xNodeChild.is() && xMasterChild.is() && (xNodeChild->getParent() == xMasterChild->getParent() ) )
963 nMasterRel = 0;
965 aMasterRel <<= nMasterRel;
967 pAny[ DFF_ANIM_MASTERREL ] = &aMasterRel;
969 aOverride <<= (sal_Int32)1;
970 pAny[ DFF_ANIM_OVERRIDE ] = &aOverride;
972 aRunTimeContext <<= (sal_Int32)1;
973 pAny[ DFF_ANIM_RUNTIMECONTEXT ] = &aRunTimeContext;
976 // the order is important
977 if ( pAny[ DFF_ANIM_NODE_TYPE ] )
979 if ( *pAny[ DFF_ANIM_NODE_TYPE ] >>= nNodeType )
981 sal_uInt32 nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK;
982 switch( nNodeType )
984 case ::com::sun::star::presentation::EffectNodeType::ON_CLICK : nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK; break;
985 case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_WITH_PREVIOUS; break;
986 case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS; break;
987 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : nPPTNodeType = DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE; break;
988 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : nPPTNodeType = DFF_ANIM_NODE_TYPE_TIMING_ROOT; break;
989 case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE: nPPTNodeType = DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ; break;
991 exportAnimPropertyuInt32( rStrm, DFF_ANIM_NODE_TYPE, nPPTNodeType, TRANSLATE_NONE );
994 sal_uInt32 nPresetId = 0;
995 sal_uInt32 nPresetSubType = 0;
996 sal_uInt32 nAPIPresetClass = EffectPresetClass::CUSTOM;
997 sal_uInt32 nPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
998 sal_Bool bPresetClass, bPresetId, bPresetSubType;
999 bPresetClass = bPresetId = bPresetSubType = sal_False;
1001 if ( pAny[ DFF_ANIM_PRESET_CLASS ] )
1003 if ( *pAny[ DFF_ANIM_PRESET_CLASS ] >>= nAPIPresetClass )
1005 sal_uInt8 nPPTPresetClass;
1006 switch( nAPIPresetClass )
1008 case EffectPresetClass::ENTRANCE : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_ENTRANCE; break;
1009 case EffectPresetClass::EXIT : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EXIT; break;
1010 case EffectPresetClass::EMPHASIS : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EMPHASIS; break;
1011 case EffectPresetClass::MOTIONPATH : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MOTIONPATH; break;
1012 case EffectPresetClass::OLEACTION : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_OLE_ACTION; break;
1013 case EffectPresetClass::MEDIACALL : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MEDIACALL; break;
1014 default :
1015 nPPTPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
1017 nPresetClass = nPPTPresetClass;
1018 bPresetClass = sal_True;
1021 if ( pAny[ DFF_ANIM_PRESET_ID ] )
1023 rtl::OUString sPreset;
1024 if ( *pAny[ DFF_ANIM_PRESET_ID ] >>= sPreset )
1026 if ( sPreset.match( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ppt_" ) ), 0 ) )
1028 sal_Int32 nLast = sPreset.lastIndexOf( '_' );
1029 if ( ( nLast != -1 ) && ( ( nLast + 1 ) < sPreset.getLength() ) )
1031 rtl::OUString aNumber( sPreset.copy( nLast + 1 ) );
1032 nPresetId = aNumber.toInt32();
1033 bPresetId = sal_True;
1036 else
1038 const preset_maping* p = gPresetMaping;
1039 while( p->mpStrPresetId && ((p->mnPresetClass != (sal_Int32)nAPIPresetClass) || !sPreset.equalsAscii( p->mpStrPresetId )) )
1040 p++;
1042 if( p->mpStrPresetId )
1044 nPresetId = p->mnPresetId;
1045 bPresetId = sal_True;
1051 if ( pAny[ DFF_ANIM_PRESET_SUB_TYPE ] )
1053 rtl::OUString sPresetSubType;
1054 if ( *pAny[ DFF_ANIM_PRESET_SUB_TYPE ] >>= sPresetSubType )
1056 nPresetSubType = ImplTranslatePresetSubType( nPresetClass, nPresetId, sPresetSubType );
1057 bPresetSubType = sal_True;
1060 if ( bPresetId )
1061 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_ID, nPresetId, TRANSLATE_NONE );
1062 if ( bPresetSubType )
1063 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_SUB_TYPE, nPresetSubType, TRANSLATE_NONE );
1064 if ( bPresetClass )
1065 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_CLASS, nPresetClass, TRANSLATE_NONE );
1067 if ( pAny[ DFF_ANIM_ID ] )
1069 // TODO DFF_ANIM_ID
1072 if ( pAny[ DFF_ANIM_AFTEREFFECT ] )
1074 sal_Bool bAfterEffect = sal_False;
1075 if ( *pAny[ DFF_ANIM_AFTEREFFECT ] >>= bAfterEffect )
1076 exportAnimPropertyByte( rStrm, DFF_ANIM_AFTEREFFECT, bAfterEffect, TRANSLATE_NONE );
1079 if ( pAny[ DFF_ANIM_RUNTIMECONTEXT ] )
1081 sal_Int32 nRunTimeContext = 0;
1082 if ( *pAny[ DFF_ANIM_RUNTIMECONTEXT ] >>= nRunTimeContext )
1083 exportAnimPropertyuInt32( rStrm, DFF_ANIM_RUNTIMECONTEXT, nRunTimeContext, TRANSLATE_NONE );
1085 if ( pAny[ DFF_ANIM_PATH_EDIT_MODE ] )
1087 // TODO DFF_ANIM_ID
1090 if( !xMaster.is() )
1092 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
1093 if( xColor.is() )
1095 // sal_uInt32 nColorSpace = xColor->getColorSpace() == AnimationColorSpace::RGB ? 0 : 1;
1096 // exportAnimPropertyuInt32( rStrm, DFF_ANIM_COLORSPACE, nColorSpace, TRANSLATE_NONE );
1098 sal_Bool bDirection = !xColor->getDirection();
1099 exportAnimPropertyuInt32( rStrm, DFF_ANIM_DIRECTION, bDirection, TRANSLATE_NONE );
1103 if ( pAny[ DFF_ANIM_OVERRIDE ] )
1105 sal_Int32 nOverride = 0;
1106 if ( *pAny[ DFF_ANIM_OVERRIDE ] >>= nOverride )
1107 exportAnimPropertyuInt32( rStrm, DFF_ANIM_OVERRIDE, nOverride, TRANSLATE_NONE );
1110 if ( pAny[ DFF_ANIM_MASTERREL ] )
1112 sal_Int32 nMasterRel = 0;
1113 if ( *pAny[ DFF_ANIM_MASTERREL ] >>= nMasterRel )
1114 exportAnimPropertyuInt32( rStrm, DFF_ANIM_MASTERREL, nMasterRel, TRANSLATE_NONE );
1117 /* todo
1118 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1119 if( xAudio.is() )
1121 sal_Int16 nEndAfterSlide = 0;
1122 nEndAfterSlide = xAudio->getEndAfterSlide();
1123 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1126 Reference< XAnimate > xAnim( xNode, UNO_QUERY );
1127 if( xAnim.is() )
1129 // TODO: DFF_ANIM_TIMEFILTER
1131 if ( pAny[ DFF_ANIM_EVENT_FILTER ] )
1133 // TODO DFF_ANIM_EVENT_FILTER
1135 if ( pAny[ DFF_ANIM_VOLUME ] )
1137 // TODO DFF_ANIM_VOLUME
1139 return nNodeType;
1142 sal_Bool AnimationExporter::exportAnimProperty( SvStream& rStrm, const sal_uInt16 nPropertyId, const ::com::sun::star::uno::Any& rAny, const TranslateMode eTranslateMode )
1144 sal_Bool bRet = sal_False;
1145 if ( rAny.hasValue() )
1147 switch( rAny.getValueType().getTypeClass() )
1149 case ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT :
1150 case ::com::sun::star::uno::TypeClass_SHORT :
1151 case ::com::sun::star::uno::TypeClass_UNSIGNED_LONG :
1152 case ::com::sun::star::uno::TypeClass_LONG :
1154 sal_Int32 nVal = 0;
1155 if ( rAny >>= nVal )
1157 exportAnimPropertyuInt32( rStrm, nPropertyId, nVal, eTranslateMode );
1158 bRet = sal_True;
1161 break;
1163 case ::com::sun::star::uno::TypeClass_DOUBLE :
1165 double fVal = 0.0;
1166 if ( rAny >>= fVal )
1168 exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
1169 bRet = sal_True;
1172 break;
1173 case ::com::sun::star::uno::TypeClass_FLOAT :
1175 float fVal = 0.0;
1176 if ( rAny >>= fVal )
1178 if ( eTranslateMode & TRANSLATE_NUMBER_TO_STRING )
1180 Any aAny;
1181 rtl::OUString aNumber( rtl::OUString::valueOf( fVal ) );
1182 aAny <<= aNumber;
1183 exportAnimPropertyString( rStrm, nPropertyId, aNumber, eTranslateMode );
1185 else
1187 exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
1188 bRet = sal_True;
1192 break;
1193 case ::com::sun::star::uno::TypeClass_STRING :
1195 rtl::OUString aStr;
1196 if ( rAny >>= aStr )
1198 exportAnimPropertyString( rStrm, nPropertyId, aStr, eTranslateMode );
1199 bRet = sal_True;
1202 break;
1203 default:
1204 break;
1207 return bRet;
1209 void AnimationExporter::exportAnimPropertyString( SvStream& rStrm, const sal_uInt16 nPropertyId, const rtl::OUString& rVal, const TranslateMode eTranslateMode )
1211 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1212 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_UNISTRING;
1213 rStrm << nType;
1214 rtl::OUString aStr( rVal );
1215 if ( eTranslateMode != TRANSLATE_NONE )
1216 ImplTranslateAttribute( aStr, eTranslateMode );
1217 writeZString( rStrm, aStr );
1220 void AnimationExporter::exportAnimPropertyFloat( SvStream& rStrm, const sal_uInt16 nPropertyId, const double& rVal, const TranslateMode )
1222 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1223 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_FLOAT;
1224 float fFloat = (float)rVal;
1225 rStrm << nType
1226 << fFloat;
1229 void AnimationExporter::exportAnimPropertyuInt32( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt32 nVal, const TranslateMode )
1231 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1232 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_INT32 ;
1233 rStrm << nType
1234 << nVal;
1237 void AnimationExporter::exportAnimPropertyByte( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt8 nVal, const TranslateMode )
1239 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1240 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_BYTE;
1241 rStrm << nType
1242 << nVal;
1245 void AnimationExporter::writeZString( SvStream& rStrm, const rtl::OUString& rVal )
1247 sal_Int32 i;
1248 for ( i = 0; i < rVal.getLength(); i++ )
1249 rStrm << rVal[ i ];
1250 rStrm << (sal_Unicode)0;
1253 void AnimationExporter::exportAnimAction( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1255 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAction );
1257 sal_Int32 nConcurrent = 1;
1258 sal_Int32 nNextAction = 1;
1259 sal_Int32 nEndSync = 0;
1260 sal_Int32 nU4 = 0;
1261 sal_Int32 nU5 = 3;
1263 sal_Int16 nAnimationEndSync = 0;
1264 if ( xNode->getEndSync() >>= nAnimationEndSync )
1266 if ( nAnimationEndSync == AnimationEndSync::ALL )
1267 nEndSync = 1;
1269 rStrm << nConcurrent
1270 << nNextAction
1271 << nEndSync
1272 << nU4
1273 << nU5;
1277 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1278 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1279 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
1280 void AnimationExporter::exportAnimEvent( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Int32 nFlags )
1282 sal_uInt16 i;
1283 for ( i = 0; i < 4; i++ )
1285 sal_Int32 nU1 = 0;
1286 sal_Int32 nTrigger = 0;
1287 sal_Int32 nU3 = 0;
1288 sal_Int32 nBegin = 0;
1290 sal_Bool bCreateEvent = sal_False;
1291 Any aSource;
1293 switch( i )
1295 case 0 :
1296 case 1 :
1298 Any aAny;
1299 Event aEvent;
1300 com::sun::star::animations::Timing eTiming;
1301 if ( i == 0 )
1303 if ( nFlags & 0x20 )
1305 // taking the first child
1306 Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
1307 Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
1308 if ( xE.is() && xE->hasMoreElements() )
1310 // while( xE->hasMoreElements() )
1312 Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
1313 aAny = xClickNode->getBegin();
1317 else if ( nFlags & 0x40 )
1319 // begin has to be replaced with void, so don't do anything
1321 else
1323 aAny = xNode->getBegin();
1324 if ( nFlags & 0x10 ) // replace ON_NEXT with IDEFINITE
1326 if ( ( aAny >>= aEvent ) && ( aEvent.Trigger == EventTrigger::ON_NEXT ) )
1328 eTiming = Timing_INDEFINITE;
1329 aAny <<= eTiming;
1334 else
1335 aAny = xNode->getEnd();
1337 double fTiming = 0.0;
1338 if ( aAny >>= aEvent )
1340 bCreateEvent = sal_True;
1341 switch( aEvent.Trigger )
1343 case EventTrigger::NONE : nTrigger = 0; break;
1344 case EventTrigger::ON_BEGIN : nTrigger = 1; break;
1345 case EventTrigger::ON_END : nTrigger = 2; break;
1346 case EventTrigger::BEGIN_EVENT : nTrigger = 3; break;
1347 case EventTrigger::END_EVENT : nTrigger = 4; nU1 = 2; nU3 = mnCurrentGroup; break;
1348 case EventTrigger::ON_CLICK : nTrigger = 5; break;
1349 case EventTrigger::ON_DBL_CLICK : nTrigger = 6; break;
1350 case EventTrigger::ON_MOUSE_ENTER : nTrigger = 7; break;
1351 case EventTrigger::ON_MOUSE_LEAVE : nTrigger = 8; break;
1352 case EventTrigger::ON_NEXT : nTrigger = 9; break;
1353 case EventTrigger::ON_PREV : nTrigger = 10; break;
1354 case EventTrigger::ON_STOP_AUDIO : nTrigger = 11; break;
1356 if ( aEvent.Offset.hasValue() )
1358 if ( aEvent.Offset >>= eTiming )
1360 if ( eTiming == Timing_INDEFINITE )
1361 nBegin = -1;
1363 else if ( aEvent.Offset >>= fTiming )
1364 nBegin = (sal_Int32)( fTiming * 1000.0 );
1366 aSource = aEvent.Source;
1368 else if ( aAny >>= eTiming )
1370 bCreateEvent = sal_True;
1371 if ( eTiming == Timing_INDEFINITE )
1372 nBegin = -1;
1374 else if ( aAny >>= fTiming )
1376 bCreateEvent = sal_True;
1377 if ( eTiming == Timing_INDEFINITE )
1378 nBegin = (sal_Int32)( fTiming * 1000.0 );
1381 break;
1383 case 2 :
1385 if ( nFlags & ( 1 << i ) )
1387 bCreateEvent = sal_True;
1388 nU1 = 1;
1389 nTrigger = 9;
1392 break;
1393 case 3 :
1395 if ( nFlags & ( 1 << i ) )
1397 bCreateEvent = sal_True;
1398 nU1 = 1;
1399 nTrigger = 10;
1402 break;
1404 if ( bCreateEvent )
1406 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, i + 1 );
1408 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
1409 rStrm << nU1
1410 << nTrigger
1411 << nU3
1412 << nBegin;
1414 exportAnimateTargetElement( rStrm, aSource, ( nFlags & ( 1 << i ) ) != 0 );
1419 Any AnimationExporter::convertAnimateValue( const Any& rSourceValue, const rtl::OUString& rAttributeName ) const
1421 rtl::OUString aDest;
1422 if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "X" ) )
1423 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Y" ) )
1424 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Width" ) )
1425 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Height" ) )
1428 rtl::OUString aStr;
1429 if ( rSourceValue >>= aStr )
1431 ImplTranslateAttribute( aStr, TRANSLATE_MEASURE );
1432 aDest += aStr;
1435 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Rotate" ) ) // "r" or "style.rotation" ?
1436 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SkewX" ) )
1437 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Opacity" ) )
1438 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharHeight" ) )
1441 double fNumber = 0.0;
1442 if ( rSourceValue >>= fNumber )
1443 aDest += rtl::OUString::valueOf( fNumber );
1445 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Color" ) )
1446 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FillColor" ) ) // "Fillcolor" or "FillColor" ?
1447 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "LineColor" ) )
1448 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharColor" ) )
1451 sal_Int32 nColor = 0;
1452 Sequence< double > aHSL( 3 );
1453 rtl::OUString aP( RTL_CONSTASCII_USTRINGPARAM( "," ) );
1454 if ( rSourceValue >>= aHSL )
1456 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hsl(" ) );
1457 aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 0 ] / ( 360.0 / 255 ) ) );
1458 aDest += aP;
1459 aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 1 ] * 255.0 ) );
1460 aDest += aP;
1461 aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 2 ] * 255.0 ) );
1462 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
1464 else if ( rSourceValue >>= nColor )
1466 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "rgb(" ) );
1467 aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)nColor ) );
1468 aDest += aP;
1469 aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 8 ) ) );
1470 aDest += aP;
1471 aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 16 ) ) );
1472 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
1475 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FillStyle" ) ) )
1477 ::com::sun::star::drawing::FillStyle eFillStyle;
1478 if ( rSourceValue >>= eFillStyle )
1480 if ( eFillStyle == ::com::sun::star::drawing::FillStyle_NONE )
1481 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "none" ) ); // ?
1482 else
1483 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "solid" ) );
1486 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "LineStyle" ) ) )
1488 ::com::sun::star::drawing::LineStyle eLineStyle;
1489 if ( rSourceValue >>= eLineStyle )
1491 if ( eLineStyle == ::com::sun::star::drawing::LineStyle_NONE )
1492 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
1493 else
1494 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
1497 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharWeight" ) ) )
1499 float fFontWeight = 0.0;
1500 if ( rSourceValue >>= fFontWeight )
1502 if ( fFontWeight == com::sun::star::awt::FontWeight::BOLD )
1503 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "bold" ) );
1504 else
1505 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "normal" ) );
1508 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharUnderline" ) ) )
1510 sal_Int16 nFontUnderline = 0;
1511 if ( rSourceValue >>= nFontUnderline )
1513 if ( nFontUnderline == com::sun::star::awt::FontUnderline::NONE )
1514 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
1515 else
1516 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
1519 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharPosture" ) ) )
1521 ::com::sun::star::awt::FontSlant eFontSlant;
1522 if ( rSourceValue >>= eFontSlant )
1524 if ( eFontSlant == com::sun::star::awt::FontSlant_ITALIC )
1525 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "italic" ) );
1526 else
1527 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "normal" ) ); // ?
1530 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Visibility" ) ) )
1532 sal_Bool bVisible = sal_True;
1533 if ( rSourceValue >>= bVisible )
1535 if ( bVisible )
1536 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "visible" ) );
1537 else
1538 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hidden" ) );
1541 Any aRet;
1542 if ( aDest.getLength() )
1543 aRet <<= aDest;
1544 else
1545 aRet = rSourceValue;
1546 return aRet;
1549 void AnimationExporter::exportAnimateSet( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
1551 Reference< XAnimateSet > xSet( xNode, UNO_QUERY );
1552 if( xSet.is() )
1554 EscherExContainer aAnimateSet( rStrm, DFF_msofbtAnimateSet, 0 );
1556 EscherExAtom aAnimateSetData( rStrm, DFF_msofbtAnimateSetData );
1557 sal_uInt32 nId1 = 1; // ??
1558 sal_uInt32 nId2 = 1; // ??
1559 rStrm << nId1 << nId2;
1561 Any aConvertedValue( convertAnimateValue( xSet->getTo(), xSet->getAttributeName() ) );
1562 if ( aConvertedValue.hasValue() )
1563 exportAnimProperty( rStrm, 1, aConvertedValue, TRANSLATE_NONE );
1564 exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
1568 sal_uInt32 GetValueTypeForAttributeName( const rtl::OUString& rAttributeName )
1570 sal_uInt32 nValueType = 0;
1573 AnimationValueType::STRING == 0;
1574 AnimationValueType::NUMBER == 1;
1575 AnimationValueType::COLOR == 2;
1578 struct Entry
1580 const sal_Char* pName;
1581 sal_uInt8 nType;
1583 static const Entry lcl_attributeMap[] =
1585 { "charcolor", 2 },
1586 { "charfontname", 0 },
1587 { "charheight", 1 },
1588 { "charposture", 0 },
1589 // TODO(Q1): This should prolly be changed in PPT import
1590 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1591 { "charrotation", 1 },
1592 { "charunderline", 0 },
1593 { "charweight", 0 },
1594 { "color", 2 },
1595 { "dimcolor", 2 },
1596 { "fillcolor", 2 },
1597 { "fillstyle", 0 },
1598 { "height", 1 },
1599 { "linecolor", 2 },
1600 { "linestyle", 0 },
1601 { "opacity", 0 },
1602 { "rotate", 1 },
1603 { "skewx", 1 },
1604 { "skewy", 1 },
1605 { "visibility", 1 },
1606 { "width", 1 },
1607 { "x", 1 },
1608 { "y", 1 },
1609 { NULL, 0 }
1611 const Entry* pPtr = &lcl_attributeMap[ 0 ];
1612 while( pPtr->pName )
1614 if ( rAttributeName.equalsIgnoreAsciiCaseAscii( pPtr->pName ) )
1616 nValueType = pPtr->nType;
1617 break;
1619 pPtr++;
1621 DBG_ASSERT( pPtr->pName, "GetValueTypeForAttributeName, unknown property value!" );
1622 return nValueType;
1625 void AnimationExporter::exportAnimate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1627 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
1628 if ( xAnimate.is() )
1630 Any aBy ( xAnimate->getBy() );
1631 Any aFrom( xAnimate->getFrom() );
1632 Any aTo ( xAnimate->getTo() );
1634 EscherExContainer aContainer( rStrm, DFF_msofbtAnimate, 0 );
1636 EscherExAtom aAnimateData( rStrm, DFF_msofbtAnimateData );
1637 sal_uInt32 nBits = 0x38;
1638 sal_Int16 nTmp = xAnimate->getCalcMode();
1639 sal_uInt32 nCalcMode = /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp == AnimationCalcMode::LINEAR) ? 1 : 0;
1640 nTmp = xAnimate->getValueType();
1641 sal_uInt32 nValueType = GetValueTypeForAttributeName( xAnimate->getAttributeName() );
1643 if ( aBy.hasValue() )
1644 nBits |= 1;
1645 if ( aFrom.hasValue() )
1646 nBits |= 2;
1647 if ( aTo.hasValue() )
1648 nBits |= 4;
1650 rStrm << nCalcMode
1651 << nBits
1652 << nValueType;
1654 if ( aBy.hasValue() )
1655 exportAnimProperty( rStrm, 1, aBy, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1656 if ( aFrom.hasValue() )
1657 exportAnimProperty( rStrm, 2, aFrom, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1658 if ( aTo.hasValue() )
1659 exportAnimProperty( rStrm, 3, aTo, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1661 exportAnimateKeyPoints( rStrm, xAnimate );
1662 exportAnimateTarget( rStrm, xNode );
1666 void AnimationExporter::exportAnimateTarget( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_uInt32 nForceAttributeNames, int nAfterEffectType )
1668 EscherExContainer aAnimateTarget( rStrm, DFF_msofbtAnimateTarget, 0 );
1669 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
1670 if ( xAnimate.is() )
1673 EscherExAtom aAnimateTargetSettings( rStrm, DFF_msofbtAnimateTargetSettings, 0 );
1674 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1675 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1676 // nAccumulate 0 = none, 1 = always
1677 // nTransformType 0: "property" else "image"
1678 sal_uInt32 nBits = 0;
1679 sal_uInt32 nAdditive = 0;
1680 sal_uInt32 nAccumulate = 0;
1681 sal_uInt32 nTransformType = 0;
1682 if ( xAnimate.is() )
1684 if ( xAnimate->getAttributeName().getLength() )
1685 nBits |= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1686 sal_Int16 nAdditiveMode = xAnimate->getAdditive();
1687 if ( nAdditiveMode != AnimationAdditiveMode::BASE )
1689 nBits |= 1;
1690 switch( nAdditiveMode )
1692 case AnimationAdditiveMode::SUM : nAdditive = 1; break;
1693 case AnimationAdditiveMode::REPLACE : nAdditive = 2; break;
1694 case AnimationAdditiveMode::MULTIPLY : nAdditive = 3; break;
1695 case AnimationAdditiveMode::NONE : nAdditive = 4; break;
1698 if ( xAnimate->getAccumulate() )
1700 nBits |= 2;
1701 nAccumulate = 1;
1704 rStrm << nBits
1705 << nAdditive
1706 << nAccumulate
1707 << nTransformType;
1709 if ( xAnimate->getAttributeName().getLength() || nForceAttributeNames )
1711 EscherExContainer aAnimateAttributeNames( rStrm, DFF_msofbtAnimateAttributeNames, 1 );
1712 rtl::OUString aAttributeName( xAnimate->getAttributeName() );
1713 if ( nForceAttributeNames )
1715 switch( nForceAttributeNames )
1717 case 1 : aAttributeName = rtl::OUString::createFromAscii( "r" ); break;
1720 sal_Int32 nIndex = 0;
1723 OUString aToken( aAttributeName.getToken( 0, ';', nIndex ) );
1724 exportAnimPropertyString( rStrm, 0, aToken, TRANSLATE_ATTRIBUTE );
1726 while ( nIndex >= 0 );
1729 if( nAfterEffectType != AFTEREFFECT_NONE )
1731 EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
1732 exportAnimPropertyuInt32( rStrm, 6, 1, TRANSLATE_NONE );
1733 if( nAfterEffectType == AFTEREFFECT_COLOR )
1735 exportAnimPropertyuInt32( rStrm, 4, 0, TRANSLATE_NONE );
1736 exportAnimPropertyuInt32( rStrm, 5, 0, TRANSLATE_NONE );
1739 exportAnimateTargetElement( rStrm, aTarget.hasValue() ? aTarget : xAnimate->getTarget(), sal_False );
1743 void AnimationExporter::exportAnimateTargetElement( SvStream& rStrm, const Any aAny, const sal_Bool bCreate2b01Atom )
1745 Reference< XShape > xShape;
1746 aAny >>= xShape;
1747 sal_uInt32 nRefMode = 0; // nRefMode == 2 -> Paragraph
1748 sal_Int32 begin = -1;
1749 sal_Int32 end = -1;
1751 if( !xShape.is() )
1753 ParagraphTarget aParaTarget;
1754 if( aAny >>= aParaTarget )
1755 xShape = aParaTarget.Shape;
1756 if ( xShape.is() )
1758 // now calculating the character range for the paragraph
1759 sal_Int16 nParagraph = aParaTarget.Paragraph;
1760 Reference< XSimpleText > xText( xShape, UNO_QUERY );
1761 if ( xText.is() )
1763 nRefMode = 2;
1764 Reference< XEnumerationAccess > xTextParagraphEnumerationAccess( xText, UNO_QUERY );
1765 if ( xTextParagraphEnumerationAccess.is() )
1767 Reference< XEnumeration > xTextParagraphEnumeration( xTextParagraphEnumerationAccess->createEnumeration() );
1768 if ( xTextParagraphEnumeration.is() )
1770 sal_Int16 nCurrentParagraph;
1771 begin = end = nCurrentParagraph = 0;
1772 while ( xTextParagraphEnumeration->hasMoreElements() )
1774 Reference< XTextRange > xTextRange( xTextParagraphEnumeration->nextElement(), UNO_QUERY );
1775 if ( xTextRange.is() )
1777 rtl::OUString aParaText( xTextRange->getString() );
1778 sal_Int32 nLength = aParaText.getLength() + 1;
1779 end += nLength;
1780 if ( nCurrentParagraph == nParagraph )
1781 break;
1782 nCurrentParagraph++;
1783 begin += nLength;
1791 if ( xShape.is() || bCreate2b01Atom )
1793 EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
1794 if ( xShape.is() )
1796 EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
1798 sal_uInt32 nRefType = 1; // TODO: nRefType == 2 -> Sound;
1799 sal_uInt32 nRefId = ((EscherSolverContainer&)mrSolverContainer).GetShapeId( xShape );
1801 rStrm << nRefMode
1802 << nRefType
1803 << nRefId
1804 << begin
1805 << end;
1807 if ( bCreate2b01Atom )
1809 EscherExAtom a2b01Atom( rStrm, 0x2b01 );
1810 rStrm << (sal_uInt32)1; // ?
1815 void AnimationExporter::exportAnimateKeyPoints( SvStream& rStrm, const Reference< XAnimate >& xAnimate )
1817 Sequence< double > aKeyTimes( xAnimate->getKeyTimes() );
1818 Sequence< Any > aValues( xAnimate->getValues() );
1819 OUString aFormula( xAnimate->getFormula() );
1820 if ( aKeyTimes.getLength() )
1822 EscherExContainer aAnimKeyPoints( rStrm, DFF_msofbtAnimKeyPoints );
1823 sal_Int32 i;
1824 for ( i = 0; i < aKeyTimes.getLength(); i++ )
1827 EscherExAtom aAnimKeyTime( rStrm, DFF_msofbtAnimKeyTime );
1828 sal_Int32 nKeyTime = (sal_Int32)( aKeyTimes[ i ] * 1000.0 );
1829 rStrm << nKeyTime;
1831 Any aAny[ 2 ];
1832 if ( aValues[ i ].hasValue() )
1834 ValuePair aPair;
1835 if ( aValues[ i ] >>= aPair )
1837 aAny[ 0 ] = convertAnimateValue( aPair.First, xAnimate->getAttributeName() );
1838 aAny[ 1 ] = convertAnimateValue( aPair.Second, xAnimate->getAttributeName() );
1840 else
1842 aAny[ 0 ] = convertAnimateValue( aValues[ i ], xAnimate->getAttributeName() );
1844 if ( !i && aFormula.getLength() )
1846 ImplTranslateAttribute( aFormula, TRANSLATE_MEASURE );
1847 aAny[ 1 ] <<= aFormula;
1849 exportAnimProperty( rStrm, 0, aAny[ 0 ], TRANSLATE_NONE );
1850 exportAnimProperty( rStrm, 1, aAny[ 1 ], TRANSLATE_NONE );
1856 void AnimationExporter::exportAnimValue( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Bool bExportAlways )
1858 Any aAny;
1859 // repeat count (0)
1860 double fRepeat = 0.0;
1861 float fRepeatCount = 0.0;
1862 com::sun::star::animations::Timing eTiming;
1863 aAny = xNode->getRepeatCount();
1864 if ( aAny >>= eTiming )
1866 if ( eTiming == Timing_INDEFINITE )
1867 fRepeatCount = ((float)3.40282346638528860e+38);
1869 else if ( aAny >>= fRepeat )
1870 fRepeatCount = (float)fRepeat;
1871 if ( fRepeatCount != 0.0 )
1873 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1874 sal_uInt32 nType = 0;
1875 rStrm << nType
1876 << fRepeatCount;
1878 // accelerate (3)
1879 float fAccelerate = (float)xNode->getAcceleration();
1880 if ( bExportAlways || ( fAccelerate != 0.0 ) )
1882 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1883 sal_uInt32 nType = 3;
1884 rStrm << nType
1885 << fAccelerate;
1888 // decelerate (4)
1889 float fDecelerate = (float)xNode->getDecelerate();
1890 if ( bExportAlways || ( fDecelerate != 0.0 ) )
1892 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1893 sal_uInt32 nType = 4;
1894 rStrm << nType
1895 << fDecelerate;
1898 // autoreverse (5)
1899 sal_Bool bAutoReverse = xNode->getAutoReverse();
1900 if ( bExportAlways || bAutoReverse )
1902 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1903 sal_uInt32 nType = 5;
1904 sal_uInt32 nVal = bAutoReverse ? 1 : 0;
1905 rStrm << nType
1906 << nVal;
1910 void AnimationExporter::exportTransitionFilter( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1912 Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY );
1913 if ( xFilter.is() )
1915 EscherExContainer aAnimateFilter( rStrm, DFF_msofbtAnimateFilter );
1917 EscherExAtom aAnimateFilterData( rStrm, DFF_msofbtAnimateFilterData );
1918 sal_uInt32 nBits = 3; // bit 0 -> use AnimAttributeValue
1919 // bit 1 -> use nTransition
1921 sal_uInt32 nTransition = xFilter->getMode() ? 0 : 1;
1922 rStrm << nBits
1923 << nTransition;
1925 const sal_Char* pFilter = transition::find( xFilter->getTransition(), xFilter->getSubtype(), xFilter->getDirection() );
1926 if ( pFilter )
1928 const OUString aStr( OUString::createFromAscii( pFilter ) );
1929 exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
1931 exportAnimateTarget( rStrm, xNode );
1935 void AnimationExporter::exportAnimateMotion( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1937 Reference< XAnimateMotion > xMotion( xNode, UNO_QUERY );
1938 if ( xMotion.is() )
1940 EscherExContainer aAnimateMotion( rStrm, DFF_msofbtAnimateMotion );
1942 { //SJ: Ignored from import filter
1943 EscherExAtom aAnimateMotionData( rStrm, DFF_msofbtAnimateMotionData );
1944 sal_uInt32 nBits = 0x98;
1945 sal_uInt32 nOrigin = 0x2;
1946 float fByX = 100.0; // nBits&1
1947 float fByY = 100.0; // nBits&1
1948 float fFromX = 0.0; // nBits&2
1949 float fFromY = 0.0; // nBits&2
1950 float fToX = 100.0; // nBits&4
1951 float fToY = 100.0; // nBits&4
1952 rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nOrigin;
1954 /* ?
1956 EscherExAtom aF137( rStrm, 0xf137 );
1959 OUString aStr;
1960 if ( xMotion->getPath() >>= aStr )
1962 if ( aStr.getLength() )
1963 exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
1965 exportAnimateTarget( rStrm, xNode );
1970 void AnimationExporter::exportAnimateTransform( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1972 Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY );
1973 if ( xTransform.is() )
1975 if ( xTransform->getTransformType() == AnimationTransformType::SCALE )
1977 EscherExContainer aAnimateScale( rStrm, DFF_msofbtAnimateScale );
1979 EscherExAtom aAnimateScaleData( rStrm, DFF_msofbtAnimateScaleData );
1980 sal_uInt32 nBits = 0;
1981 sal_uInt32 nZoomContents = 1;
1982 float fByX = 100.0;
1983 float fByY = 100.0;
1984 float fFromX = 0.0;
1985 float fFromY = 0.0;
1986 float fToX = 100.0;
1987 float fToY = 100.0;
1989 double fX = 0.0, fY = 0.0;
1990 ValuePair aPair;
1991 if ( xTransform->getBy() >>= aPair )
1993 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
1995 nBits |= 1;
1996 fByX = (float)( fX * 100 );
1997 fByY = (float)( fY * 100 );
2000 if ( xTransform->getFrom() >>= aPair )
2002 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
2004 nBits |= 2;
2005 fFromX = (float)( fX * 100 );
2006 fFromY = (float)( fY * 100 );
2009 if( xTransform->getTo() >>= aPair )
2011 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
2013 nBits |= 4;
2014 fToX = (float)( fX * 100 );
2015 fToY = (float)( fY * 100 );
2019 // TODO: ZoomContents:
2020 //if( nBits & 8 )
2021 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
2023 rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nZoomContents;
2025 exportAnimateTarget( rStrm, xNode );
2027 else if ( xTransform->getTransformType() == AnimationTransformType::ROTATE )
2029 EscherExContainer aAnimateRotation( rStrm, DFF_msofbtAnimateRotation );
2031 EscherExAtom aAnimateRotationData( rStrm, DFF_msofbtAnimateRotationData );
2032 sal_uInt32 nBits = 0;
2033 sal_uInt32 nU1 = 0;
2034 float fBy = 360.0;
2035 float fFrom = 0.0;
2036 float fTo = 360.0;
2038 double fVal = 0.0;
2039 if ( xTransform->getBy() >>= fVal )
2041 nBits |= 1;
2042 fBy = (float)fVal;
2044 if ( xTransform->getFrom() >>= fVal )
2046 nBits |= 2;
2047 fFrom = (float)fVal;
2049 if ( xTransform->getTo() >>= fVal )
2051 nBits |= 4;
2052 fTo = (float)fVal;
2054 rStrm << nBits << fBy << fFrom << fTo << nU1;
2056 exportAnimateTarget( rStrm, xNode, 1 );
2061 sal_Bool AnimationExporter::getColorAny( const Any& rAny, const sal_Int16 nColorSpace, sal_Int32& rMode, sal_Int32& rA, sal_Int32& rB, sal_Int32& rC ) const
2063 sal_Bool bIsColor = sal_True;
2065 rMode = 0;
2066 if ( nColorSpace == AnimationColorSpace::HSL )
2067 rMode = 1;
2069 sal_Int32 nColor = 0;
2070 Sequence< double > aHSL( 3 );
2071 if ( rAny >>= nColor ) // RGB color
2073 rA = (sal_uInt8)( nColor >> 24 );
2074 rB = (sal_uInt8)( nColor >> 8 );
2075 rC = (sal_uInt8)( nColor );
2077 else if ( rAny >>= aHSL ) // HSL
2079 rA = (sal_Int32) ( aHSL[ 0 ] * 255.0 / 360.0 );
2080 rB = (sal_Int32) ( aHSL[ 1 ] * 255.0 );
2081 rC = (sal_Int32) ( aHSL[ 2 ] * 255.0 );
2083 else
2084 bIsColor = sal_False;
2085 return bIsColor;
2088 void AnimationExporter::exportAnimateColor( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
2090 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
2091 if ( xColor.is() )
2093 EscherExContainer aAnimateColor( rStrm, DFF_msofbtAnimateColor );
2095 EscherExAtom aAnimateColorData( rStrm, DFF_msofbtAnimateColorData );
2096 sal_uInt32 nBits = 8;
2098 sal_Int32 nByMode, nByA, nByB, nByC;
2099 nByMode = nByA = nByB = nByC = 0;
2101 sal_Int32 nFromMode, nFromA, nFromB, nFromC;
2102 nFromMode = nFromA = nFromB = nFromC = 0;
2104 sal_Int32 nToMode, nToA, nToB, nToC;
2105 nToMode = nToA = nToB = nToC = 0;
2107 sal_Int16 nColorSpace = xColor->getColorInterpolation();
2109 Any aAny( xColor->getBy() );
2110 if ( aAny.hasValue() )
2112 if ( getColorAny( aAny, nColorSpace, nByMode, nByA, nByB, nByC ) )
2113 nBits |= 0x11;
2115 aAny = xColor->getFrom();
2116 if ( aAny.hasValue() )
2118 if ( getColorAny( aAny, nColorSpace, nFromMode, nFromA, nFromB, nFromC ) )
2119 nBits |= 0x12;
2121 aAny = xColor->getTo();
2122 if ( aAny.hasValue() )
2124 if ( getColorAny( aAny, nColorSpace, nToMode, nToA, nToB, nToC ) )
2125 nBits |= 0x14;
2127 rStrm << nBits
2128 << nByMode << nByA << nByB << nByC
2129 << nFromMode << nFromA << nFromB << nFromC
2130 << nToMode << nToA << nToB << nToC;
2132 exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
2136 void AnimationExporter::exportIterate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
2138 Reference< XIterateContainer > xIterate( xNode, UNO_QUERY );
2139 if ( xIterate.is() )
2141 EscherExAtom aAnimIteration( rStrm, DFF_msofbtAnimIteration );
2143 float fInterval = 10.0;
2144 sal_Int32 nTextUnitEffect = 0;
2145 sal_Int32 nU1 = 1;
2146 sal_Int32 nU2 = 1;
2147 sal_Int32 nU3 = 0xe;
2149 sal_Int16 nIterateType = xIterate->getIterateType();
2150 switch( nIterateType )
2152 case TextAnimationType::BY_WORD : nTextUnitEffect = 1; break;
2153 case TextAnimationType::BY_LETTER : nTextUnitEffect = 2; break;
2156 fInterval = (float)xIterate->getIterateInterval();
2158 // convert interval from absolute to percentage
2159 double fDuration = 0.0;
2161 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
2162 if( xEnumerationAccess.is() )
2164 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
2165 if( xEnumeration.is() )
2167 while( xEnumeration->hasMoreElements() )
2169 Reference< XAnimate > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
2170 if( xChildNode.is() )
2172 double fChildBegin = 0.0;
2173 double fChildDuration = 0.0;
2174 xChildNode->getBegin() >>= fChildBegin;
2175 xChildNode->getDuration() >>= fChildDuration;
2177 fChildDuration += fChildBegin;
2178 if( fChildDuration > fDuration )
2179 fDuration = fChildDuration;
2185 if( fDuration )
2186 fInterval = (float)(100.0 * fInterval / fDuration);
2188 rStrm << fInterval << nTextUnitEffect << nU1 << nU2 << nU3;
2189 aTarget = xIterate->getTarget();
2193 } // namespace ppt;