bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / filter / ppt / pptinanimations.cxx
blobd5ed3721c012e8c5093c586ddc4bd57d01eb5ef4
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/Command.hpp>
27 #include <com/sun/star/animations/EventTrigger.hpp>
28 #include <com/sun/star/animations/AnimationNodeType.hpp>
29 #include <com/sun/star/animations/AnimationTransformType.hpp>
30 #include <com/sun/star/animations/AnimationCalcMode.hpp>
31 #include <com/sun/star/animations/AnimationValueType.hpp>
32 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
33 #include <com/sun/star/animations/XIterateContainer.hpp>
34 #include <com/sun/star/animations/XAnimateSet.hpp>
35 #include <com/sun/star/animations/XAudio.hpp>
36 #include <com/sun/star/animations/XCommand.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/ValuePair.hpp>
42 #include <com/sun/star/animations/AnimationColorSpace.hpp>
43 #include <com/sun/star/presentation/EffectNodeType.hpp>
44 #include <com/sun/star/presentation/EffectPresetClass.hpp>
45 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
46 #include <com/sun/star/presentation/EffectCommands.hpp>
47 #include <com/sun/star/beans/NamedValue.hpp>
48 #include <com/sun/star/drawing/FillStyle.hpp>
49 #include <com/sun/star/drawing/LineStyle.hpp>
50 #include <com/sun/star/awt/FontWeight.hpp>
51 #include <com/sun/star/awt/FontUnderline.hpp>
52 #include <com/sun/star/awt/FontSlant.hpp>
53 #include <com/sun/star/container/XEnumerationAccess.hpp>
54 #include <com/sun/star/presentation/ParagraphTarget.hpp>
55 #include <com/sun/star/presentation/TextAnimationType.hpp>
56 #include <comphelper/processfactory.hxx>
57 #include <rtl/ustrbuf.hxx>
58 #include <rtl/math.hxx>
60 #include <vcl/vclenum.hxx>
61 #include <svx/svdotext.hxx>
62 #include <editeng/outlobj.hxx>
63 #include <editeng/editobj.hxx>
64 #include <pptinanimations.hxx>
65 #include <pptatom.hxx>
66 #include "pptin.hxx"
67 #include "randomnode.hxx"
68 #include <algorithm>
70 using ::std::map;
71 using ::com::sun::star::beans::NamedValue;
72 using ::com::sun::star::container::XEnumerationAccess;
73 using ::com::sun::star::container::XEnumeration;
74 using ::com::sun::star::lang::XMultiServiceFactory;
76 using namespace ::com::sun::star::uno;
77 using namespace ::com::sun::star::drawing;
78 using namespace ::com::sun::star::animations;
79 using namespace ::com::sun::star::presentation;
81 namespace ppt
84 const transition* transition::find( const OUString& rName )
86 const transition* p = gTransitions;
88 while( p->mpName )
90 if( rName.equalsAscii( p->mpName ) )
91 return p;
93 p++;
96 return NULL;
99 SvStream& operator>>(SvStream& rIn, AnimationNode& rNode )
101 rIn.ReadInt32( rNode.mnU1 );
102 rIn.ReadInt32( rNode.mnRestart );
103 rIn.ReadInt32( rNode.mnGroupType );
104 rIn.ReadInt32( rNode.mnFill );
105 rIn.ReadInt32( rNode.mnU3 );
106 rIn.ReadInt32( rNode.mnU4 );
107 rIn.ReadInt32( rNode.mnDuration );
108 rIn.ReadInt32( rNode.mnNodeType );
110 return rIn;
113 static bool convertMeasure( OUString& rString )
115 bool bRet = false;
117 const sal_Char* pSource[] = { "ppt_x", "ppt_y", "ppt_w", "ppt_h", NULL };
118 const sal_Char* pDest[] = { "x", "y", "width", "height", NULL };
119 sal_Int32 nIndex = 0;
121 const sal_Char** ps = pSource;
122 const sal_Char** pd = pDest;
124 while( *ps )
126 const OUString aSearch( OUString::createFromAscii( *ps ) );
127 while( (nIndex = rString.indexOf( aSearch, nIndex )) != -1 )
129 sal_Int32 nLength = aSearch.getLength();
130 if( nIndex && (rString[nIndex-1] == '#' ) )
132 nIndex--;
133 nLength++;
136 const OUString aNew( OUString::createFromAscii( *pd ) );
137 rString = rString.replaceAt( nIndex, nLength, aNew );
138 nIndex += aNew.getLength();
139 bRet = true;
141 ps++;
142 pd++;
145 return bRet;
148 bool PropertySet::hasProperty( sal_Int32 nProperty ) const
150 return maProperties.find( nProperty ) != maProperties.end();
153 Any PropertySet::getProperty( sal_Int32 nProperty ) const
155 PropertySetMap_t::const_iterator aIter( maProperties.find( nProperty ) );
156 if( aIter != maProperties.end() )
157 return (*aIter).second;
158 else
159 return Any();
162 /** this adds an any to another any.
163 if rNewValue is empty, rOldValue is returned.
164 if rOldValue is empty, rNewValue is returned.
165 if rOldValue contains a value, a sequence with rOldValue and rNewValue is returned.
166 if rOldValue contains a sequence, a new sequence with the old sequence and rNewValue is returned.
168 static Any addToSequence( const Any& rOldValue, const Any& rNewValue )
170 if( !rNewValue.hasValue() )
172 return rOldValue;
174 else if( !rOldValue.hasValue() )
176 return rNewValue;
178 else
180 Sequence< Any > aNewSeq;
181 if( rOldValue >>= aNewSeq )
183 sal_Int32 nSize = aNewSeq.getLength();
184 aNewSeq.realloc(nSize+1);
185 aNewSeq[nSize] = rNewValue;
187 else
189 aNewSeq.realloc(2);
190 aNewSeq[0] = rOldValue;
191 aNewSeq[1] = rNewValue;
193 return makeAny( aNewSeq );
197 AnimationImporter::AnimationImporter( ImplSdPPTImport* pPPTImport, SvStream& rStCtrl )
198 : mpPPTImport( pPPTImport ), mrStCtrl( rStCtrl )
202 int AnimationImporter::import( const Reference< XDrawPage >& xPage, const DffRecordHeader& rProgTagContentHd )
204 int nNodes = 0;
206 #ifdef DBG_ANIM_LOG
207 static int ppt_anim_debug_stream_number = 1;
208 OUString ppt_anim_debug_filename("ppt-animation-import-debug-output-");
209 ppt_anim_debug_filename += OUString::number(ppt_anim_debug_stream_number++);
210 ppt_anim_debug_filename += ".xml";
211 mpFile = fopen( OUStringToOString( ppt_anim_debug_filename, RTL_TEXTENCODING_UTF8).getStr() , "w+" );
212 #endif
213 dump("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
215 Reference< XAnimationNodeSupplier > xNodeSupplier( xPage, UNO_QUERY );
216 if( xNodeSupplier.is() )
218 mxRootNode = xNodeSupplier->getAnimationNode();
219 if( mxRootNode.is() )
221 Reference< XAnimationNode > xParent;
223 boost::scoped_ptr<Atom> pAtom(Atom::import( rProgTagContentHd, mrStCtrl ));
224 if( pAtom )
226 nNodes = importAnimationContainer( pAtom.get(), xParent );
229 processAfterEffectNodes();
233 #ifdef DBG_ANIM_LOG
234 fclose( mpFile );
235 #endif
237 return nNodes;
240 void AnimationImporter::processAfterEffectNodes()
242 std::for_each( maAfterEffectNodes.begin(), maAfterEffectNodes.end(), sd::stl_process_after_effect_node_func );
245 Reference< XAnimationNode > AnimationImporter::createNode( const Atom* pAtom, const AnimationNode& rNode )
247 const char* pServiceName = NULL;
249 switch( rNode.mnGroupType )
251 case mso_Anim_GroupType_PAR:
252 if( pAtom->hasChildAtom( DFF_msofbtAnimIteration ) )
253 pServiceName = "com.sun.star.animations.IterateContainer";
254 else
255 pServiceName = "com.sun.star.animations.ParallelTimeContainer";
256 break;
257 case mso_Anim_GroupType_SEQ:
258 pServiceName = "com.sun.star.animations.SequenceTimeContainer";
259 break;
260 case mso_Anim_GroupType_NODE:
262 switch( rNode.mnNodeType )
264 case mso_Anim_Behaviour_FILTER:
265 case mso_Anim_Behaviour_ANIMATION:
266 if( pAtom->hasChildAtom( DFF_msofbtAnimateSet ) )
267 pServiceName = "com.sun.star.animations.AnimateSet";
268 else if( pAtom->hasChildAtom( DFF_msofbtAnimateColor ) )
269 pServiceName = "com.sun.star.animations.AnimateColor";
270 else if( pAtom->hasChildAtom( DFF_msofbtAnimateScale ) )
271 pServiceName = "com.sun.star.animations.AnimateTransform";
272 else if( pAtom->hasChildAtom( DFF_msofbtAnimateRotation ) )
273 pServiceName = "com.sun.star.animations.AnimateTransform";
274 else if( pAtom->hasChildAtom( DFF_msofbtAnimateMotion ) )
275 pServiceName = "com.sun.star.animations.AnimateMotion";
276 else if( pAtom->hasChildAtom( DFF_msofbtAnimateFilter ) )
277 pServiceName = "com.sun.star.animations.TransitionFilter";
278 else if( pAtom->hasChildAtom( DFF_msofbtAnimCommand ) )
279 pServiceName = "com.sun.star.animations.Command";
280 else
281 pServiceName = "com.sun.star.animations.Animate";
282 break;
284 break;
286 case mso_Anim_GroupType_MEDIA:
287 pServiceName = "com.sun.star.animations.Audio";
288 break;
290 default:
291 pServiceName = "com.sun.star.animations.Animate";
292 break;
295 Reference< XAnimationNode > xNode;
296 if( pServiceName )
298 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
299 const OUString aServiceName( OUString::createFromAscii(pServiceName) );
300 Reference< XInterface > xFac( xContext->getServiceManager()->createInstanceWithContext(aServiceName, xContext) );
301 xNode.set(xFac , UNO_QUERY );
304 DBG_ASSERT( xNode.is(), "sd::AnimationImporter::createNode(), node creation failed!" );
305 return xNode;
308 static bool is_random( const AnimationNode& rNode, const PropertySet& rSet, sal_Int32& rPresetClass )
310 if( rNode.mnGroupType != mso_Anim_GroupType_PAR )
311 return false;
313 if( !rSet.hasProperty( DFF_ANIM_PRESET_ID ) || !rSet.hasProperty( DFF_ANIM_PRESET_CLASS ) )
314 return false;
316 sal_Int32 nPresetId = 0;
317 if( !(rSet.getProperty( DFF_ANIM_PRESET_ID ) >>= nPresetId) || (nPresetId != 24) )
318 return false;
320 sal_Int32 nPresetClass = 0;
321 if( !(rSet.getProperty( DFF_ANIM_PRESET_CLASS ) >>= nPresetClass) )
322 return false;
324 switch( nPresetClass )
326 case DFF_ANIM_PRESS_CLASS_ENTRANCE: rPresetClass = EffectPresetClass::ENTRANCE; return true;
327 case DFF_ANIM_PRESS_CLASS_EXIT: rPresetClass = EffectPresetClass::EXIT; return true;
329 return false;
332 int AnimationImporter::importAnimationContainer( const Atom* pAtom, const Reference< XAnimationNode >& xParent )
334 int nNodes = 0;
335 if( pAtom->seekToContent() )
337 AnimationNode aNode;
338 const Atom* pAnimationNodeAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimNode );
339 if( pAnimationNodeAtom && pAnimationNodeAtom->seekToContent() )
340 mrStCtrl >> aNode;
342 PropertySet aSet;
343 const Atom* pAnimationPropertySetAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimPropertySet );
344 if( pAnimationPropertySetAtom )
345 importPropertySetContainer( pAnimationPropertySetAtom, aSet );
347 Reference< XAnimationNode > xNode;
349 if( xParent.is() )
351 sal_Int32 nPresetClass;
352 if( is_random( aNode, aSet, nPresetClass ) )
354 // create a random animation node with the given preset class
355 xNode.set( sd::RandomAnimationNode_createInstance( (sal_Int16)nPresetClass ), UNO_QUERY );
358 if( !xNode.is() )
360 // create a node for the given atom
361 xNode = createNode( pAtom, aNode );
364 else
366 // if we have no parent we fill the root node
367 xNode = mxRootNode;
370 // import if we have a node and its not random
371 if( xNode.is() )
373 fillNode( xNode, aNode, aSet );
375 switch( aNode.mnGroupType )
377 case mso_Anim_GroupType_PAR:
379 dump( "<par" );
380 dump( aNode );
381 dump( aSet );
382 nNodes += importTimeContainer( pAtom, xNode );
383 dump( "</par>\n" );
385 // for iteration containers, map target from children to iteration
386 Reference< XIterateContainer > xIter( xNode, UNO_QUERY );
387 if( xIter.is() )
389 double fDuration = 0.0;
390 Any aTarget, aEmpty;
391 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
392 if( xEnumerationAccess.is() )
394 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
395 if( xEnumeration.is() )
397 while( xEnumeration->hasMoreElements() )
399 Reference< XAnimate > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
400 if( xChildNode.is() )
402 double fChildBegin = 0.0;
403 double fChildDuration = 0.0;
404 xChildNode->getBegin() >>= fChildBegin;
405 xChildNode->getDuration() >>= fChildDuration;
407 fChildDuration += fChildBegin;
408 if( fChildDuration > fDuration )
409 fDuration = fChildDuration;
411 if( !aTarget.hasValue() )
412 aTarget = xChildNode->getTarget();
414 xChildNode->setTarget( aEmpty );
420 xIter->setTarget( aTarget );
422 double fIterateInterval = xIter->getIterateInterval() * fDuration / 100;
423 xIter->setIterateInterval( fIterateInterval );
426 break;
428 case mso_Anim_GroupType_SEQ:
430 dump( "<seq" );
431 dump( aNode );
432 dump( aSet );
433 nNodes += importTimeContainer( pAtom, xNode );
434 dump( "</seq>\n" );
436 if( aSet.hasProperty( DFF_ANIM_NODE_TYPE ) )
438 sal_Int32 nPPTNodeType = 0;
439 if( aSet.getProperty( DFF_ANIM_NODE_TYPE ) >>= nPPTNodeType )
441 switch(nPPTNodeType)
443 case DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE:
444 fixMainSequenceTiming( xNode );
445 break;
446 case DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ:
447 fixInteractiveSequenceTiming( xNode );
448 break;
453 break;
455 case mso_Anim_GroupType_NODE:
457 #ifdef DBG_ANIM_LOG
458 if( pAtom->hasChildAtom( DFF_msofbtAnimateSet ) )
460 dump( "<set" );
462 else if( pAtom->hasChildAtom( DFF_msofbtAnimateColor ) )
464 dump( "<animateColor" );
466 else if( pAtom->hasChildAtom( DFF_msofbtAnimateScale ) )
468 dump( "<animateScale" );
470 else if( pAtom->hasChildAtom( DFF_msofbtAnimateRotation ) )
472 dump( "<animateRotation" );
474 else if( pAtom->hasChildAtom( DFF_msofbtAnimateMotion ) )
476 dump( "<animateMotion" );
478 else if( pAtom->hasChildAtom( DFF_msofbtAnimate ) )
480 dump( "<animate" );
482 else if( pAtom->hasChildAtom( DFF_msofbtAnimateFilter ) )
484 dump( "<animateFilter" );
486 else if( pAtom->hasChildAtom( DFF_msofbtAnimCommand ) )
488 dump( "<command" );
490 else
492 OSL_FAIL( "unknown node atom!" );
493 dump_atom_header( pAtom, true, false );
494 dump_atom( pAtom );
495 dump_atom_header( pAtom, false, false );
496 break;
498 dump( aNode );
499 dump( aSet );
500 #endif
501 int nANCNodes = importAnimationNodeContainer( pAtom, xNode );
502 if( !convertAnimationNode( xNode, xParent ) )
503 xNode = 0;
504 else
505 nNodes += nANCNodes;
506 dump( "/>\n");
509 break;
511 case mso_Anim_GroupType_MEDIA:
513 dump( "<audio" );
514 dump( aNode );
515 dump( aSet );
516 nNodes += importAudioContainer( pAtom, xNode );
517 dump( "</audio>\n" );
519 break;
521 default:
522 OSL_FAIL( "unknown group atom!" );
524 dump_atom_header( pAtom, true, false );
525 dump_atom( pAtom );
526 dump_atom_header( pAtom, false, false );
527 break;
532 if( xParent.is() && xNode.is() )
534 Reference< XTimeContainer > xParentContainer( xParent, UNO_QUERY );
535 DBG_ASSERT( xParentContainer.is(), "parent is no container, then why do I have a child here?" );
536 if( xParentContainer.is() )
538 xParentContainer->appendChild( xNode );
543 return nNodes;
546 void AnimationImporter::fixMainSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
550 bool bFirst = true;
551 Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
552 Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
553 while( xE->hasMoreElements() )
555 // click node
556 Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
558 Event aEvent;
559 aEvent.Trigger = EventTrigger::ON_NEXT;
560 aEvent.Repeat = 0;
561 xClickNode->setBegin( makeAny( aEvent ) );
563 if( bFirst )
565 bFirst = false;
566 Reference< XEnumerationAccess > xEA2( xClickNode, UNO_QUERY_THROW );
567 Reference< XEnumeration > xE2( xEA2->createEnumeration(), UNO_QUERY_THROW );
568 if( xE2->hasMoreElements() )
570 // with node
571 xE2->nextElement() >>= xEA2;
572 if( xEA2.is() )
573 xE2.set(xEA2->createEnumeration(), css::uno::UNO_QUERY);
574 else
575 xE2.clear();
577 if( xE2.is() && xE2->hasMoreElements() )
579 Reference< XAnimationNode > xEffectNode( xE2->nextElement(), UNO_QUERY_THROW );
580 const Sequence< NamedValue > aUserData( xEffectNode->getUserData() );
581 const NamedValue* p = aUserData.getConstArray();
582 sal_Int32 nLength = aUserData.getLength();
583 while( nLength-- )
585 if ( p->Name == "node-type" )
587 sal_Int16 nNodeType = 0;
588 p->Value >>= nNodeType;
589 if( nNodeType != ::com::sun::star::presentation::EffectNodeType::ON_CLICK )
591 // first effect does not start on click, so correct
592 // first click nodes begin to 0s
593 xClickNode->setBegin( makeAny( (double)0.0 ) );
594 break;
597 p++;
604 catch( Exception& )
606 OSL_FAIL("sd::AnimationImporter::fixMainSequenceTiming(), exception caught!" );
610 void AnimationImporter::fixInteractiveSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode )
614 Any aBegin( xNode->getBegin() );
615 Any aEmpty;
616 xNode->setBegin( aEmpty );
618 Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
619 Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
620 while( xE->hasMoreElements() )
622 // click node
623 Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
624 xClickNode->setBegin( aBegin );
627 catch( Exception& )
629 OSL_FAIL("sd::AnimationImporter::fixInteractiveSequenceTiming(), exception caught!" );
633 bool AnimationImporter::convertAnimationNode( const Reference< XAnimationNode >& xNode, const Reference< XAnimationNode >& xParent )
635 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
636 if( !xAnimate.is() )
637 return true;
639 if( !xAnimate->getTarget().hasValue() )
640 return false;
642 const sal_Int16 nNodeType = xNode->getType();
644 if( nNodeType == AnimationNodeType::TRANSITIONFILTER )
645 return true;
647 OUString aAttributeName( xAnimate->getAttributeName() );
649 if( (nNodeType == AnimationNodeType::SET) && aAttributeName == "fill.on" )
650 return false;
652 const ImplAttributeNameConversion* p = gImplConversionList;
654 MS_AttributeNames eAttribute = MS_UNKNOWN;
656 if( (nNodeType == AnimationNodeType::ANIMATEMOTION) ||
657 (nNodeType == AnimationNodeType::ANIMATETRANSFORM) )
659 OUString aEmpty;
660 aAttributeName = aEmpty;
662 else
664 while( p->mpMSName )
666 if( aAttributeName.equalsAscii( p->mpMSName ) )
667 break;
669 p++;
672 DBG_ASSERT( p->mpMSName || aAttributeName.isEmpty(), "sd::AnimationImporter::convertAnimationNode(), unknown attribute!" );
673 #ifdef DBG_ANIM_LOG
674 if( p->mpMSName == 0 ) dump( "<error text=\"sd::AnimationImporter::convertAnimationNode(), unknown attribute!\"/>\n" );
675 #endif
677 eAttribute = p->meAttribute;
679 if( p->mpAPIName )
680 aAttributeName = OUString::createFromAscii( p->mpAPIName );
683 xAnimate->setAttributeName( aAttributeName );
685 if( eAttribute != MS_UNKNOWN )
687 Any aAny( xAnimate->getFrom() );
688 if( aAny.hasValue() )
690 if( convertAnimationValue( eAttribute, aAny ) )
691 xAnimate->setFrom( aAny );
694 aAny = xAnimate->getBy();
695 if( aAny.hasValue() )
697 if( convertAnimationValue( eAttribute, aAny ) )
698 xAnimate->setBy( aAny );
701 aAny = xAnimate->getTo();
702 if( aAny.hasValue() )
704 if( convertAnimationValue( eAttribute, aAny ) )
705 xAnimate->setTo( aAny );
708 Sequence< Any > aValues( xAnimate->getValues() );
709 sal_Int32 nValues = aValues.getLength();
710 if( nValues )
712 Any* p2 = aValues.getArray();
713 while( nValues-- )
714 convertAnimationValue( eAttribute, *p2++ );
716 xAnimate->setValues( aValues );
719 OUString aFormula( xAnimate->getFormula() );
720 if( !aFormula.isEmpty() )
722 if( convertMeasure( aFormula ) )
723 xAnimate->setFormula( aFormula );
727 // check for after-affect
728 Sequence< NamedValue > aUserData( xNode->getUserData() );
729 NamedValue* pValue = aUserData.getArray();
730 NamedValue* pLastValue = pValue;
731 sal_Int32 nLength = aUserData.getLength(), nRemoved = 0;
733 bool bAfterEffect = false;
734 sal_Int32 nMasterRel = 0;
735 for( ; nLength--; pValue++ )
737 if ( pValue->Name == "after-effect" )
739 pValue->Value >>= bAfterEffect;
740 nRemoved++;
742 else if ( pValue->Name == "master-rel" )
744 pValue->Value >>= nMasterRel;
745 nRemoved++;
747 else
749 if( nRemoved )
750 *pLastValue = *pValue;
751 pLastValue++;
755 if( nRemoved )
757 aUserData.realloc( aUserData.getLength() - nRemoved );
758 xNode->setUserData( aUserData );
761 // if its an after effect node, add it to the list for
762 // later processing
763 // after effect nodes are not inserted at their import
764 // position, so return false in this case
765 if( bAfterEffect )
767 if( nMasterRel != 2 )
769 Event aEvent;
771 aEvent.Source <<= xParent;
772 aEvent.Trigger = EventTrigger::END_EVENT;
773 aEvent.Repeat = 0;
775 xNode->setBegin( makeAny( aEvent ) );
778 // add to after effect nodes for later processing
779 sd::AfterEffectNode aNode( xNode, xParent, nMasterRel == 2 );
780 maAfterEffectNodes.push_back( aNode );
781 return false;
784 return true;
787 static int lcl_gethex( int nChar )
789 if( nChar >= '0' && nChar <= '9' )
790 return nChar - '0';
791 else if( nChar >= 'a' && nChar <= 'f' )
792 return nChar - 'a' + 10;
793 else if( nChar >= 'A' && nChar <= 'F' )
794 return nChar - 'A' + 10;
795 else
796 return 0;
799 bool AnimationImporter::convertAnimationValue( MS_AttributeNames eAttribute, Any& rValue )
801 bool bRet = false;
802 switch( eAttribute )
804 case MS_PPT_X:
805 case MS_PPT_Y:
806 case MS_PPT_W:
807 case MS_PPT_H:
809 OUString aString;
811 if( rValue.getValueType() == cppu::UnoType<ValuePair>::get() )
813 ValuePair aValuePair;
814 if( rValue >>= aValuePair )
816 if( aValuePair.First >>= aString )
818 if( convertMeasure( aString ) )
820 aValuePair.First <<= aString;
821 bRet = true;
825 if( aValuePair.Second >>= aString )
827 if( convertMeasure( aString ) )
829 aValuePair.Second <<= aString;
830 bRet = true;
835 else if( rValue.getValueType() == cppu::UnoType<OUString>::get() )
837 if( rValue >>= aString )
839 bRet = convertMeasure( aString );
841 if( bRet )
842 rValue <<= aString;
846 break;
848 case MS_XSHEAR:
849 case MS_R:
851 OUString aString;
852 if( rValue >>= aString )
854 rValue <<= aString.toDouble();
855 bRet = true;
858 break;
860 case MS_STYLEROTATION:
862 if( rValue.getValueType() == cppu::UnoType<OUString>::get() )
864 OUString aString;
865 rValue >>= aString;
866 rValue <<= (sal_Int16)aString.toDouble();
867 bRet = true;
869 else if( rValue.getValueType() == cppu::UnoType<double>::get() )
871 double fValue = 0.0;
872 rValue >>= fValue;
873 rValue <<= (sal_Int16)fValue;
874 bRet = true;
877 break;
879 case MS_FILLCOLOR:
880 case MS_STROKECOLOR:
881 case MS_STYLECOLOR:
882 case MS_PPT_C:
884 OUString aString;
885 if( rValue >>= aString )
887 if( aString.getLength() >= 7 && aString[0] == '#' )
889 Color aColor;
890 aColor.SetRed( (sal_uInt8)(lcl_gethex( aString[1] ) * 16 + lcl_gethex( aString[2] )) );
891 aColor.SetGreen( (sal_uInt8)(lcl_gethex( aString[3] ) * 16 + lcl_gethex( aString[4] )) );
892 aColor.SetBlue( (sal_uInt8)(lcl_gethex( aString[5] ) * 16 + lcl_gethex( aString[6] )) );
893 rValue <<= (sal_Int32)aColor.GetColor();
894 bRet = true;
896 else if( aString.startsWith( "rgb(" ) )
898 aString = aString.copy( 4, aString.getLength() - 5 );
899 Color aColor;
900 sal_Int32 index = 0;
901 aColor.SetRed( (sal_uInt8)aString.getToken( 0, (sal_Unicode)',', index ).toInt32() );
902 aColor.SetGreen( (sal_uInt8)aString.getToken( 0, (sal_Unicode)',', index ).toInt32() );
903 aColor.SetRed( (sal_uInt8)aString.getToken( 0, (sal_Unicode)',', index ).toInt32() );
904 rValue <<= (sal_Int32)aColor.GetColor();
905 bRet = true;
907 else if( aString.startsWith( "hsl(" ) )
909 sal_Int32 index = 0;
910 sal_Int32 nA = aString.getToken( 0, (sal_Unicode)',', index ).toInt32();
911 sal_Int32 nB = aString.getToken( 0, (sal_Unicode)',', index ).toInt32();
912 sal_Int32 nC = aString.getToken( 0, (sal_Unicode)',', index ).toInt32();
913 dump( "hsl(%ld", nA );
914 dump( ",%ld", nB );
915 dump( ",%ld)", nC );
916 Sequence< double > aHSL( 3 );
917 aHSL[0] = nA * 360.0/255.0;
918 aHSL[1] = nB / 255.0;
919 aHSL[2] = nC / 255.0;
920 rValue <<= aHSL;
921 bRet = true;
925 break;
927 case MS_FILLTYPE:
929 OUString aString;
930 if( rValue >>= aString )
932 rValue <<= aString == "solid" ? FillStyle_SOLID : FillStyle_NONE;
933 bRet = true;
936 break;
938 case MS_STROKEON:
940 OUString aString;
941 if( rValue >>= aString )
943 rValue <<= aString == "true" ? ::com::sun::star::drawing::LineStyle_SOLID : ::com::sun::star::drawing::LineStyle_NONE;
944 bRet = true;
947 break;
949 case MS_FONTWEIGHT:
951 OUString aString;
952 if( rValue >>= aString )
954 rValue <<= aString == "bold" ? com::sun::star::awt::FontWeight::BOLD : com::sun::star::awt::FontWeight::NORMAL;
955 bRet = true;
958 break;
960 case MS_STYLEFONTSTYLE:
962 OUString aString;
963 if( rValue >>= aString )
965 rValue <<= aString == "italic" ? com::sun::star::awt::FontSlant_ITALIC : com::sun::star::awt::FontSlant_NONE;
966 bRet = true;
969 break;
971 case MS_STYLEUNDERLINE:
973 OUString aString;
974 if( rValue >>= aString )
976 rValue <<= aString == "true" ? com::sun::star::awt::FontUnderline::SINGLE : com::sun::star::awt::FontUnderline::NONE;
977 bRet = true;
980 break;
982 case MS_STYLEOPACITY:
983 case MS_STYLEFONTSIZE:
985 OUString aString;
986 if( rValue >>= aString )
988 rValue <<= (float)aString.toDouble();
989 bRet = true;
992 break;
994 case MS_STYLEVISIBILITY:
996 OUString aString;
997 if( rValue >>= aString )
999 rValue <<= aString == "visible" ? sal_True : sal_False;
1000 bRet = true;
1003 break;
1004 default:
1005 break;
1008 return bRet;
1011 static OUString getConvertedSubType( sal_Int16 nPresetClass, sal_Int32 nPresetId, sal_Int32 nPresetSubType )
1013 const sal_Char* pStr = 0;
1015 if( (nPresetClass == EffectPresetClass::ENTRANCE) || (nPresetClass == EffectPresetClass::EXIT) )
1017 // skip wheel effect
1018 if( nPresetId != 21 )
1020 if( nPresetId == 5 )
1022 // checkerboard
1023 switch( nPresetSubType )
1025 case 5: pStr = "downward"; break;
1026 case 10: pStr = "across"; break;
1029 else if( nPresetId == 17 )
1031 // stretch
1032 if( nPresetSubType == 10 )
1033 pStr = "across";
1035 else if( nPresetId == 18 )
1037 // strips
1038 switch( nPresetSubType )
1040 case 3: pStr = "right-to-top"; break;
1041 case 6: pStr = "right-to-bottom"; break;
1042 case 9: pStr = "left-to-top"; break;
1043 case 12: pStr = "left-to-bottom"; break;
1047 if( pStr == 0 )
1049 const convert_subtype* p = gConvertArray;
1051 while( p->mpStrSubType )
1053 if( p->mnID == nPresetSubType )
1055 pStr = p->mpStrSubType;
1056 break;
1058 p++;
1064 if( pStr )
1065 return OUString::createFromAscii( pStr );
1066 else
1067 return OUString::number( nPresetSubType );
1070 void AnimationImporter::fillNode( Reference< XAnimationNode >& xNode, const AnimationNode& rNode, const PropertySet& rSet )
1072 bool bAfterEffect = false;
1074 // attribute Restart
1075 if( rNode.mnRestart )
1077 sal_Int16 nRestart = AnimationRestart::DEFAULT;
1078 switch( rNode.mnRestart )
1080 case 1: nRestart = AnimationRestart::ALWAYS; break;
1081 case 2: nRestart = AnimationRestart::WHEN_NOT_ACTIVE; break;
1082 case 3: nRestart = AnimationRestart::NEVER; break;
1084 xNode->setRestart( nRestart );
1087 // attribute Fill
1088 if( rNode.mnFill )
1090 sal_Int16 nFill = AnimationFill::DEFAULT;
1091 switch( rNode.mnFill )
1093 case 1: nFill = AnimationFill::REMOVE; break;
1094 case 2: nFill = AnimationFill::FREEZE; break;
1095 case 3: nFill = AnimationFill::HOLD; break;
1096 case 4: nFill = AnimationFill::TRANSITION; break;
1098 xNode->setFill( nFill );
1101 // attribute Duration
1102 if( rNode.mnDuration )
1104 Any aDuration;
1105 if( rNode.mnDuration > 0 )
1107 aDuration <<= (double)(rNode.mnDuration / 1000.0);
1109 else if( rNode.mnDuration < 0 )
1111 aDuration <<= Timing_INDEFINITE;
1113 xNode->setDuration( aDuration );
1116 // TODO: DFF_ANIM_PATH_EDIT_MODE
1117 if( rSet.hasProperty( DFF_ANIM_PATH_EDIT_MODE ) )
1119 sal_Int32 nPathEditMode ;
1120 if( rSet.getProperty( DFF_ANIM_PATH_EDIT_MODE ) >>= nPathEditMode )
1125 // set user data
1126 Sequence< NamedValue > aUserData;
1128 // attribute Type
1129 if( rSet.hasProperty( DFF_ANIM_NODE_TYPE ) )
1131 sal_Int32 nPPTNodeType = 0;
1132 if( rSet.getProperty( DFF_ANIM_NODE_TYPE ) >>= nPPTNodeType )
1134 sal_Int16 nNodeType = ::com::sun::star::presentation::EffectNodeType::DEFAULT;
1135 switch( nPPTNodeType )
1137 case DFF_ANIM_NODE_TYPE_ON_CLICK: nNodeType = ::com::sun::star::presentation::EffectNodeType::ON_CLICK; break;
1138 case DFF_ANIM_NODE_TYPE_WITH_PREVIOUS: nNodeType = ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS; break;
1139 case DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS: nNodeType = ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS; break;
1140 case DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE: nNodeType = ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE; break;
1141 case DFF_ANIM_NODE_TYPE_TIMING_ROOT: nNodeType = ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT; break;
1142 case DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ:nNodeType = ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE; break;
1145 sal_Int32 nSize = aUserData.getLength();
1146 aUserData.realloc(nSize+1);
1147 aUserData[nSize].Name = "node-type";
1148 aUserData[nSize].Value <<= nNodeType;
1152 if( rSet.hasProperty( DFF_ANIM_GROUP_ID ) )
1154 sal_Int32 nGroupId;
1155 if( rSet.getProperty( DFF_ANIM_GROUP_ID ) >>= nGroupId )
1157 sal_Int32 nSize = aUserData.getLength();
1158 aUserData.realloc(nSize+1);
1159 aUserData[nSize].Name = "group-id";
1160 aUserData[nSize].Value <<= nGroupId;
1164 sal_Int16 nEffectPresetClass = EffectPresetClass::CUSTOM;
1165 sal_Int32 nPresetId = 0;
1167 if( rSet.hasProperty( DFF_ANIM_PRESET_CLASS ) )
1169 sal_Int32 nPresetClass = 0;
1170 if ( rSet.getProperty( DFF_ANIM_PRESET_CLASS ) >>= nPresetClass )
1172 switch( nPresetClass )
1174 case DFF_ANIM_PRESS_CLASS_ENTRANCE: nEffectPresetClass = EffectPresetClass::ENTRANCE; break;
1175 case DFF_ANIM_PRESS_CLASS_EXIT: nEffectPresetClass = EffectPresetClass::EXIT; break;
1176 case DFF_ANIM_PRESS_CLASS_EMPHASIS: nEffectPresetClass = EffectPresetClass::EMPHASIS; break;
1177 case DFF_ANIM_PRESS_CLASS_MOTIONPATH: nEffectPresetClass = EffectPresetClass::MOTIONPATH; break;
1178 case DFF_ANIM_PRESS_CLASS_OLE_ACTION: nEffectPresetClass = EffectPresetClass::OLEACTION; break;
1179 case DFF_ANIM_PRESS_CLASS_MEDIACALL: nEffectPresetClass = EffectPresetClass::MEDIACALL; break;
1181 sal_Int32 nSize = aUserData.getLength();
1182 aUserData.realloc(nSize+1);
1183 aUserData[nSize].Name = "preset-class";
1184 aUserData[nSize].Value <<= nEffectPresetClass;
1188 if( rSet.hasProperty( DFF_ANIM_PRESET_ID ) )
1190 if( rSet.getProperty( DFF_ANIM_PRESET_ID ) >>= nPresetId )
1192 sal_Int32 nSize = aUserData.getLength();
1193 aUserData.realloc(nSize+1);
1194 aUserData[nSize].Name = "preset-id";
1196 const preset_maping* p = gPresetMaping;
1197 while( p->mpStrPresetId && ((p->mnPresetClass != nEffectPresetClass) || (p->mnPresetId != nPresetId )) )
1198 p++;
1200 if( p->mpStrPresetId )
1202 aUserData[nSize].Value <<= OUString::createFromAscii( p->mpStrPresetId );
1204 else
1206 OUStringBuffer sBuffer;
1207 sBuffer.appendAscii( "ppt_" );
1208 switch( nEffectPresetClass )
1210 case EffectPresetClass::ENTRANCE: sBuffer.appendAscii( "entrance_" ); break;
1211 case EffectPresetClass::EXIT: sBuffer.appendAscii( "exit_" ); break;
1212 case EffectPresetClass::EMPHASIS: sBuffer.appendAscii( "emphasis_" ); break;
1213 case EffectPresetClass::MOTIONPATH: sBuffer.appendAscii( "motionpath_" ); break;
1214 case EffectPresetClass::OLEACTION: sBuffer.appendAscii( "oleaction_" ); break;
1215 case EffectPresetClass::MEDIACALL: sBuffer.appendAscii( "mediacall_" ); break;
1217 sBuffer.append( nPresetId );
1219 aUserData[nSize].Value <<= sBuffer.makeStringAndClear();
1224 if( rSet.hasProperty( DFF_ANIM_PRESET_SUB_TYPE ) )
1226 sal_Int32 nPresetSubType = 0;
1227 if( (rSet.getProperty( DFF_ANIM_PRESET_SUB_TYPE ) >>= nPresetSubType) )
1229 if( nPresetSubType )
1231 sal_Int32 nSize = aUserData.getLength();
1232 aUserData.realloc(nSize+1);
1233 aUserData[nSize].Name = "preset-sub-type";
1234 aUserData[nSize].Value <<= getConvertedSubType( nEffectPresetClass, nPresetId, nPresetSubType );
1239 if( rSet.hasProperty( DFF_ANIM_AFTEREFFECT ) )
1241 if( rSet.getProperty( DFF_ANIM_AFTEREFFECT ) >>= bAfterEffect )
1243 sal_Int32 nSize = aUserData.getLength();
1244 aUserData.realloc(nSize+1);
1245 aUserData[nSize].Name = "after-effect";
1246 aUserData[nSize].Value <<= bAfterEffect;
1250 if( bAfterEffect && rSet.hasProperty( DFF_ANIM_MASTERREL ) )
1252 sal_Int32 nMasterRel = 2;
1253 if( rSet.getProperty( DFF_ANIM_MASTERREL ) >>= nMasterRel )
1255 sal_Int32 nSize = aUserData.getLength();
1256 aUserData.realloc(nSize+1);
1257 aUserData[nSize].Name = "master-rel";
1258 aUserData[nSize].Value <<= nMasterRel;
1262 xNode->setUserData( aUserData );
1264 // TODO: DFF_ANIM_ID
1265 if( rSet.hasProperty( DFF_ANIM_ID ) )
1267 OUString aString;
1268 rSet.getProperty( DFF_ANIM_ID ) >>= aString;
1269 //if( !aString.isEmpty() )
1274 // TODO: DFF_ANIM_EVENT_FILTER
1275 if( rSet.hasProperty( DFF_ANIM_EVENT_FILTER ) )
1277 OUString aString;
1278 rSet.getProperty( DFF_ANIM_EVENT_FILTER ) >>= aString;
1279 //if( !aString.isEmpty() )
1284 // DFF_ANIM_TIMEFILTER
1285 if( rSet.hasProperty( DFF_ANIM_TIMEFILTER ) )
1287 Reference< XAnimate > xAnim( xNode, UNO_QUERY );
1288 if( xAnim.is() )
1290 OUString aString;
1291 rSet.getProperty( DFF_ANIM_TIMEFILTER ) >>= aString;
1292 if( !aString.isEmpty() )
1294 sal_Int32 nElements = 1; // a non empty string has at least one value
1296 sal_Int32 fromIndex = 0;
1297 while(true)
1299 fromIndex = aString.indexOf( (sal_Unicode)';', fromIndex );
1300 if( fromIndex == -1 )
1301 break;
1303 fromIndex++;
1304 nElements++;
1307 Sequence< TimeFilterPair > aTimeFilter( nElements );
1309 TimeFilterPair* pValues = aTimeFilter.getArray();
1310 sal_Int32 nIndex = 0;
1311 while( (nElements--) && (nIndex >= 0) )
1313 const OUString aToken( aString.getToken( 0, ';', nIndex ) );
1315 sal_Int32 nPos = aToken.indexOf( ',' );
1316 if( nPos >= 0 )
1318 pValues->Time = aToken.copy( 0, nPos ).toDouble();
1319 pValues->Progress = aToken.copy( nPos+1, aToken.getLength() - nPos - 1 ).toDouble();
1321 pValues++;
1324 xAnim->setTimeFilter( aTimeFilter );
1329 // TODO: DFF_ANIM_ENDAFTERSLIDE / DFF_ANIM_VOLUME handling. git history has sample code
1330 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
1331 if( xColor.is() )
1333 if( rSet.hasProperty( DFF_ANIM_DIRECTION ) )
1335 bool bDirection = false;
1336 if( rSet.getProperty( DFF_ANIM_DIRECTION ) >>= bDirection )
1337 xColor->setDirection( !bDirection );
1340 if( rSet.hasProperty( DFF_ANIM_COLORSPACE ) )
1342 sal_Int32 nColorSpace = 0;
1343 rSet.getProperty( DFF_ANIM_COLORSPACE ) >>= nColorSpace;
1344 xColor->setColorInterpolation( (nColorSpace == 0) ? AnimationColorSpace::RGB : AnimationColorSpace::HSL );
1349 int AnimationImporter::importTimeContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
1351 int nNodes = 0;
1353 DBG_ASSERT( pAtom && xNode.is(), "invalid call to ppt::AnimationImporter::importTimeContainer()!");
1354 if( pAtom && xNode.is() )
1356 importAnimationEvents( pAtom, xNode );
1357 importAnimationValues( pAtom, xNode );
1358 importAnimationActions( pAtom, xNode );
1360 dump(">\n");
1362 // import sub containers
1363 const Atom* pChildAtom = pAtom->findFirstChildAtom();
1365 while( pChildAtom )
1367 switch( pChildAtom->getType() )
1369 case DFF_msofbtAnimNode:
1370 case DFF_msofbtAnimEvent:
1371 case DFF_msofbtAnimValue:
1372 case DFF_msofbtAnimAction:
1373 case DFF_msofbtAnimPropertySet:
1374 break;
1376 case DFF_msofbtAnimSubGoup :
1378 if( pChildAtom->hasChildAtom( DFF_msofbtAnimCommand ) )
1380 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1381 Reference< XAnimationNode > xChildNode( Command::create(xContext), UNO_QUERY_THROW );
1382 nNodes += importAnimationNodeContainer( pChildAtom, xChildNode );
1383 Reference< XTimeContainer > xParentContainer( xNode, UNO_QUERY );
1384 if( xParentContainer.is() && xChildNode.is() )
1385 xParentContainer->appendChild( xChildNode );
1387 else
1389 nNodes += importAnimationContainer( pChildAtom, xNode );
1392 break;
1393 case DFF_msofbtAnimGroup :
1395 nNodes += importAnimationContainer( pChildAtom, xNode );
1397 break;
1398 case DFF_msofbtAnimIteration:
1400 if( pChildAtom->seekToContent() )
1402 float fInterval;
1403 sal_Int32 nTextUnitEffect, nU1, nU2, nU3;
1405 mrStCtrl.ReadFloat( fInterval ).ReadInt32( nTextUnitEffect ).ReadInt32( nU1 ).ReadInt32( nU2 ).ReadInt32( nU3 );
1407 Reference< XIterateContainer > xIter( xNode, UNO_QUERY );
1408 if( xIter.is() )
1410 sal_Int16 nIterateType = TextAnimationType::BY_PARAGRAPH;
1411 switch( nTextUnitEffect )
1413 case 1: nIterateType = TextAnimationType::BY_WORD; break;
1414 case 2: nIterateType = TextAnimationType::BY_LETTER; break;
1416 xIter->setIterateType( nIterateType );
1417 xIter->setIterateInterval( (double)fInterval );
1420 nNodes++;
1422 dump( "<iterate" );
1423 dump( " iterateType=\"%s\"", (nTextUnitEffect == 0) ? "byElement" : (nTextUnitEffect == 1) ? "byWord" : "byLetter" );
1424 dump( " iterateInterval=\"%g\"", fInterval );
1425 dump( " u1=\"%ld\"", nU1 );
1426 dump( " u2=\"%ld\"", nU2 );
1427 dump( " u3=\"%ld\"/>\n", nU3 );
1430 break;
1432 case 0xf136:
1434 #ifdef DBG_ANIM_LOG
1435 sal_uInt32 nU1, nU2;
1436 mrStCtrl >> nU1 >> nU2;
1438 fprintf( mpFile, "<unknown_0xf136 nU1=\"%ld\" nU2=\"%ld\"/>\n", nU1, nU2 );
1439 #endif
1441 break;
1443 default:
1445 dump_atom_header( pChildAtom, true, false );
1446 dump_atom( pChildAtom );
1447 dump_atom_header( pChildAtom, false, false );
1449 break;
1452 pChildAtom = Atom::findNextChildAtom( pChildAtom );
1456 return nNodes;
1459 int AnimationImporter::importAnimationNodeContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
1461 int nNodes = 0;
1463 DBG_ASSERT( pAtom && xNode.is(), "invalid call to ppt::AnimationImporter::importAnimationNodeContainer()!");
1464 if( pAtom && xNode.is() )
1466 importAnimationEvents( pAtom, xNode );
1467 importAnimationValues( pAtom, xNode );
1468 importAnimationActions( pAtom, xNode );
1470 const Atom* pChildAtom = pAtom->findFirstChildAtom();
1472 while( pChildAtom )
1474 nNodes ++;
1475 switch( pChildAtom->getType() )
1477 case DFF_msofbtAnimNode:
1478 case DFF_msofbtAnimEvent:
1479 case DFF_msofbtAnimValue:
1480 case DFF_msofbtAnimAction:
1481 case DFF_msofbtAnimPropertySet:
1482 break;
1484 case DFF_msofbtAnimateFilter:
1485 importAnimateFilterContainer( pChildAtom, xNode );
1486 break;
1488 case DFF_msofbtAnimateSet:
1489 importAnimateSetContainer( pChildAtom, xNode );
1490 break;
1492 case DFF_msofbtAnimate:
1493 importAnimateContainer( pChildAtom, xNode );
1494 break;
1496 case DFF_msofbtAnimateScale:
1497 importAnimateScaleContainer( pChildAtom, xNode );
1498 break;
1500 case DFF_msofbtAnimateColor:
1501 importAnimateColorContainer( pChildAtom, xNode );
1502 break;
1504 case DFF_msofbtAnimateRotation:
1505 importAnimateRotationContainer( pChildAtom, xNode );
1506 break;
1508 case DFF_msofbtAnimateMotion:
1509 importAnimateMotionContainer( pChildAtom, xNode );
1510 break;
1512 case DFF_msofbtAnimCommand:
1513 importCommandContainer( pChildAtom, xNode );
1514 break;
1516 default:
1518 nNodes --;
1519 dump_atom_header( pChildAtom, true, false );
1520 dump_atom( pChildAtom );
1521 dump_atom_header( pChildAtom, false, false );
1523 break;
1526 pChildAtom = Atom::findNextChildAtom( pChildAtom );
1530 return nNodes;
1533 void AnimationImporter::importAnimateFilterContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
1535 Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY );
1537 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateFilter && xFilter.is(), "invalid call to ppt::AnimationImporter::importAnimateFilterContainer()!");
1538 if( pAtom && xFilter.is() )
1540 sal_uInt32 nBits = 0;
1542 const Atom* pChildAtom = pAtom->findFirstChildAtom();
1544 while( pChildAtom )
1546 if( !pChildAtom->isContainer() )
1548 if( !pChildAtom->seekToContent() )
1549 break;
1552 switch( pChildAtom->getType() )
1554 case DFF_msofbtAnimateFilterData:
1556 sal_uInt32 transition;
1557 mrStCtrl.ReadUInt32( nBits );
1558 mrStCtrl.ReadUInt32( transition );
1560 if( nBits & 1 )
1561 xFilter->setMode( transition == 0 );
1563 dump( " transition=\"%s\"", (transition == 0) ? "in" : "out" );
1565 break;
1567 case DFF_msofbtAnimAttributeValue:
1569 if( (nBits & 2 ) && ( pChildAtom->getInstance() == 1 ) )
1571 Any aAny;
1572 if ( importAttributeValue( pChildAtom, aAny ) )
1574 OUString filter;
1575 aAny >>= filter;
1577 dump( " filter=\"%s\"", filter );
1579 const transition* pTransition = transition::find( filter );
1580 if( pTransition )
1582 xFilter->setTransition( pTransition->mnType );
1583 xFilter->setSubtype( pTransition->mnSubType );
1584 xFilter->setDirection( pTransition->mbDirection );
1586 else
1588 OSL_FAIL( "unknown transition!" );
1593 break;
1595 case DFF_msofbtAnimateTarget:
1596 importAnimateAttributeTargetContainer( pChildAtom, xNode );
1597 break;
1599 default:
1600 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
1601 break;
1605 pChildAtom = Atom::findNextChildAtom( pChildAtom );
1610 void AnimationImporter::importAnimateAttributeTargetContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
1612 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateTarget, "invalid call to ppt::AnimationImporter::importAnimateAttributeTargetContainer()!");
1614 Any aTarget;
1616 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
1618 bool bWrongContext = false;
1620 if( pAtom )
1622 const Atom* pChildAtom = pAtom->findFirstChildAtom();
1624 while( pChildAtom )
1626 if( !pChildAtom->isContainer() )
1628 if( !pChildAtom->seekToContent() )
1629 break;
1632 switch( pChildAtom->getType() )
1634 case DFF_msofbtAnimPropertySet:
1636 PropertySet aSet;
1637 importPropertySetContainer( pChildAtom, aSet );
1638 if( aSet.hasProperty( DFF_ANIM_RUNTIMECONTEXT ) )
1640 OUString aContext;
1641 if( aSet.getProperty( DFF_ANIM_RUNTIMECONTEXT ) >>= aContext )
1643 if( aContext != "PPT" )
1644 bWrongContext = true;
1648 dump( aSet );
1650 break;
1652 case DFF_msofbtAnimateTargetSettings:
1654 if( xAnimate.is() )
1656 sal_uInt32 nBits;
1657 sal_uInt32 nAdditive;
1658 sal_uInt32 nAccumulate;
1659 sal_uInt32 nTransformType;
1661 mrStCtrl.ReadUInt32( nBits ).ReadUInt32( nAdditive ).ReadUInt32( nAccumulate ).ReadUInt32( nTransformType );
1663 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1664 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1665 // nAccumulate 0 = none, 1 = always
1666 // nTransformType 0: "property" else "image"
1668 if( nBits & 3 )
1670 if( xAnimate.is() )
1672 if( nBits & 1 )
1674 sal_Int16 nTemp = AnimationAdditiveMode::BASE;
1675 switch( nAdditive )
1677 case 1: nTemp = AnimationAdditiveMode::SUM; break;
1678 case 2: nTemp = AnimationAdditiveMode::REPLACE; break;
1679 case 3: nTemp = AnimationAdditiveMode::MULTIPLY; break;
1680 case 4: nTemp = AnimationAdditiveMode::NONE; break;
1682 xAnimate->setAdditive( nTemp );
1685 if( nBits & 2 )
1687 xAnimate->setAccumulate( (nAccumulate == 0) ? sal_True : sal_False );
1691 #ifdef DBG_ANIM_LOG
1692 if( nBits & 1 )
1693 fprintf( mpFile, " additive=\"%s\"", (nAdditive == 0) ? "base" : (nAdditive == 2) ? "replace" : (nAdditive == 1) ? "sum" : (nAdditive == 3 ) ? "multiply" : (nAdditive == 4) ? "none" : "unknown" );
1695 if( nBits & 2 )
1696 fprintf( mpFile, " accumulate=\"%s\"", (nAccumulate == 0) ? "none" : "always" );
1698 if( nBits & 8 )
1699 fprintf( mpFile, " transformType=\"%s\"", (nTransformType == 0) ? "property" : "image" );
1700 #endif
1703 break;
1705 case DFF_msofbtAnimateAttributeNames:
1707 if( xAnimate.is() )
1709 OUString aAttributeName;
1710 importAttributeNamesContainer( pChildAtom, aAttributeName );
1711 if( xAnimate.is() )
1712 xAnimate->setAttributeName( aAttributeName );
1713 dump( " attributeName=\"%s\"", aAttributeName );
1716 break;
1718 case DFF_msofbtAnimateTargetElement:
1720 sal_Int16 nSubType;
1721 importTargetElementContainer( pChildAtom, aTarget, nSubType );
1722 if( xAnimate.is() )
1723 xAnimate->setSubItem( nSubType );
1725 dump( " target=\"" );
1726 dump_target( aTarget );
1727 dump( "\"" );
1729 break;
1731 default:
1732 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
1733 break;
1736 pChildAtom = Atom::findNextChildAtom( pChildAtom );
1740 if( bWrongContext )
1741 aTarget.clear();
1743 if( xAnimate.is() )
1744 xAnimate->setTarget( aTarget );
1745 else
1747 Reference< XCommand > xCommand( xNode, UNO_QUERY );
1748 if( xCommand.is() )
1749 xCommand->setTarget( aTarget );
1753 sal_Int16 AnimationImporter::implGetColorSpace( sal_Int32 nMode, sal_Int32 /*nA*/, sal_Int32 /*nB*/, sal_Int32 /*nC*/ )
1755 switch( nMode )
1757 case 2: // index
1758 // FALLTHROUGH intended
1759 default:
1760 // FALLTHROUGH intended
1761 case 0: // rgb
1762 return AnimationColorSpace::RGB;
1764 case 1: // hsl
1765 return AnimationColorSpace::HSL;
1769 Any AnimationImporter::implGetColorAny( sal_Int32 nMode, sal_Int32 nA, sal_Int32 nB, sal_Int32 nC )
1771 switch( nMode )
1773 case 0: // rgb
1775 dump( "rgb(%ld", nA );
1776 dump( ",%ld", nB );
1777 dump( ",%ld)", nC );
1778 Color aColor( (sal_uInt8)nA, (sal_uInt8)nB, (sal_uInt8)nC );
1779 return makeAny( (sal_Int32)aColor.GetRGBColor() );
1781 case 1: // hsl
1783 dump( "hsl(%ld", nA );
1784 dump( ",%ld", nB );
1785 dump( ",%ld)", nC );
1786 Sequence< double > aHSL( 3 );
1787 aHSL[0] = nA * 360.0/255.0;
1788 aHSL[1] = nB / 255.0;
1789 aHSL[2] = nC / 255.0;
1790 return makeAny( aHSL );
1793 case 2: // index
1795 Color aColor;
1796 mpPPTImport->GetColorFromPalette((sal_uInt16)nA, aColor );
1797 dump( "index(%ld", nA );
1798 dump( " [%ld", (sal_Int32)aColor.GetRed() );
1799 dump( ",%ld", (sal_Int32)aColor.GetGreen() );
1800 dump( ",%ld])", (sal_Int32)aColor.GetBlue() );
1801 return makeAny( (sal_Int32)aColor.GetRGBColor() );
1804 default:
1806 dump( "unknown_%ld(", nMode );
1807 dump( "%ld", nA );
1808 dump( ",%ld", nB );
1809 dump( ",%ld)", nC );
1810 OSL_FAIL( "ppt::implGetColorAny(), unhandled color type" );
1812 Any aAny;
1813 return aAny;
1818 void AnimationImporter::importAnimateColorContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
1820 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
1822 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateColor && xColor.is(), "invalid call to ppt::AnimationImporter::importAnimateColorContainer()!");
1823 if( pAtom && xColor.is() )
1825 const Atom* pChildAtom = pAtom->findFirstChildAtom();
1827 while( pChildAtom )
1829 if( !pChildAtom->isContainer() )
1831 if( !pChildAtom->seekToContent() )
1832 break;
1835 switch( pChildAtom->getType() )
1837 case DFF_msofbtAnimateColorData:
1839 sal_uInt32 nBits;
1840 sal_Int32 nByMode, nByA, nByB, nByC;
1841 sal_Int32 nFromMode, nFromA, nFromB, nFromC;
1842 sal_Int32 nToMode, nToA, nToB, nToC;
1843 mrStCtrl.ReadUInt32( nBits );
1844 mrStCtrl.ReadInt32( nByMode ).ReadInt32( nByA ).ReadInt32( nByB ).ReadInt32( nByC );
1845 mrStCtrl.ReadInt32( nFromMode ).ReadInt32( nFromA ).ReadInt32( nFromB ).ReadInt32( nFromC );
1846 mrStCtrl.ReadInt32( nToMode ).ReadInt32( nToA ).ReadInt32( nToB ).ReadInt32( nToC );
1848 if( nBits & 1 )
1850 dump( " by=\"" );
1851 xColor->setBy( implGetColorAny( nByMode, nByA, nByB, nByC ) );
1852 xColor->setColorInterpolation( implGetColorSpace( nByMode, nByA, nByB, nByC ) );
1853 dump( "\"");
1856 if( nBits & 2 )
1858 dump( " from=\"" );
1859 xColor->setFrom( implGetColorAny( nFromMode, nFromA, nFromB, nFromC ) );
1860 xColor->setColorInterpolation( implGetColorSpace( nFromMode, nFromA, nFromB, nFromC ) );
1861 dump( "\"");
1864 if( nBits & 4 )
1866 dump( " to=\"" );
1867 xColor->setTo( implGetColorAny( nToMode, nToA, nToB, nToC ) );
1868 xColor->setColorInterpolation( implGetColorSpace( nToMode, nToA, nToB, nToC ) );
1869 dump( "\"");
1872 break;
1874 case DFF_msofbtAnimateTarget:
1875 importAnimateAttributeTargetContainer( pChildAtom, xNode );
1876 break;
1878 default:
1879 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
1880 break;
1883 pChildAtom = Atom::findNextChildAtom( pChildAtom );
1888 void AnimationImporter::importAnimateSetContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
1890 Reference< XAnimateSet > xSet( xNode, UNO_QUERY );
1892 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateSet && xSet.is(), "invalid call to ppt::AnimationImporter::importAnimateSetContainer()!");
1893 if( pAtom && xSet.is() )
1895 const Atom* pChildAtom = pAtom->findFirstChildAtom();
1897 while( pChildAtom )
1899 if( !pChildAtom->isContainer() )
1901 if( !pChildAtom->seekToContent() )
1902 break;
1905 switch( pChildAtom->getType() )
1907 case DFF_msofbtAnimateSetData:
1909 sal_Int32 nU1, nU2;
1910 mrStCtrl.ReadInt32( nU1 ).ReadInt32( nU2 );
1912 dump( " set_1=\"%ld\"", nU1 ),
1913 dump( " set_2=\"%ld\"", nU2 );
1915 break;
1917 case DFF_msofbtAnimAttributeValue:
1919 Any aTo;
1920 if ( importAttributeValue( pChildAtom, aTo ) )
1922 xSet->setTo( aTo );
1924 dump( " value=\"" );
1925 dump( aTo );
1926 dump( "\"" );
1929 break;
1931 case DFF_msofbtAnimateTarget:
1932 importAnimateAttributeTargetContainer( pChildAtom, xNode );
1933 break;
1935 default:
1936 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
1937 break;
1940 pChildAtom = Atom::findNextChildAtom( pChildAtom );
1945 void AnimationImporter::importAnimateContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
1947 Reference< XAnimate > xAnim( xNode, UNO_QUERY );
1949 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimate && xAnim.is(), "invalid call to ppt::AnimationImporter::importAnimateContainer()!");
1950 if( pAtom && xAnim.is() )
1952 const Atom* pChildAtom = pAtom->findFirstChildAtom();
1954 while( pChildAtom )
1956 if( !pChildAtom->isContainer() )
1958 if( !pChildAtom->seekToContent() )
1959 break;
1962 switch( pChildAtom->getType() )
1964 case DFF_msofbtAnimateData:
1966 sal_uInt32 nCalcmode, nBits, nValueType;
1967 mrStCtrl.ReadUInt32( nCalcmode ).ReadUInt32( nBits ).ReadUInt32( nValueType );
1969 if( nBits & 0x08 )
1971 sal_Int16 n = (nCalcmode == 1) ? AnimationCalcMode::LINEAR : /* (nCalcmode == 2) ? AnimationCalcMode::FORMULA : */ AnimationCalcMode::DISCRETE;
1972 xAnim->setCalcMode( n );
1973 dump( " calcmode=\"%s\"", (nCalcmode == 0) ? "discrete" : (nCalcmode == 1) ? "linear" : (nCalcmode == 2) ? "formula" : "unknown" );
1976 if( nBits & 0x30 )
1978 sal_Int16 n = (nValueType == 1) ? AnimationValueType::NUMBER : (nValueType == 2 ) ? AnimationValueType::COLOR : AnimationValueType::STRING;
1979 xAnim->setValueType( n );
1980 dump( " valueType=\"%s\"", (nValueType == 0) ? "string" : (nValueType == 1) ? "number" : (nValueType == 2) ? "color" : "unknown" );
1983 break;
1985 case DFF_msofbtAnimateTarget:
1986 importAnimateAttributeTargetContainer( pChildAtom, xNode );
1987 break;
1989 case DFF_msofbtAnimKeyPoints:
1990 importAnimateKeyPoints( pChildAtom, xNode );
1991 break;
1993 case DFF_msofbtAnimAttributeValue:
1995 Any a;
1996 if ( importAttributeValue( pChildAtom, a ) )
1998 switch( pChildAtom->getInstance() )
2000 case 1: xAnim->setBy( a ); dump( " by=\"" ); break;
2001 case 2: xAnim->setFrom( a ); dump( " from=\"" ); break;
2002 case 3: xAnim->setTo( a ); dump( " to=\"" ); break;
2003 default:
2004 dump( " unknown_value=\"" );
2007 dump( a );
2008 dump( "\"" );
2011 break;
2012 default:
2013 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
2014 break;
2017 pChildAtom = Atom::findNextChildAtom( pChildAtom );
2022 void AnimationImporter::importAnimateMotionContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2024 Reference< XAnimateMotion > xMotion( xNode, UNO_QUERY );
2026 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateMotion && xMotion.is(), "invalid call to ppt::AnimationImporter::importAnimateMotionContainer()!");
2027 if( pAtom && xMotion.is() )
2029 const Atom* pChildAtom = pAtom->findFirstChildAtom();
2031 while( pChildAtom )
2033 if( !pChildAtom->isContainer() )
2035 if( !pChildAtom->seekToContent() )
2036 break;
2039 switch( pChildAtom->getType() )
2041 case DFF_msofbtAnimateMotionData:
2043 sal_uInt32 nBits, nOrigin;
2044 float fByX, fByY, fFromX, fFromY, fToX, fToY;
2046 mrStCtrl.ReadUInt32( nBits ).ReadFloat( fByX ).ReadFloat( fByY ).ReadFloat( fFromX ).ReadFloat( fFromY ).ReadFloat( fToX ).ReadFloat( fToY ).ReadUInt32( nOrigin );
2048 #ifdef DBG_ANIM_LOG
2049 if( nBits & 1 )
2050 fprintf( mpFile, " by=\"%g,%g\"", (double)fByX, (double)fByY );
2052 if( nBits & 2 )
2053 fprintf( mpFile, " from=\"%g,%g\"", (double)fFromX, (double)fFromY );
2055 if( nBits & 4 )
2056 fprintf( mpFile, " to=\"%g,%g\"", (double)fToX, (double)fToY );
2058 if( nBits & 8 )
2059 fprintf( mpFile, " origin=\"%s\"", (nOrigin == 1) ? "parent" : (nOrigin == 2) ? "layout" : "unknown" );
2061 #endif
2063 break;
2065 case DFF_msofbtAnimAttributeValue:
2067 Any aPath;
2068 if ( importAttributeValue( pChildAtom, aPath ) )
2070 OUString aStr;
2071 if ( aPath >>= aStr )
2073 // E can appear inside a number, so we only check for its presence at the end
2074 aStr = aStr.trim();
2075 if (aStr.endsWith("E"))
2076 aStr = aStr.copy(0, aStr.getLength() - 1);
2077 aStr = aStr.trim();
2078 aPath <<= aStr;
2079 xMotion->setPath( aPath );
2080 dump( " path=\"" );
2081 dump( aPath );
2082 dump( "\"" );
2086 break;
2088 case DFF_msofbtAnimateTarget:
2089 importAnimateAttributeTargetContainer( pChildAtom, xNode );
2090 break;
2092 default:
2093 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
2094 break;
2097 pChildAtom = Atom::findNextChildAtom( pChildAtom );
2102 void AnimationImporter::importCommandContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2104 Reference< XCommand > xCommand( xNode, UNO_QUERY );
2105 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimCommand && xCommand.is(), "invalid call to ppt::AnimationImporter::importCommandContainer()!");
2106 if( pAtom && xCommand.is() )
2108 sal_Int32 nBits = 0;
2109 Any aValue;
2111 const Atom* pChildAtom = pAtom->findFirstChildAtom();
2113 while( pChildAtom )
2115 if( !pChildAtom->isContainer() )
2117 if( !pChildAtom->seekToContent() )
2118 break;
2121 switch( pChildAtom->getType() )
2123 case DFF_msofbtCommandData:
2125 sal_Int32 nCommandType;
2126 // looks like U1 is a bitset, bit 1 enables the type and bit 2 enables
2127 // a propertyvalue that follows
2128 mrStCtrl.ReadInt32( nBits );
2129 mrStCtrl.ReadInt32( nCommandType );
2131 if( nBits & 1 )
2133 dump( " type=\"%s\"", (nCommandType == 0) ? "event" : ( nCommandType == 1) ? "call" : "verb" );
2136 break;
2138 case DFF_msofbtAnimAttributeValue:
2140 if ( importAttributeValue( pChildAtom, aValue ) )
2142 if( nBits & 2 )
2144 dump( " cmd=\"" );
2145 dump( aValue );
2146 dump( "\"" );
2150 break;
2152 case DFF_msofbtAnimateTarget:
2153 importAnimateAttributeTargetContainer( pChildAtom, xNode );
2154 break;
2156 default:
2157 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
2158 break;
2161 pChildAtom = Atom::findNextChildAtom( pChildAtom );
2164 if( nBits & 3 )
2166 OUString aParam;
2167 aValue >>= aParam;
2169 sal_Int16 nCommand = EffectCommands::CUSTOM;
2171 NamedValue aParamValue;
2173 if ( aParam == "onstopaudio" )
2175 nCommand = EffectCommands::STOPAUDIO;
2177 else if ( aParam == "play" )
2179 nCommand = EffectCommands::PLAY;
2181 else if( aParam.startsWith( "playFrom" ) )
2183 const OUString aMediaTime( aParam.copy( 9, aParam.getLength() - 10 ) );
2184 rtl_math_ConversionStatus eStatus;
2185 double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
2186 if( eStatus == rtl_math_ConversionStatus_Ok )
2188 aParamValue.Name = "MediaTime";
2189 aParamValue.Value <<= fMediaTime;
2191 nCommand = EffectCommands::PLAY;
2193 else if ( aParam == "togglePause" )
2195 nCommand = EffectCommands::TOGGLEPAUSE;
2197 else if ( aParam == "stop" )
2199 nCommand = EffectCommands::STOP;
2202 xCommand->setCommand( nCommand );
2203 if( nCommand == EffectCommands::CUSTOM )
2205 OSL_FAIL("sd::AnimationImporter::importCommandContainer(), unknown command!");
2206 aParamValue.Name = "UserDefined";
2207 aParamValue.Value <<= aParam;
2210 if( aParamValue.Value.hasValue() )
2212 Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
2213 xCommand->setParameter( makeAny( aParamSeq ) );
2219 int AnimationImporter::importAudioContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2221 int nNodes = 0;
2223 Reference< XAudio > xAudio( xNode, UNO_QUERY );
2224 DBG_ASSERT( pAtom && xAudio.is() &&
2225 ( (pAtom->getType() == DFF_msofbtAnimGroup) ||
2226 (pAtom->getType() == DFF_msofbtAnimSubGoup) ), "invalid call to ppt::AnimationImporter::importAudioContainer()!");
2227 if( pAtom && xAudio.is() )
2229 importAnimationEvents( pAtom, xNode );
2230 importAnimationValues( pAtom, xNode );
2231 importAnimationActions( pAtom, xNode );
2233 dump(">\n");
2235 const Atom* pChildAtom = pAtom->findFirstChildAtom();
2237 while( pChildAtom )
2239 if( !pChildAtom->isContainer() )
2241 if( !pChildAtom->seekToContent() )
2242 break;
2245 switch( pChildAtom->getType() )
2247 case DFF_msofbtAnimNode:
2248 case DFF_msofbtAnimEvent:
2249 case DFF_msofbtAnimValue:
2250 case DFF_msofbtAnimAction:
2251 case DFF_msofbtAnimPropertySet:
2252 break;
2254 case DFF_msofbtAnimAttributeValue:
2256 Any aValue;
2257 if ( importAttributeValue( pChildAtom, aValue ) )
2259 nNodes ++;
2260 dump( " value=\"" );
2261 dump( aValue );
2262 dump( "\"" );
2265 break;
2267 case DFF_msofbtAnimateTargetElement:
2269 sal_Int16 nSubType;
2270 Any aSource;
2271 importTargetElementContainer( pChildAtom, aSource, nSubType );
2272 if( xAudio.is() ) {
2273 xAudio->setSource( aSource );
2274 nNodes ++;
2277 break;
2279 default:
2280 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
2281 break;
2284 pChildAtom = Atom::findNextChildAtom( pChildAtom );
2287 // TODO: What to do with them?
2288 Any aEmpty;
2289 xAudio->setBegin( aEmpty );
2290 xAudio->setEnd( aEmpty );
2293 return nNodes;
2296 void AnimationImporter::importAnimateScaleContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2298 Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY );
2300 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateScale && xTransform.is(), "invalid call to ppt::AnimationImporter::importAnimateScaleContainer()!");
2301 if( pAtom && xTransform.is() )
2303 xTransform->setTransformType( AnimationTransformType::SCALE );
2305 const Atom* pChildAtom = pAtom->findFirstChildAtom();
2307 while( pChildAtom )
2309 if( !pChildAtom->isContainer() )
2311 if( !pChildAtom->seekToContent() )
2312 break;
2315 switch( pChildAtom->getType() )
2317 case DFF_msofbtAnimateScaleData:
2319 sal_uInt32 nBits, nZoomContents;
2320 float fByX, fByY, fFromX, fFromY, fToX, fToY;
2322 // nBits %001: by, %010: from, %100: to, %1000: zoomContents(bool)
2323 mrStCtrl.ReadUInt32( nBits ).ReadFloat( fByX ).ReadFloat( fByY ).ReadFloat( fFromX ).ReadFloat( fFromY ).ReadFloat( fToX ).ReadFloat( fToY ).ReadUInt32( nZoomContents );
2325 ValuePair aPair;
2326 // 'from' value
2327 if( nBits & 2 )
2329 aPair.First <<= (double)fFromX / 100.0;
2330 aPair.Second <<= (double)fFromY / 100.0;
2331 xTransform->setFrom( makeAny( aPair ) );
2334 // 'to' value
2335 if( nBits & 4 )
2337 aPair.First <<= (double)fToX / 100.0;
2338 aPair.Second <<= (double)fToY / 100.0;
2339 xTransform->setTo( makeAny( aPair ) );
2342 // 'by' value
2343 if( nBits & 1 )
2345 aPair.First <<= (double)fByX / 100.0;
2346 aPair.Second <<= (double)fByY / 100.0;
2348 if( nBits & 2 )
2350 // 'from' value given, import normally
2351 xTransform->setBy( makeAny( aPair ) );
2353 else
2355 // mapping 'by' to 'to', if no 'from' is
2356 // given. This is due to a non-conformity in
2357 // PPT, which exports animateScale effects
2358 // with a sole 'by' value, but with the
2359 // semantics of a sole 'to' animation
2360 xTransform->setTo( makeAny( aPair ) );
2364 #ifdef DBG_ANIM_LOG
2365 if( nBits & 1 )
2366 fprintf( mpFile, " by=\"%g,%g\"", (double)fByX, (double)fByY );
2368 if( nBits & 2 )
2369 fprintf( mpFile, " from=\"%g,%g\"", (double)fFromX, (double)fFromY );
2371 if( nBits & 4 )
2372 fprintf( mpFile, " to=\"%g,%g\"", (double)fToX, (double)fToY );
2374 if( nBits & 8 )
2375 fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
2376 #endif
2378 break;
2380 case DFF_msofbtAnimateTarget:
2381 importAnimateAttributeTargetContainer( pChildAtom, xNode );
2382 break;
2384 default:
2385 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
2386 break;
2389 pChildAtom = Atom::findNextChildAtom( pChildAtom );
2394 void AnimationImporter::importAnimateRotationContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2396 Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY );
2398 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateRotation && xTransform.is(), "invalid call to ppt::AnimationImporter::importAnimateRotationContainer()!");
2399 if( pAtom && xTransform.is() )
2401 xTransform->setTransformType( AnimationTransformType::ROTATE );
2403 const Atom* pChildAtom = pAtom->findFirstChildAtom();
2405 while( pChildAtom )
2407 if( !pChildAtom->isContainer() )
2409 if( !pChildAtom->seekToContent() )
2410 break;
2413 switch( pChildAtom->getType() )
2415 case DFF_msofbtAnimateRotationData:
2417 sal_uInt32 nBits, nU1;
2418 float fBy, fFrom, fTo;
2420 // nBits %001: by, %010: from, %100: to, %1000: zoomContents(bool)
2421 mrStCtrl.ReadUInt32( nBits ).ReadFloat( fBy ).ReadFloat( fFrom ).ReadFloat( fTo ).ReadUInt32( nU1 );
2423 if( nBits & 1 )
2424 xTransform->setBy( makeAny( (double) fBy ) );
2426 if( nBits & 2 )
2427 xTransform->setFrom( makeAny( (double) fFrom ) );
2429 if( nBits & 4 )
2430 xTransform->setTo( makeAny( (double) fTo ) );
2432 #ifdef DBG_ANIM_LOG
2433 if( nBits & 1 )
2434 fprintf( mpFile, " by=\"%g\"", (double)fBy );
2436 if( nBits & 2 )
2437 fprintf( mpFile, " from=\"%g\"", (double)fFrom );
2439 if( nBits & 4 )
2440 fprintf( mpFile, " to=\"%g\"", (double)fTo );
2442 if( nU1 )
2443 fprintf( mpFile, " rotation_1=\"%ld\"", nU1 );
2444 #endif
2446 break;
2448 case DFF_msofbtAnimateTarget:
2449 importAnimateAttributeTargetContainer( pChildAtom, xNode );
2450 break;
2452 default:
2453 dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() );
2454 break;
2457 pChildAtom = Atom::findNextChildAtom( pChildAtom );
2462 bool AnimationImporter::importAttributeNamesContainer( const Atom* pAtom, OUString& rAttributeNames )
2464 OUStringBuffer aNames;
2466 DBG_ASSERT( pAtom && (pAtom->getType() == DFF_msofbtAnimateAttributeNames), "invalid call to ppt::AnimationImporter::importAttributeName()!" );
2467 if( pAtom )
2469 const Atom* pAttributeValueAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimAttributeValue );
2471 while( pAttributeValueAtom )
2473 Any aAny;
2474 if ( importAttributeValue( pAttributeValueAtom, aAny ) )
2476 OUString aName;
2477 if( aAny >>= aName )
2479 if( !aNames.isEmpty() )
2480 aNames.append( ';' );
2482 aNames.append( aName );
2485 else
2487 OSL_FAIL( "error during ppt::AnimationImporter::importAttributeName()!" );
2490 pAttributeValueAtom = pAtom->findNextChildAtom( DFF_msofbtAnimAttributeValue, pAttributeValueAtom );
2494 rAttributeNames = aNames.makeStringAndClear();
2495 return true;
2498 void AnimationImporter::importAnimationValues( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2500 DBG_ASSERT( pAtom, "invalid call to ppt::AnimationImporter::importAnimationValues()!" );
2502 if( pAtom )
2504 const Atom* pValueAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimValue );
2506 while( pValueAtom && pValueAtom->seekToContent() )
2508 sal_uInt32 nType;
2509 mrStCtrl.ReadUInt32( nType );
2510 switch( nType )
2512 case 0:
2514 float fRepeat;
2515 mrStCtrl.ReadFloat( fRepeat );
2516 xNode->setRepeatCount( (fRepeat < ((float)3.40282346638528860e+38)) ? makeAny( (double)fRepeat ) : makeAny( Timing_INDEFINITE ) );
2518 #ifdef DBG_ANIM_LOG
2519 if( (fRepeat < ((float)3.40282346638528860e+38)) )
2521 dump( " repeat=\"%g\"", (double)fRepeat );
2523 else
2525 dump( " repeat=\"indefinite\"" );
2527 #endif
2529 break;
2531 case 3:
2533 float faccelerate;
2534 mrStCtrl.ReadFloat( faccelerate );
2535 xNode->setAcceleration( faccelerate );
2536 dump( " accelerate=\"%g\"", (double)faccelerate );
2538 break;
2540 case 4:
2542 float fdecelerate;
2543 mrStCtrl.ReadFloat( fdecelerate );
2544 xNode->setDecelerate( fdecelerate );
2545 dump( " decelerate=\"%g\"", (double)fdecelerate );
2547 break;
2549 case 5:
2551 sal_Int32 nAutoreverse;
2552 mrStCtrl.ReadInt32( nAutoreverse );
2553 xNode->setAutoReverse( nAutoreverse != 0 );
2554 dump( " autoreverse=\"%#lx\"", nAutoreverse );
2556 break;
2558 default:
2560 sal_uInt32 nUnknown;
2561 mrStCtrl.ReadUInt32( nUnknown );
2562 #ifdef DBG_ANIM_LOG
2563 fprintf(mpFile, " attribute_%d=\"%#lx\"", nType, nUnknown );
2564 #endif
2566 break;
2569 pValueAtom = pAtom->findNextChildAtom( DFF_msofbtAnimValue, pValueAtom );
2574 void AnimationImporter::importAnimateKeyPoints( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2576 Reference< XAnimate > xAnim( xNode, UNO_QUERY );
2578 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimKeyPoints && xAnim.is(), "invalid call to ppt::AnimationImporter::importAnimateKeyPoints()!" );
2580 if( pAtom && xAnim.is() )
2582 // first count keytimes
2583 const Atom* pIter = NULL;
2584 int nKeyTimes = 0;
2586 while( (pIter = pAtom->findNextChildAtom( DFF_msofbtAnimKeyTime, pIter )) != 0 )
2587 nKeyTimes++;
2589 Sequence< double > aKeyTimes( nKeyTimes );
2590 Sequence< Any > aValues( nKeyTimes );
2591 OUString aFormula;
2593 pIter = pAtom->findFirstChildAtom(DFF_msofbtAnimKeyTime);
2594 int nKeyTime;
2595 sal_Int32 nTemp;
2596 for( nKeyTime = 0; (nKeyTime < nKeyTimes) && pIter; nKeyTime++ )
2598 if( pIter->seekToContent() )
2600 mrStCtrl.ReadInt32( nTemp );
2601 double fTemp = (double)nTemp / 1000.0;
2602 aKeyTimes[nKeyTime] = fTemp;
2604 const Atom* pValue = Atom::findNextChildAtom(pIter);
2605 if( pValue && pValue->getType() == DFF_msofbtAnimAttributeValue )
2607 Any aValue1, aValue2;
2608 if( importAttributeValue( pValue, aValue1 ) )
2610 pValue = Atom::findNextChildAtom(pValue);
2611 if( pValue && pValue->getType() == DFF_msofbtAnimAttributeValue )
2612 (void)importAttributeValue( pValue, aValue2 );
2614 bool bCouldBeFormula = false;
2615 bool bHasValue = aValue2.hasValue();
2616 if( bHasValue )
2618 if( aValue2.getValueType() == cppu::UnoType<OUString>::get() )
2620 OUString aTest;
2621 aValue2 >>= aTest;
2622 bHasValue = !aTest.isEmpty();
2623 bCouldBeFormula = true;
2627 if( bHasValue && bCouldBeFormula && (aValue1.getValueType() == cppu::UnoType<double>::get() ))
2629 aValue2 >>= aFormula;
2630 bHasValue = false;
2633 if( bHasValue )
2635 aValues[nKeyTime] = makeAny( ValuePair( aValue1, aValue2 ) );
2637 else
2639 aValues[nKeyTime] = aValue1;
2644 pIter = pAtom->findNextChildAtom(DFF_msofbtAnimKeyTime, pIter);
2647 #ifdef DBG_ANIM_LOG
2648 dump( " keyTimes=\"" );
2649 for( int i=0; i<nKeyTimes; ++i )
2650 dump( "%f;", aKeyTimes[i] );
2652 if( !aFormula.isEmpty() )
2654 dump( "formula=\"%s", aFormula );
2657 dump( "\" values=\"" );
2658 double nVal;
2659 OUString aStr;
2660 for( int i=0; i<nKeyTimes; ++i )
2662 if( i != 0 )
2663 dump( ";" );
2665 if( aValues[i] >>= aStr )
2666 dump( "%s",
2667 OUStringToOString( aStr,
2668 RTL_TEXTENCODING_ASCII_US ).getStr() );
2669 else if( aValues[i] >>= nVal )
2670 dump( "%f", nVal );
2671 else
2673 ValuePair aValuePair;
2675 if( aValues[i] >>= aValuePair )
2677 if( aValuePair.First >>= aStr )
2678 dump( "%s",
2679 OUStringToOString( aStr,
2680 RTL_TEXTENCODING_ASCII_US ).getStr() );
2681 else if( aValuePair.First >>= nVal )
2682 dump( "%f", nVal );
2683 else
2684 dump( "%X", (sal_Int64)&aValuePair.First );
2686 if( aValuePair.Second >>= aStr )
2687 dump( ",%s",
2688 OUStringToOString( aStr,
2689 RTL_TEXTENCODING_ASCII_US ).getStr() );
2690 else if( aValuePair.Second >>= nVal )
2691 dump( ",%f", nVal );
2692 else
2693 dump( ",%X", (sal_Int64)&aValuePair.Second );
2697 dump( "\"" );
2698 #endif
2700 xAnim->setKeyTimes( aKeyTimes );
2701 xAnim->setValues( aValues );
2702 xAnim->setFormula( aFormula );
2706 bool AnimationImporter::importAttributeValue( const Atom* pAtom, Any& rAny )
2708 DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimAttributeValue, "invalid call to ppt::AnimationImporter::importAttributeValue()!" );
2710 bool bOk = false;
2712 if( pAtom && pAtom->seekToContent() )
2714 sal_uInt32 nRecLen = pAtom->getLength();
2715 if ( nRecLen >= 1 )
2717 sal_Int8 nType;
2718 mrStCtrl.ReadSChar( nType );
2719 switch( nType )
2721 case DFF_ANIM_PROP_TYPE_BYTE :
2723 if ( nRecLen == 2 )
2725 sal_uInt8 nByte;
2726 mrStCtrl.ReadUChar( nByte );
2727 rAny <<= nByte;
2729 bOk = true;
2732 break;
2734 case DFF_ANIM_PROP_TYPE_INT32 :
2736 if ( nRecLen == 5 )
2738 sal_uInt32 nInt32;
2739 mrStCtrl.ReadUInt32( nInt32 );
2740 rAny <<= nInt32;
2742 bOk = true;
2745 break;
2747 case DFF_ANIM_PROP_TYPE_FLOAT:
2749 if( nRecLen == 5 )
2751 float fFloat;
2752 mrStCtrl.ReadFloat( fFloat );
2753 rAny <<= (double)fFloat;
2755 bOk = true;
2758 break;
2760 case DFF_ANIM_PROP_TYPE_UNISTRING :
2762 if ( ( nRecLen & 1 ) && ( nRecLen > 1 ) )
2764 OUString aOUString = SvxMSDffManager::MSDFFReadZString( mrStCtrl, nRecLen - 1, true );
2765 rAny <<= aOUString;
2767 bOk = true;
2770 break;
2775 DBG_ASSERT( bOk, "invalid value inside ppt::AnimationImporter::importAttributeValue()!" );
2776 return bOk;
2779 void AnimationImporter::importAnimationEvents( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2781 DBG_ASSERT( xNode.is() && pAtom, "invalid call to ppt::AnimationImporter::importAnimationEvents()!" );
2783 Any aBegin, aEnd, aNext, aPrev;
2785 const Atom* pEventAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimEvent );
2786 while( pEventAtom )
2788 Any* pEvents = NULL;
2790 switch( pEventAtom->getInstance() )
2792 case 1: pEvents = &aBegin; break;
2793 case 2: pEvents = &aEnd; break;
2794 case 3: pEvents = &aNext; break;
2795 case 4: pEvents = &aPrev; break;
2798 if( pEvents )
2800 Event aEvent;
2801 aEvent.Trigger = EventTrigger::NONE;
2802 aEvent.Repeat = 0;
2804 const Atom* pChildAtom = pEventAtom->findFirstChildAtom();
2806 while( pChildAtom && pChildAtom->seekToContent() )
2808 switch( pChildAtom->getType() )
2810 case DFF_msofbtAnimTrigger:
2812 sal_Int32 nU1, nTrigger, nU3, nBegin;
2813 mrStCtrl.ReadInt32( nU1 );
2814 mrStCtrl.ReadInt32( nTrigger );
2815 mrStCtrl.ReadInt32( nU3 );
2816 mrStCtrl.ReadInt32( nBegin );
2818 switch( nTrigger )
2820 case 0: aEvent.Trigger = EventTrigger::NONE; break;
2821 case 1: aEvent.Trigger = EventTrigger::ON_BEGIN; break;
2822 case 2: aEvent.Trigger = EventTrigger::ON_END; break;
2823 case 3: aEvent.Trigger = EventTrigger::BEGIN_EVENT; break;
2824 case 4: aEvent.Trigger = EventTrigger::END_EVENT; break;
2825 case 5: aEvent.Trigger = EventTrigger::ON_CLICK; break;
2826 case 6: aEvent.Trigger = EventTrigger::ON_DBL_CLICK; break;
2827 case 7: aEvent.Trigger = EventTrigger::ON_MOUSE_ENTER; break;
2828 case 8: aEvent.Trigger = EventTrigger::ON_MOUSE_LEAVE; break;
2829 case 9: aEvent.Trigger = EventTrigger::ON_NEXT; break;
2830 case 10: aEvent.Trigger = EventTrigger::ON_PREV; break;
2831 case 11: aEvent.Trigger = EventTrigger::ON_STOP_AUDIO; break;
2834 if( (nBegin != 0) || (aEvent.Trigger == EventTrigger::NONE) )
2835 aEvent.Offset = (nBegin == -1) ? makeAny( Timing_INDEFINITE ) : makeAny( (double)(nBegin / 1000.0) );
2837 break;
2838 case DFF_msofbtAnimateTargetElement:
2840 sal_Int16 nSubType;
2841 importTargetElementContainer( pChildAtom, aEvent.Source, nSubType );
2843 break;
2844 default:
2846 OSL_FAIL("unknown atom inside ppt::AnimationImporter::importAnimationEvents()!");
2850 pChildAtom = Atom::findNextChildAtom( pChildAtom );
2853 *pEvents = addToSequence( *pEvents, (aEvent.Trigger == EventTrigger::NONE) ? aEvent.Offset : makeAny( aEvent ) );
2856 pEventAtom = pAtom->findNextChildAtom( DFF_msofbtAnimEvent, pEventAtom );
2859 xNode->setBegin( aBegin );
2860 xNode->setEnd( aEnd );
2861 // TODO: xNode->setNext( aNext );
2862 // TODO: xNode->setPrev( aNext );
2864 #ifdef DBG_ANIM_LOG
2865 if( aBegin.hasValue() )
2867 dump( " begin=\"" );
2868 dump( aBegin );
2869 dump( "\"" );
2872 if( aEnd.hasValue() )
2874 dump( " end=\"" );
2875 dump( aEnd );
2876 dump( "\"" );
2879 if( aNext.hasValue() )
2881 dump( " next=\"" );
2882 dump( aNext );
2883 dump( "\"" );
2886 if( aPrev.hasValue() )
2888 dump( " prev=\"" );
2889 dump( aPrev );
2890 dump( "\"" );
2892 #endif
2895 void AnimationImporter::importAnimationActions( const Atom* pAtom, const Reference< XAnimationNode >& xNode )
2897 DBG_ASSERT( pAtom && xNode.is(), "invalid call to ppt::AnimationImporter::importAnimationActions()!");
2899 if( pAtom )
2901 const Atom* pActionAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimAction );
2903 if( pActionAtom && pActionAtom->seekToContent() )
2905 sal_Int32 nConcurrent, nNextAction, nEndSync, nU4, nU5;
2906 mrStCtrl.ReadInt32( nConcurrent );
2907 mrStCtrl.ReadInt32( nNextAction );
2908 mrStCtrl.ReadInt32( nEndSync );
2909 mrStCtrl.ReadInt32( nU4 );
2910 mrStCtrl.ReadInt32( nU5 );
2912 if( nEndSync == 1 )
2913 xNode->setEndSync( makeAny( AnimationEndSync::ALL ) );
2915 #ifdef DBG_ANIM_LOG
2916 dump( " concurrent=\"%s\"", nConcurrent == 0 ? "disabled" : (nConcurrent == 1 ? "enabled" : "unknown") );
2918 dump( " nextAction=\"%s\"", nNextAction == 0 ? "none" : (nNextAction == 1 ? "seek" : "unknown") );
2920 if( nEndSync != 0 )
2922 dump( " endSync=\"%s\"", nEndSync == 1 ? "all" : "unknown" );
2925 dump( " action_4=\"%#lx\"", nU4 );
2926 dump( " action_5=\"%#lx\"", nU5 );
2927 #endif
2932 sal_Int32 AnimationImporter::importTargetElementContainer( const Atom* pAtom, Any& rTarget, sal_Int16& rSubType )
2934 rSubType = ShapeAnimationSubType::AS_WHOLE;
2935 sal_Int32 nRefMode = -1;
2937 DBG_ASSERT( pAtom && (pAtom->getType() == DFF_msofbtAnimateTargetElement), "invalid call to ppt::AnimationImporter::importTargetElementContainer()!" );
2938 if( pAtom )
2940 const Atom* pChildAtom = pAtom->findFirstChildAtom();
2941 while( pChildAtom && pChildAtom->seekToContent() )
2943 switch( pChildAtom->getType() )
2945 case DFF_msofbtAnimReference:
2947 sal_Int32 nRefType,nRefId;
2948 sal_Int32 begin,end;
2949 mrStCtrl.ReadInt32( nRefMode );
2950 mrStCtrl.ReadInt32( nRefType );
2951 mrStCtrl.ReadInt32( nRefId );
2952 mrStCtrl.ReadInt32( begin );
2953 mrStCtrl.ReadInt32( end );
2955 switch( nRefType )
2957 case 1: // shape
2959 SdrObject* pSdrObject = mpPPTImport->getShapeForId( nRefId );
2960 if( pSdrObject == NULL )
2961 break;
2963 rTarget <<= pSdrObject->getUnoShape();
2965 switch( nRefMode )
2967 case 6: rSubType = ShapeAnimationSubType::ONLY_BACKGROUND; break;
2968 case 8: rSubType = ShapeAnimationSubType::ONLY_TEXT; break;
2969 case 2: // one paragraph
2971 if( ((begin == -1) && (end == -1)) || !pSdrObject->ISA( SdrTextObj ) )
2972 break;
2974 SdrTextObj* pTextObj = static_cast< SdrTextObj* >( pSdrObject );
2976 const OutlinerParaObject* pOPO = pTextObj->GetOutlinerParaObject();
2977 if( pOPO == NULL )
2978 break;
2980 const EditTextObject& rEditTextObject = pOPO->GetTextObject();
2982 const sal_Int32 nParaCount = rEditTextObject.GetParagraphCount();
2984 sal_Int32 nPara = 0;
2986 while( (nPara < nParaCount) && (begin > 0) )
2988 sal_Int32 nParaLength = rEditTextObject.GetText( nPara ).getLength() + 1;
2989 begin -= nParaLength;
2990 end -= nParaLength;
2991 nPara++;
2994 if( nPara < nParaCount )
2996 ParagraphTarget aParaTarget;
2997 rTarget >>= aParaTarget.Shape;
2998 /* FIXME: Paragraph should be sal_Int32 as well */
2999 aParaTarget.Paragraph = static_cast<sal_Int16>(nPara);
3000 rTarget = makeAny( aParaTarget );
3002 rSubType = ShapeAnimationSubType::ONLY_TEXT;
3003 dump( " paragraph %d,", (sal_Int32)nPara);
3004 dump( " %d characters", (sal_Int32)end );
3009 break;
3011 case 2: // sound
3013 OUString aSoundURL( mpPPTImport->ReadSound( nRefId ) );
3014 rTarget <<= aSoundURL;
3015 dump( " srcRef=\"%s\"", aSoundURL );
3017 break;
3018 case 3: // audio object
3019 case 4: // video object
3021 SdrObject* pSdrObject = mpPPTImport->getShapeForId( nRefId );
3022 if( pSdrObject == NULL )
3023 break;
3025 rTarget <<= pSdrObject->getUnoShape();
3027 break;
3028 default:
3029 OSL_FAIL("unknown reference type");
3033 break;
3034 case 0x2b01:
3036 sal_Int32 nU1;
3037 mrStCtrl.ReadInt32( nU1 );
3039 break;
3040 default:
3041 OSL_FAIL("unknown atom inside ppt::AnimationImporter::importTargetElementContainer()!");
3042 break;
3045 pChildAtom = Atom::findNextChildAtom( pChildAtom );
3050 return nRefMode;
3053 void AnimationImporter::importPropertySetContainer( const Atom* pAtom, PropertySet& rSet )
3055 DBG_ASSERT( pAtom && (pAtom->getType() == DFF_msofbtAnimPropertySet), "invalid call to ppt::AnimationImporter::importPropertySetContainer()!" );
3057 if( pAtom )
3059 const Atom* pChildAtom = pAtom->findFirstChildAtom();
3060 while( pChildAtom )
3062 if( pChildAtom->getType() == DFF_msofbtAnimAttributeValue )
3064 Any aAny;
3065 (void)importAttributeValue( pChildAtom, aAny );
3066 rSet.maProperties[ pChildAtom->getInstance() ] = aAny;
3068 else
3070 OSL_FAIL("unknown atom inside ppt::AnimationImporter::importPropertySetContainer()!");
3073 pChildAtom = Atom::findNextChildAtom( pChildAtom );
3078 #ifdef DBG_ANIM_LOG
3079 void AnimationImporter::dump_atom_header( const Atom* pAtom, bool bOpen, bool bAppend )
3081 if( pAtom )
3083 const char* pTitle;
3085 switch( pAtom->getType() )
3087 case DFF_msofbtAnimEvent: pTitle = "AnimEvent"; break;
3088 case DFF_msofbtAnimTrigger: pTitle = "AnimTrigger"; break;
3089 case DFF_msofbtAnimateMotion: pTitle = "AnimateMotion"; break;
3090 case DFF_msofbtAnimPropertySet: pTitle = "AnimPropertySet"; break;
3091 case DFF_msofbtAnimateAttributeNames: pTitle = "AnimAttributeName"; break;
3092 case DFF_msofbtAnimAttributeValue: pTitle = "AnimAttributeValue"; break;
3093 case DFF_msofbtAnimGroup: pTitle = "AnimGroup"; break;
3094 case DFF_msofbtAnimNode: pTitle = "AnimNode"; break;
3095 case DFF_msofbtAnimValue: pTitle = "AnimValue"; break;
3096 case DFF_msofbtAnimateFilter: pTitle = "animateFilter"; break;
3097 case DFF_msofbtAnimate: pTitle = "animate"; break;
3098 case DFF_msofbtAnimateSet: pTitle = "set"; break;
3099 case DFF_msofbtAnimKeyTime: pTitle = "AnimKeyTime"; break;
3100 case DFF_msofbtAnimKeyPoints: pTitle = "AnimKeyPoints"; break;
3101 case DFF_msofbtAnimReference: pTitle = "AnimReference"; break;
3102 case DFF_msofbtAnimateTargetElement: pTitle = "AnimTargetElementContainer"; break;
3103 case DFF_msofbtAnimAction: pTitle = "AnimAction"; break;
3104 case DFF_msofbtAnimCommand: pTitle = "AnimCommand"; break;
3105 case DFF_msofbtAnimateTarget: pTitle = "TransformationTarget"; break;
3106 case DFF_msofbtAnimateTargetSettings: pTitle = "TransformationTargetSettings"; break;
3107 case DFF_msofbtAnimIteration: pTitle = "iterate"; break;
3108 case DFF_msofbtAnimateColorData: pTitle = "colorData"; break;
3109 case DFF_msofbtAnimateScaleData: pTitle = "scaleData"; break;
3110 case DFF_msofbtAnimateSetData: pTitle = "setData"; break;
3112 default:
3114 static char buffer[128];
3115 sprintf( buffer, "unknown_%#x", pAtom->getType() );
3116 pTitle = buffer;
3120 if( bOpen )
3122 fprintf(mpFile, "<%s", pTitle );
3124 fprintf(mpFile, " instance=\"%hu\"%s",
3125 pAtom->getInstance(),
3126 bAppend ? "" : ">\n");
3128 else
3130 if( bAppend )
3131 fprintf(mpFile,"/>\n");
3132 else
3133 fprintf(mpFile, "</%s>\n", pTitle );
3138 void AnimationImporter::dump( sal_uInt32 nLen, bool bNewLine )
3140 char * faul = "0123456789abcdef";
3142 sal_uInt32 i = 0;
3143 int b = 0;
3144 sal_Int8 nData;
3146 for( i = 0; i < nLen; i++ )
3148 mrStCtrl >> nData;
3150 fprintf( mpFile, "%c%c ", faul[ (nData >> 4) & 0x0f ], faul[ nData & 0x0f ] );
3152 b++;
3153 if( bNewLine && (b == 32) )
3155 fprintf(mpFile,"\n");
3156 b = 0;
3159 if( (b != 0) && bNewLine )
3160 fprintf(mpFile,"\n");
3163 void AnimationImporter::dump_atom( const Atom* pAtom, bool bNewLine )
3165 if( pAtom )
3167 if( pAtom->isContainer() )
3169 const Atom* pChildAtom = pAtom->findFirstChildAtom();
3170 while( pChildAtom )
3172 if( pChildAtom->getType() == DFF_msofbtAnimAttributeValue )
3174 fprintf(mpFile, "<attributeValue instance=\"%hu\"", pChildAtom->getInstance() );
3176 Any aValue;
3177 if( importAttributeValue( pChildAtom, aValue ) )
3179 sal_Int32 nInt;
3180 OUString aString;
3181 double fDouble;
3183 if( aValue >>= nInt )
3185 fprintf(mpFile, " value=\"%ld\"", nInt );
3187 else if( aValue >>= aString )
3189 fprintf(mpFile, " value=\"%s\"",
3190 OUStringToOString(aString,
3191 RTL_TEXTENCODING_UTF8).getStr());
3193 else if( aValue >>= fDouble )
3195 fprintf(mpFile, " value=\"%g\"", fDouble );
3198 else
3200 if( pChildAtom->seekToContent() )
3202 fprintf(mpFile, " value=\"" );
3203 dump_atom( pChildAtom, false );
3204 fprintf(mpFile, "\"");
3208 fprintf(mpFile, "/>\n" );
3210 else
3212 dump_atom_header( pChildAtom, true, pChildAtom->getType() == DFF_msofbtAnimAttributeValue );
3213 dump_atom( pChildAtom );
3214 dump_atom_header( pChildAtom, false, pChildAtom->getType() == DFF_msofbtAnimAttributeValue );
3217 pChildAtom = Atom::findNextChildAtom(pChildAtom);
3220 else if( pAtom->seekToContent() )
3222 dump( pAtom->getLength(), bNewLine );
3227 void AnimationImporter::dump_anim_group( const Atom* pAtom, const AnimationNode& rNode, const PropertySet& rSet, bool bOpen )
3229 fprintf( mpFile, bOpen ? "<" : "</" );
3231 switch( rNode.mnGroupType )
3233 case mso_Anim_GroupType_PAR:
3234 fprintf( mpFile, "par" );
3235 break;
3236 case mso_Anim_GroupType_SEQ:
3237 fprintf( mpFile, "seq" );
3238 break;
3239 case mso_Anim_GroupType_NODE:
3240 switch( rNode.mnNodeType )
3242 case mso_Anim_Behaviour_FILTER:
3243 fprintf( mpFile, "animateFilter" );
3244 break;
3245 case mso_Anim_Behaviour_ANIMATION:
3246 if( pAtom->hasChildAtom( DFF_msofbtAnimateSet ) )
3247 fprintf( mpFile, "set" );
3248 else if( pAtom->hasChildAtom( DFF_msofbtAnimateColor ) )
3249 fprintf( mpFile, "animateColor" );
3250 else if( pAtom->hasChildAtom( DFF_msofbtAnimateScale ) )
3251 fprintf( mpFile, "animateScale" );
3252 else if( pAtom->hasChildAtom( DFF_msofbtAnimateRotation ) )
3253 fprintf( mpFile, "animateRotation" );
3254 else if( pAtom->hasChildAtom( DFF_msofbtAnimateMotion ) )
3255 fprintf( mpFile, "animateMotion" );
3256 else if( pAtom->hasChildAtom( DFF_msofbtAnimCommand ) )
3257 fprintf( mpFile, "command" );
3258 else
3259 fprintf( mpFile, "animation" );
3260 break;
3261 default:
3263 fprintf( mpFile, "unknown_node_%#lx", rNode.mnNodeType );
3265 break;
3267 break;
3268 case mso_Anim_GroupType_MEDIA:
3269 fprintf( mpFile, "media" );
3270 break;
3271 default:
3272 fprintf( mpFile, "unknown_group_%#lx", rNode.mnGroupType );
3273 break;
3276 if( bOpen )
3278 dump( rNode );
3279 dump( rSet );
3282 fprintf(mpFile,">\n");
3285 void AnimationImporter::dump( const AnimationNode& rNode )
3287 // dump animation node
3288 if( rNode.mnRestart != 0 )
3290 fprintf(mpFile," restart=\"%s\"",
3291 rNode.mnRestart == 1 ? "always" : (rNode.mnRestart == 2 ? "whenOff" : (rNode.mnRestart == 3 ? "never" : "unknown")) );
3294 if( rNode.mnFill )
3296 fprintf(mpFile," fill=\"%s\"",
3297 rNode.mnFill == 1 ? "remove" : (rNode.mnFill == 3 ? "hold" : (rNode.mnFill == 2 ? "freeze" : "unknown")) );
3300 if( rNode.mnDuration > 0 )
3302 double fSeconds = rNode.mnDuration;
3303 fSeconds /= 1000.0;
3304 fprintf(mpFile, " dur=\"%g\"", fSeconds);
3306 else if( rNode.mnDuration < 0 )
3308 fprintf(mpFile, " dur=\"indefinite\"" );
3311 if( rNode.mnU1 ) fprintf(mpFile," u1=\"%#lx\"", rNode.mnU1);
3312 if( rNode.mnU3 ) fprintf(mpFile," u3=\"%#lx\"", rNode.mnU3);
3313 if( rNode.mnU4 ) fprintf(mpFile," u4=\"%#lx\"", rNode.mnU4);
3316 void AnimationImporter::dump( Any& rAny )
3318 Sequence< Any > aSeq;
3319 sal_Int32 nInt;
3320 double fDouble;
3321 OUString aString;
3322 sal_Bool bBool;
3323 Event aEvent;
3324 Timing aTiming;
3326 if( rAny >>= aSeq )
3328 const sal_Int32 nSize = aSeq.getLength();
3329 sal_Int32 nIndex = 0;
3330 while( nIndex < nSize )
3332 dump( aSeq[nIndex++] );
3333 if(nIndex < nSize)
3334 fprintf( mpFile, "," );
3337 else if( rAny >>= aString )
3339 fprintf( mpFile, "%s", OUStringToOString(aString,
3340 RTL_TEXTENCODING_UTF8).getStr() );
3342 else if( rAny >>= nInt )
3344 fprintf( mpFile, "%ld", nInt );
3346 else if( rAny >>= bBool )
3348 fprintf( mpFile, "%s", bBool ? "true" : "false" );
3350 else if( rAny >>= fDouble )
3352 fprintf( mpFile, "%g", fDouble );
3354 else if( rAny >>= aTiming )
3356 fprintf( mpFile, "%s", aTiming == (Timing_INDEFINITE) ? "indefinite" : "media" );
3358 else if( rAny >>= aEvent )
3360 static const char* triggers[] =
3362 "none","onbegin","onend","begin",
3363 "end","onclick","ondoubleclick","onmouseenter",
3364 "onmouseleave","onpptnext","onpptprev","onstopaudio"
3367 if( aEvent.Trigger != EventTrigger::NONE )
3369 if( aEvent.Source.hasValue() )
3371 dump_target( aEvent.Source );
3372 dump( "." );
3375 dump( triggers[ aEvent.Trigger ] );
3378 if( aEvent.Offset.hasValue() )
3380 double fOffset;
3381 if( aEvent.Offset >>= fOffset )
3382 fprintf( mpFile, "%g", fOffset );
3383 else
3384 dump( "indefinite" );
3389 void AnimationImporter::dump( const PropertySet& rSet )
3391 // dump property set
3393 map< sal_Int32, Any >::const_iterator aIter( rSet.maProperties.begin() );
3394 const map< sal_Int32, Any >::const_iterator aEnd( rSet.maProperties.end() );
3395 while( aIter != aEnd )
3397 bool bKnown = false;
3399 const sal_Int32 nInstance = (*aIter).first;
3400 Any aAny( (*aIter).second );
3402 switch ( nInstance )
3404 case DFF_ANIM_COLORSPACE:
3406 sal_Int32 nColorSpace;
3407 if( aAny >>= nColorSpace )
3409 fprintf( mpFile, " colorSpace=\"%s\"", (nColorSpace == 0) ? "rgb" : (nColorSpace == 1) ? "hsl" : "unknown" );
3410 bKnown = true;
3413 break;
3415 case DFF_ANIM_DIRECTION:
3417 sal_Bool bDirection;
3418 if( aAny >>= bDirection )
3420 fprintf( mpFile, " direction=\"%s\"", bDirection ? "cclockwise" : "clockwise" );
3421 bKnown = true;
3423 else
3425 sal_Int32 nMasterRel;
3426 if( aAny >>= nMasterRel )
3428 fprintf( mpFile, " direction=\"%s\"", nMasterRel == 0 ? "sameClick" : ( nMasterRel == 2 ? "nextClick" : "lastClick" ) );
3429 bKnown = true;
3433 break;
3435 case DFF_ANIM_OVERRIDE: // TODO
3437 sal_Int32 nOverride;
3438 if( aAny >>= nOverride )
3440 fprintf( mpFile, " override=\"%s\"", (nOverride == 1) ? "childStyle" : (nOverride == 0) ? "normal" : "unknown" );
3441 bKnown = true;
3444 break;
3446 case DFF_ANIM_PATH_EDIT_MODE:
3448 sal_Bool bPathEditMode;
3449 if( aAny >>= bPathEditMode )
3451 fprintf( mpFile, " pptPathEditMode=\"%s\"", bPathEditMode ? "relative" : "fixed" );
3452 bKnown = true;
3455 break;
3457 case DFF_ANIM_PRESET_ID :
3459 sal_Int32 nPresetId ;
3460 if( aAny >>= nPresetId )
3462 fprintf(mpFile, " presetid=\"%ld\"", nPresetId );
3463 bKnown = true;
3466 break;
3468 case DFF_ANIM_PRESET_SUB_TYPE :
3470 sal_Int32 nPointsType ;
3471 if( aAny >>= nPointsType )
3473 fprintf(mpFile, " presetSubType=\"%ld\"", nPointsType );
3474 bKnown = true;
3477 break;
3479 case DFF_ANIM_PRESET_CLASS :
3481 sal_Int32 nPresetClass;
3482 if ( aAny >>= nPresetClass )
3484 const char* pMode;
3485 switch( nPresetClass )
3487 case DFF_ANIM_PRESS_CLASS_USER_DEFINED: pMode = "userdefined"; break;
3488 case DFF_ANIM_PRESS_CLASS_ENTRANCE: pMode = "entrance"; break;
3489 case DFF_ANIM_PRESS_CLASS_EXIT: pMode = "exit"; break;
3490 case DFF_ANIM_PRESS_CLASS_EMPHASIS: pMode = "emphasis"; break;
3491 case DFF_ANIM_PRESS_CLASS_MOTIONPATH: pMode = "motionpath"; break;
3492 case DFF_ANIM_PRESS_CLASS_OLE_ACTION: pMode = "oleaction"; break;
3493 case DFF_ANIM_PRESS_CLASS_MEDIACALL: pMode = "mediacall"; break;
3494 default:
3496 static char buffer[128];
3497 sprintf( buffer, "%ld", nPresetClass );
3498 pMode = buffer;
3500 break;
3503 fprintf(mpFile, " class=\"%s\"", pMode);
3504 bKnown = true;
3507 break;
3509 case DFF_ANIM_NODE_TYPE :
3511 sal_Int32 nNodeType;
3512 if ( aAny >>= nNodeType )
3514 const char* pNode;
3515 switch( nNodeType )
3517 case DFF_ANIM_NODE_TYPE_ON_CLICK: pNode = "onclick"; break;
3518 case DFF_ANIM_NODE_TYPE_WITH_PREVIOUS: pNode = "withprevious"; break;
3519 case DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS: pNode = "afterprevious"; break;
3520 case DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE: pNode = "mainsequence"; break;
3521 case DFF_ANIM_NODE_TYPE_TIMING_ROOT: pNode = "timingroot"; break;
3522 case DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ:pNode = "interactivesequence"; break;
3523 default :
3525 static char buffer[128];
3526 sprintf( buffer, "%ld", nNodeType );
3527 pNode = buffer;
3529 break;
3532 fprintf(mpFile, " nodeType=\"%s\"", pNode);
3533 bKnown = true;
3536 break;
3538 case DFF_ANIM_GROUP_ID:
3540 sal_Int32 nGroupId;
3541 if ( aAny >>= nGroupId )
3543 fprintf( mpFile, " groupId=\"%ld\"", nGroupId );
3544 bKnown = true;
3547 break;
3549 case DFF_ANIM_ID:
3551 OUString aString;
3552 if( aAny >>= aString )
3554 fprintf( mpFile, " id=\"%s\"",
3555 OUStringToOString(aString,
3556 RTL_TEXTENCODING_UTF8).getStr() );
3557 bKnown = true;
3560 break;
3562 case DFF_ANIM_EVENT_FILTER:
3564 OUString aString;
3565 if( aAny >>= aString )
3567 fprintf( mpFile, " eventFilter=\"%s\"",
3568 OUStringToOString(aString,
3569 RTL_TEXTENCODING_UTF8).getStr() );
3570 bKnown = true;
3573 break;
3575 case DFF_ANIM_ENDAFTERSLIDE:
3577 sal_Int32 nEndAfterSlide;
3578 if( aAny >>= nEndAfterSlide )
3580 fprintf(mpFile, " endAfterSlide=\"%ld\"", nEndAfterSlide );
3581 bKnown = true;
3585 case DFF_ANIM_TIMEFILTER:
3587 OUString aString;
3588 if( aAny >>= aString )
3590 fprintf( mpFile, " timeFilter=\"%s\"",
3591 OUStringToOString(aString,
3592 RTL_TEXTENCODING_UTF8).getStr() );
3593 bKnown = true;
3596 break;
3598 case DFF_ANIM_RUNTIMECONTEXT:
3600 OUString aString;
3601 if( aAny >>= aString )
3603 fprintf( mpFile, " runtimeContext=\"%s\"",
3604 OUStringToOString(aString,
3605 RTL_TEXTENCODING_UTF8).getStr() );
3606 bKnown = true;
3609 break;
3611 case DFF_ANIM_VOLUME:
3613 double fVolume(0.0);
3614 if( aAny >>= fVolume )
3616 fprintf( mpFile, " volume=\"%g%%\"", (double)(fVolume * 100.0) );
3617 bKnown = true;
3620 break;
3622 case DFF_ANIM_AFTEREFFECT:
3624 sal_Bool bAfterEffect;
3625 if( aAny >>= bAfterEffect )
3627 fprintf( mpFile, "afterEffect=\"%s\"", bAfterEffect ? "true" : "false" );
3628 bKnown = true;
3631 break;
3635 if( !bKnown )
3637 fprintf( mpFile, " unknown_%lu=\"", nInstance );
3638 dump( aAny );
3639 fprintf( mpFile, "\"" );
3642 ++aIter;
3646 void AnimationImporter::dump_target( Any& rAny )
3648 Any aSource, aSourceData;
3649 Sequence< Any > aSeq;
3650 if( rAny >>= aSeq )
3652 if( aSeq.getLength() >= 1 ) aSource = aSeq[0];
3653 if( aSeq.getLength() >= 2 ) aSourceData = aSeq[1];
3655 else
3657 aSource = rAny;
3660 Reference< XShape > xShape;
3661 aSource >>= xShape;
3662 if( xShape.is() )
3664 OUString aStr( xShape->getShapeType() );
3665 dump( aStr );
3667 if( aSourceData.hasValue() )
3669 dump( "(" );
3670 dump( aSourceData );
3671 dump( ")" );
3676 void AnimationImporter::dump( const char * pText )
3678 fprintf( mpFile, "%s", pText );
3681 void AnimationImporter::dump( const OUString& rString )
3683 fprintf( mpFile, OUStringToOString(rString,
3684 RTL_TEXTENCODING_UTF8).getStr() );
3687 void AnimationImporter::dump( const char * pText, sal_Int64 nInt )
3689 fprintf( mpFile, pText, nInt );
3692 void AnimationImporter::dump( const char * pText, sal_Int32 nInt )
3694 fprintf( mpFile, pText, nInt );
3697 void AnimationImporter::dump( const char * pText, double fDouble )
3699 fprintf( mpFile, pText, fDouble );
3702 void AnimationImporter::dump( const char * pText, const char * pText2 )
3704 fprintf( mpFile, pText, pText2 );
3707 void AnimationImporter::dump( const char * pText, const OUString& rString )
3709 fprintf( mpFile, pText, OUStringToOString(rString,
3710 RTL_TEXTENCODING_UTF8).getStr() );
3713 #else
3715 void AnimationImporter::dump_atom_header( const Atom* , bool , bool )
3719 void AnimationImporter::dump_atom( const Atom* , bool )
3723 void AnimationImporter::dump_target( ::com::sun::star::uno::Any& )
3727 void AnimationImporter::dump( ::com::sun::star::uno::Any& )
3731 void AnimationImporter::dump( const PropertySet& )
3735 void AnimationImporter::dump( const AnimationNode& )
3739 void AnimationImporter::dump( const char * )
3743 void AnimationImporter::dump( const char * , sal_Int32 )
3747 void AnimationImporter::dump( const char * , double )
3751 void AnimationImporter::dump( const char * , const char * )
3755 void AnimationImporter::dump( const char * , const OUString& )
3759 #endif
3761 } // namespace ppt;
3763 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */