1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
27 #include <com/sun/star/animations/AnimationFill.hpp>
28 #include <com/sun/star/animations/AnimationRestart.hpp>
29 #include <com/sun/star/animations/Timing.hpp>
30 #include <com/sun/star/animations/Event.hpp>
31 #include <com/sun/star/animations/AnimationEndSync.hpp>
32 #include <com/sun/star/animations/EventTrigger.hpp>
33 #include <com/sun/star/presentation/EffectNodeType.hpp>
34 #include <com/sun/star/presentation/EffectPresetClass.hpp>
35 #include <com/sun/star/animations/AnimationNodeType.hpp>
36 #include <com/sun/star/animations/AnimationTransformType.hpp>
37 #include <com/sun/star/animations/AnimationCalcMode.hpp>
38 #include <com/sun/star/animations/AnimationValueType.hpp>
39 #include <com/sun/star/util/XCloneable.hpp>
40 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
41 #include <com/sun/star/animations/XAnimateSet.hpp>
42 #include <com/sun/star/animations/XAudio.hpp>
43 #include <com/sun/star/animations/XTransitionFilter.hpp>
44 #include <com/sun/star/animations/XAnimateColor.hpp>
45 #include <com/sun/star/animations/XAnimateMotion.hpp>
46 #include <com/sun/star/animations/XAnimateTransform.hpp>
47 #include <com/sun/star/animations/TransitionType.hpp>
48 #include <com/sun/star/animations/TransitionSubType.hpp>
49 #include <com/sun/star/animations/ValuePair.hpp>
50 #include <com/sun/star/animations/AnimationColorSpace.hpp>
51 #include <com/sun/star/beans/NamedValue.hpp>
52 #include <com/sun/star/drawing/FillStyle.hpp>
53 #include <com/sun/star/drawing/LineStyle.hpp>
54 #include <com/sun/star/awt/FontWeight.hpp>
55 #include <com/sun/star/awt/FontUnderline.hpp>
56 #include <com/sun/star/awt/FontSlant.hpp>
57 #include <com/sun/star/container/XEnumerationAccess.hpp>
58 #include <com/sun/star/presentation/ParagraphTarget.hpp>
59 #include <com/sun/star/text/XSimpleText.hpp>
60 #include <com/sun/star/animations/XIterateContainer.hpp>
61 #include <com/sun/star/presentation/TextAnimationType.hpp>
62 #include <com/sun/star/container/XChild.hpp>
63 #include <comphelper/processfactory.hxx>
64 #include <rtl/ustrbuf.hxx>
65 #ifndef _RTL_MEMORY_H_
66 #include <rtl/memory.hxx>
67 #endif
68
69 #include <vcl/vclenum.hxx>
70 #include <svx/svdotext.hxx>
71 #include <editeng/outlobj.hxx>
72 #include <editeng/editobj.hxx>
73 #include <pptexanimations.hxx>
74 #include <osl/endian.h>
75
76 #include <algorithm>
77
78 using ::std::map;
79 using ::rtl::OUString;
80 using ::rtl::OUStringBuffer;
81 using ::com::sun::star::uno::Any;
82 using ::com::sun::star::container::XChild;
83 using ::com::sun::star::util::XCloneable;
84 using ::com::sun::star::uno::Reference;
85 using ::com::sun::star::uno::UNO_QUERY;
86 using ::com::sun::star::uno::UNO_QUERY_THROW;
87 using ::com::sun::star::uno::Sequence;
88 using ::com::sun::star::uno::makeAny;
89 using ::com::sun::star::uno::Exception;
90 using ::com::sun::star::uno::XInterface;
91 using ::com::sun::star::beans::NamedValue;
92 using ::com::sun::star::container::XEnumerationAccess;
93 using ::com::sun::star::container::XEnumeration;
94 using ::com::sun::star::lang::XMultiServiceFactory;
95
96 using namespace ::com::sun::star::text;
97 using namespace ::com::sun::star::drawing;
98 using namespace ::com::sun::star::animations;
99 using namespace ::com::sun::star::presentation;
100
101 namespace ppt
102 {
103
ImplTranslateAttribute(rtl::OUString & rString,const TranslateMode eTranslateMode)104 void ImplTranslateAttribute( rtl::OUString& rString, const TranslateMode eTranslateMode )
105 {
106 if ( eTranslateMode != TRANSLATE_NONE )
107 {
108 if ( ( eTranslateMode & TRANSLATE_VALUE ) || ( eTranslateMode & TRANSLATE_ATTRIBUTE ) )
109 {
110 const ImplAttributeNameConversion* p = gImplConversionList;
111 while( p->mpAPIName )
112 {
113 if( rString.compareToAscii( p->mpAPIName ) == 0 )
114 break;
115 p++;
116 }
117 if( p->mpMSName )
118 {
119 if ( eTranslateMode & TRANSLATE_VALUE )
120 {
121 rString = rtl::OUString( (sal_Unicode)'#' );
122 rString += OUString::createFromAscii( p->mpMSName );
123 }
124 else
125 rString = OUString::createFromAscii( p->mpMSName );
126 }
127 }
128 else if ( eTranslateMode & TRANSLATE_MEASURE )
129 {
130 const sal_Char* pDest[] = { "#ppt_x", "#ppt_y", "#ppt_w", "#ppt_h", NULL };
131 const sal_Char* pSource[] = { "x", "y", "width", "height", NULL };
132 sal_Int32 nIndex = 0;
133
134 const sal_Char** ps = pSource;
135 const sal_Char** pd = pDest;
136
137 while( *ps )
138 {
139 const OUString aSearch( OUString::createFromAscii( *ps ) );
140 while( (nIndex = rString.indexOf( aSearch, nIndex )) != -1 )
141 {
142 sal_Int32 nLength = aSearch.getLength();
143 if( nIndex && (rString.getStr()[nIndex-1] == '#' ) )
144 {
145 nIndex--;
146 nLength++;
147 }
148
149 const OUString aNew( OUString::createFromAscii( *pd ) );
150 rString = rString.replaceAt( nIndex, nLength, aNew );
151 nIndex += aNew.getLength();
152 }
153 ps++;
154 pd++;
155 }
156 }
157 }
158 }
159
ImplTranslatePresetSubType(const sal_uInt32 nPresetClass,const sal_uInt32 nPresetId,const rtl::OUString & rPresetSubType)160 sal_uInt32 ImplTranslatePresetSubType( const sal_uInt32 nPresetClass, const sal_uInt32 nPresetId, const rtl::OUString& rPresetSubType )
161 {
162 sal_uInt32 nPresetSubType = 0;
163 sal_Bool bTranslated = sal_False;
164
165 if ( ( nPresetClass == (sal_uInt32)EffectPresetClass::ENTRANCE ) || ( nPresetClass == (sal_uInt32)EffectPresetClass::EXIT ) )
166 {
167 if ( nPresetId != 21 )
168 {
169 switch( nPresetId )
170 {
171 case 5 :
172 {
173 if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "downward" ) ) )
174 {
175 nPresetSubType = 5;
176 bTranslated = sal_True;
177 }
178 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "across" ) ) )
179 {
180 nPresetSubType = 10;
181 bTranslated = sal_True;
182 }
183 }
184 break;
185 case 17 :
186 {
187 if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "across" ) ) )
188 {
189 nPresetSubType = 10;
190 bTranslated = sal_True;
191 }
192 }
193 break;
194 case 18 :
195 {
196 if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "right-to-top" ) ) )
197 {
198 nPresetSubType = 3;
199 bTranslated = sal_True;
200 }
201 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "right-to-bottom" ) ) )
202 {
203 nPresetSubType = 6;
204 bTranslated = sal_True;
205 }
206 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "left-to-top" ) ) )
207 {
208 nPresetSubType = 9;
209 bTranslated = sal_True;
210 }
211 else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "left-to-bottom" ) ) )
212 {
213 nPresetSubType = 12;
214 bTranslated = sal_True;
215 }
216 }
217 break;
218 }
219 }
220 if ( !bTranslated )
221 {
222 const convert_subtype* p = gConvertArray;
223 while( p->mpStrSubType )
224 {
225 if ( rPresetSubType.equalsAscii( p->mpStrSubType ) )
226 {
227 nPresetSubType = p->mnID;
228 bTranslated = sal_True;
229 break;
230 }
231 p++;
232 }
233 }
234 }
235 if ( !bTranslated )
236 nPresetSubType = (sal_uInt32)rPresetSubType.toInt32();
237 return nPresetSubType;
238 }
239
find(const sal_Int16 nType,const sal_Int16 nSubType,const sal_Bool bDirection)240 const sal_Char* transition::find( const sal_Int16 nType, const sal_Int16 nSubType, const sal_Bool bDirection )
241 {
242 const sal_Char* pRet = NULL;
243 int nFit = 0;
244
245 const transition* p = gTransitions;
246 while( p->mpName )
247 {
248 int nF = 0;
249 if ( nType == p->mnType )
250 nF += 4;
251 if ( nSubType == p->mnSubType )
252 nF += 2;
253 if ( bDirection == p->mbDirection )
254 nF += 1;
255 if ( nF > nFit )
256 {
257 pRet = p->mpName;
258 nFit = nF;
259 }
260 if ( nFit == 7 ) // maximum
261 break;
262 p++;
263 }
264 return pRet;
265 }
266
operator <<(SvStream & rOut,AnimationNode & rNode)267 SvStream& operator<<(SvStream& rOut, AnimationNode& rNode )
268 {
269 rOut << rNode.mnU1;
270 rOut << rNode.mnRestart;
271 rOut << rNode.mnGroupType;
272 rOut << rNode.mnFill;
273 rOut << rNode.mnU3;
274 rOut << rNode.mnU4;
275 rOut << rNode.mnDuration;
276 rOut << rNode.mnNodeType;
277
278 return rOut;
279 }
280
AnimationExporter(const EscherSolverContainer & rSolverContainer,ppt::ExSoundCollection & rExSoundCollection)281 AnimationExporter::AnimationExporter( const EscherSolverContainer& rSolverContainer, ppt::ExSoundCollection& rExSoundCollection ) :
282 mrSolverContainer ( rSolverContainer ),
283 mrExSoundCollection ( rExSoundCollection ),
284 mnCurrentGroup(0)
285 {
286 }
287
288 // --------------------------------------------------------------------
289
GetFillMode(const Reference<XAnimationNode> & xNode,const sal_Int16 nFillDefault)290 static sal_Int16 GetFillMode( const Reference< XAnimationNode >& xNode, const sal_Int16 nFillDefault )
291 {
292 sal_Int16 nFill = xNode->getFill();
293 //[bug 119699] <Animation> The animation effect "Emphasis->FlashBulb" play incorrectly in Aoo saves a .ppt to another .ppt and plays the saved one.
294 //[bug 119740] <Animation> The animation effect "Entrance->Flash Once" fails to play in Aoo while Aoo saves a .ppt to another .ppt and plays the saved one.
295 if ((xNode->getType() == AnimationNodeType::ANIMATE)
296 ||(xNode->getType() == AnimationNodeType::SET)
297 ||(xNode->getType() == AnimationNodeType::TRANSITIONFILTER))
298 {
299 if ( nFill == AnimationFill::DEFAULT )
300 return nFill;
301 }
302
303 if ( ( nFill == AnimationFill::DEFAULT ) ||
304 ( nFill == AnimationFill::INHERIT ) )
305 {
306 if ( nFill != AnimationFill::AUTO )
307 nFill = nFillDefault;
308 }
309 if( nFill == AnimationFill::AUTO )
310 {
311 nFill = AnimationFill::REMOVE;
312 sal_Bool bIsIndefiniteTiming = sal_True;
313 Any aAny = xNode->getDuration();
314 if( aAny.hasValue() )
315 {
316 Timing eTiming;
317 if( aAny >>= eTiming )
318 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
319 }
320 if ( bIsIndefiniteTiming )
321 {
322 aAny = xNode->getEnd();
323 if( aAny.hasValue() )
324 {
325 Timing eTiming;
326 if( aAny >>= eTiming )
327 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
328 }
329 if ( bIsIndefiniteTiming )
330 {
331 if ( !xNode->getRepeatCount().hasValue() )
332 {
333 aAny = xNode->getRepeatDuration();
334 if( aAny.hasValue() )
335 {
336 Timing eTiming;
337 if( aAny >>= eTiming )
338 bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
339 }
340 if ( bIsIndefiniteTiming )
341 nFill = AnimationFill::FREEZE;
342 }
343 }
344 }
345 }
346 return nFill;
347 }
348
doexport(const Reference<XDrawPage> & xPage,SvStream & rStrm)349 void AnimationExporter::doexport( const Reference< XDrawPage >& xPage, SvStream& rStrm )
350 {
351 Reference< XAnimationNodeSupplier > xNodeSupplier( xPage, UNO_QUERY );
352 if( xNodeSupplier.is() )
353 {
354 const Reference< XAnimationNode > xRootNode( xNodeSupplier->getAnimationNode() );
355 if( xRootNode.is() )
356 {
357 processAfterEffectNodes( xRootNode );
358 exportNode( rStrm, xRootNode, NULL, DFF_msofbtAnimGroup, 1, 0, sal_False, AnimationFill::AUTO );
359 }
360 }
361 }
362
processAfterEffectNodes(const Reference<XAnimationNode> & xRootNode)363 void AnimationExporter::processAfterEffectNodes( const Reference< XAnimationNode >& xRootNode )
364 {
365 try
366 {
367 Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
368 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
369 while( xEnumeration->hasMoreElements() )
370 {
371 Reference< XAnimationNode > xNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
372
373 Reference< XEnumerationAccess > xEnumerationAccess2( xNode, UNO_QUERY );
374 if ( xEnumerationAccess2.is() )
375 {
376 Reference< XEnumeration > xEnumeration2( xEnumerationAccess2->createEnumeration(), UNO_QUERY_THROW );
377 while( xEnumeration2->hasMoreElements() )
378 {
379 Reference< XAnimationNode > xChildNode( xEnumeration2->nextElement(), UNO_QUERY_THROW );
380
381 Reference< XEnumerationAccess > xEnumerationAccess3( xChildNode, UNO_QUERY_THROW );
382 Reference< XEnumeration > xEnumeration3( xEnumerationAccess3->createEnumeration(), UNO_QUERY_THROW );
383 while( xEnumeration3->hasMoreElements() )
384 {
385 Reference< XAnimationNode > xChildNode2( xEnumeration3->nextElement(), UNO_QUERY_THROW );
386
387 Reference< XEnumerationAccess > xEnumerationAccess4( xChildNode2, UNO_QUERY_THROW );
388 Reference< XEnumeration > xEnumeration4( xEnumerationAccess4->createEnumeration(), UNO_QUERY_THROW );
389 while( xEnumeration4->hasMoreElements() )
390 {
391 Reference< XAnimationNode > xChildNode3( xEnumeration4->nextElement(), UNO_QUERY_THROW );
392
393 switch( xChildNode3->getType() )
394 {
395 // found an after effect
396 case AnimationNodeType::SET:
397 case AnimationNodeType::ANIMATECOLOR:
398 {
399 Reference< XAnimationNode > xMaster;
400
401 Sequence< NamedValue > aUserData( xChildNode3->getUserData() );
402 sal_Int32 nLength = aUserData.getLength();
403 const NamedValue* p = aUserData.getConstArray();
404
405 while( nLength-- )
406 {
407 if( p->Name.equalsAscii( "master-element" ) )
408 {
409 p->Value >>= xMaster;
410 break;
411 }
412 p++;
413 }
414
415 AfterEffectNodePtr pAfterEffectNode( new AfterEffectNode( xChildNode3, xMaster ) );
416 maAfterEffectNodes.push_back( pAfterEffectNode );
417 }
418 break;
419 }
420 }
421 }
422 }
423 }
424 }
425 }
426 catch( Exception& e )
427 {
428 (void)e;
429 DBG_ERROR( "(@CL)AnimationExporter::processAfterEffectNodes(), exception caught!" );
430 }
431 }
432
isAfterEffectNode(const Reference<XAnimationNode> & xNode) const433 bool AnimationExporter::isAfterEffectNode( const Reference< XAnimationNode >& xNode ) const
434 {
435 std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
436 const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
437 while( aIter != aEnd )
438 {
439 if( (*aIter)->mxNode == xNode )
440 return true;
441 aIter++;
442 }
443
444 return false;
445 }
446
hasAfterEffectNode(const Reference<XAnimationNode> & xNode,Reference<XAnimationNode> & xAfterEffectNode) const447 bool AnimationExporter::hasAfterEffectNode( const Reference< XAnimationNode >& xNode, Reference< XAnimationNode >& xAfterEffectNode ) const
448 {
449 std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
450 const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
451 while( aIter != aEnd )
452 {
453 if( (*aIter)->mxMaster == xNode )
454 {
455 xAfterEffectNode = (*aIter)->mxNode;
456 return true;
457 }
458 aIter++;
459 }
460
461 return false;
462 }
463
464 // check if this group only contain empty groups. this may happen when
465 // after effect nodes are not exported at theire original position
isEmptyNode(const Reference<XAnimationNode> & xNode) const466 bool AnimationExporter::isEmptyNode( const Reference< XAnimationNode >& xNode ) const
467 {
468 if( xNode.is() ) switch( xNode->getType() )
469 {
470 case AnimationNodeType::PAR :
471 case AnimationNodeType::SEQ :
472 case AnimationNodeType::ITERATE :
473 {
474 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
475 if( xEnumerationAccess.is() )
476 {
477 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
478 if( xEnumeration.is() )
479 {
480 while( xEnumeration->hasMoreElements() )
481 {
482 Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
483 if( xChildNode.is() && !isEmptyNode( xChildNode ) )
484 return false;
485 }
486 }
487 }
488 }
489 break;
490
491 case AnimationNodeType::SET :
492 case AnimationNodeType::ANIMATECOLOR :
493 return isAfterEffectNode( xNode );
494 default:
495 return false;
496 }
497
498 return true;
499 }
500
exportNode(SvStream & rStrm,Reference<XAnimationNode> xNode,const Reference<XAnimationNode> * pParent,const sal_uInt16 nContainerRecType,const sal_uInt16 nInstance,const sal_Int32 nGroupLevel,const sal_Bool bTakeBackInteractiveSequenceTiming,const sal_Int16 nFDef)501 void AnimationExporter::exportNode( SvStream& rStrm, Reference< XAnimationNode > xNode, const Reference< XAnimationNode >* pParent, const sal_uInt16 nContainerRecType,
502 const sal_uInt16 nInstance, const sal_Int32 nGroupLevel, const sal_Bool bTakeBackInteractiveSequenceTiming, const sal_Int16 nFDef )
503 {
504 if( (nGroupLevel == 4) && isEmptyNode( xNode ) )
505 return;
506
507 if ( ( nContainerRecType == DFF_msofbtAnimGroup ) && ( nGroupLevel == 2 ) && isEmptyNode( xNode ) )
508 return;
509
510 if( nContainerRecType == DFF_msofbtAnimGroup )
511 mnCurrentGroup++;
512
513 sal_Bool bTakeBackInteractiveSequenceTimingForChild = sal_False;
514 sal_Int16 nFillDefault = GetFillMode( xNode, nFDef );
515
516 bool bSkipChildren = false;
517
518 Reference< XAnimationNode > xAudioNode;
519 static sal_uInt32 nAudioGroup;
520
521 {
522 EscherExContainer aContainer( rStrm, nContainerRecType, nInstance );
523 switch( xNode->getType() )
524 {
525 case AnimationNodeType::CUSTOM :
526 {
527 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
528 exportAnimPropertySet( rStrm, xNode );
529 exportAnimEvent( rStrm, xNode, 0 );
530 exportAnimValue( rStrm, xNode, sal_False );
531 }
532 break;
533
534 case AnimationNodeType::PAR :
535 {
536 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
537 exportAnimPropertySet( rStrm, xNode );
538 sal_Int32 nFlags = nGroupLevel == 2 ? 0x10 : 0;
539 if ( bTakeBackInteractiveSequenceTiming )
540 nFlags |= 0x40;
541 exportAnimEvent( rStrm, xNode, nFlags );
542 exportAnimValue( rStrm, xNode, nGroupLevel == 4 );
543 }
544 break;
545
546 case AnimationNodeType::SEQ :
547 {
548 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
549 sal_Int16 nNodeType = exportAnimPropertySet( rStrm, xNode );
550 sal_Int32 nFlags = 12;
551 if ( ( nGroupLevel == 1 ) && ( nNodeType == ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE ) )
552 {
553 nFlags |= 0x20;
554 bTakeBackInteractiveSequenceTimingForChild = sal_True;
555 }
556 exportAnimAction( rStrm, xNode );
557 exportAnimEvent( rStrm, xNode, nFlags );
558 exportAnimValue( rStrm, xNode, sal_False );
559 }
560 break;
561
562 case AnimationNodeType::ITERATE :
563 {
564 {
565 EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
566 AnimationNode aAnim;
567 rtl_zeroMemory( &aAnim, sizeof( aAnim ) );
568 aAnim.mnGroupType = mso_Anim_GroupType_PAR;
569 aAnim.mnNodeType = 1;
570 // attribute Restart
571 switch( xNode->getRestart() )
572 {
573 default:
574 case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
575 case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
576 case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
577 case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
578 }
579 // attribute Fill
580 switch( xNode->getFill() )
581 {
582 default:
583 case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
584 case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
585 case AnimationFill::FREEZE : aAnim.mnFill = 2; break;
586 case AnimationFill::HOLD : aAnim.mnFill = 3; break;
587 case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
588 }
589 rStrm << aAnim;
590 }
591 exportIterate( rStrm, xNode );
592 exportAnimPropertySet( rStrm, xNode );
593 exportAnimEvent( rStrm, xNode, 0 );
594 exportAnimValue( rStrm, xNode, sal_False );
595
596 /*
597 EscherExContainer aContainer( rStrm, DFF_msofbtAnimGroup, 1 );
598 exportAnimNode( rStrm, xNode, pParent, nGroupLevel + 1, nFillDefault );
599 exportAnimPropertySet( rStrm, xNode );
600 exportAnimEvent( rStrm, xNode, 0 );
601 exportAnimValue( rStrm, xNode, sal_False );
602 */
603 }
604 break;
605
606 case AnimationNodeType::ANIMATE :
607 {
608 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
609 exportAnimPropertySet( rStrm, xNode );
610 exportAnimEvent( rStrm, xNode, 0 );
611 exportAnimValue( rStrm, xNode, sal_False );
612 exportAnimate( rStrm, xNode );
613 }
614 break;
615
616 case AnimationNodeType::SET :
617 {
618 bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
619 if( (nGroupLevel != 4) || !bIsAfterEffectNode )
620 {
621 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
622 exportAnimPropertySet( rStrm, xNode );
623 exportAnimateSet( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_SET : AFTEREFFECT_NONE );
624 exportAnimEvent( rStrm, xNode, 0 );
625 exportAnimValue( rStrm, xNode, sal_False );
626 }
627 else
628 {
629 bSkipChildren = true;
630 }
631 }
632 break;
633
634 case AnimationNodeType::ANIMATEMOTION :
635 {
636 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
637 exportAnimPropertySet( rStrm, xNode );
638 exportAnimateMotion( rStrm, xNode );
639 exportAnimEvent( rStrm, xNode, 0 );
640 exportAnimValue( rStrm, xNode, sal_False );
641 }
642 break;
643
644 case AnimationNodeType::ANIMATECOLOR :
645 {
646 bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
647 if( (nGroupLevel != 4) || !bIsAfterEffectNode )
648 {
649 if( bIsAfterEffectNode )
650 xNode = createAfterEffectNodeClone( xNode );
651
652 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
653 exportAnimPropertySet( rStrm, xNode );
654 exportAnimateColor( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_COLOR : AFTEREFFECT_NONE );
655 exportAnimEvent( rStrm, xNode, 0 );
656 exportAnimValue( rStrm, xNode, sal_False );
657 }
658 else
659 {
660 bSkipChildren = true;
661 }
662 }
663 break;
664
665 case AnimationNodeType::ANIMATETRANSFORM :
666 {
667 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
668 exportAnimPropertySet( rStrm, xNode );
669 exportAnimateTransform( rStrm, xNode );
670 exportAnimEvent( rStrm, xNode, 0 );
671 exportAnimValue( rStrm, xNode, sal_False );
672 }
673 break;
674
675 case AnimationNodeType::TRANSITIONFILTER :
676 {
677 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
678 exportAnimPropertySet( rStrm, xNode );
679 exportAnimEvent( rStrm, xNode, 0 );
680 exportAnimValue( rStrm, xNode, sal_False );
681 exportTransitionFilter( rStrm, xNode );
682 }
683 break;
684
685 case AnimationNodeType::AUDIO : // #i58428#
686 {
687 exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
688 exportAnimPropertySet( rStrm, xNode );
689
690 Reference< XAudio > xAudio( xNode, UNO_QUERY );
691 if( xAudio.is() )
692 {
693 Any aAny( xAudio->getSource() );
694 rtl::OUString aURL;
695
696 if ( ( aAny >>= aURL ) && ( aURL.getLength() ) )
697 {
698 sal_Int32 nU1 = 2;
699 sal_Int32 nTrigger = 3;
700 sal_Int32 nU3 = nAudioGroup;
701 sal_Int32 nBegin = 0;
702 {
703 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 1 );
704 {
705 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
706 rStrm << nU1 << nTrigger << nU3 << nBegin;
707 }
708 }
709 nU1 = 1;
710 nTrigger = 0xb;
711 nU3 = 0;
712 {
713 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 2 );
714 {
715 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
716 rStrm << nU1 << nTrigger << nU3 << nBegin;
717 }
718 }
719 EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
720 {
721 sal_uInt32 nRefMode = 3;
722 sal_uInt32 nRefType = 2;
723 sal_uInt32 nRefId = mrExSoundCollection.GetId( aURL );
724 sal_Int32 begin = -1;
725 sal_Int32 end = -1;
726
727 EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
728 rStrm << nRefMode << nRefType << nRefId << begin << end;
729 }
730 }
731 }
732 exportAnimValue( rStrm, xNode, sal_False );
733 }
734 break;
735 }
736 if( !bSkipChildren )
737 {
738 // export after effect node if one exists for this node
739 Reference< XAnimationNode > xAfterEffectNode;
740 if( hasAfterEffectNode( xNode, xAfterEffectNode ) )
741 {
742 exportNode( rStrm, xAfterEffectNode, &xNode, DFF_msofbtAnimSubGoup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
743 }
744
745 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
746 if( xEnumerationAccess.is() )
747 {
748 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
749 if( xEnumeration.is() )
750 {
751 while( xEnumeration->hasMoreElements() )
752 {
753 Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
754 if( xChildNode.is() )
755 {
756 if ( xChildNode->getType() == AnimationNodeType::AUDIO )
757 {
758 xAudioNode = xChildNode;
759 nAudioGroup = mnCurrentGroup;
760 }
761 else
762 exportNode( rStrm, xChildNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
763 }
764 }
765 }
766 }
767 }
768 }
769 if ( xAudioNode.is() )
770 exportNode( rStrm, xAudioNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
771
772 if( xNode->getType() == AnimationNodeType::ITERATE )
773 aTarget = Any();
774 }
775
createAfterEffectNodeClone(const Reference<XAnimationNode> & xNode) const776 Reference< XAnimationNode > AnimationExporter::createAfterEffectNodeClone( const Reference< XAnimationNode >& xNode ) const
777 {
778 try
779 {
780 Reference< ::com::sun::star::util::XCloneable > xClonable( xNode, UNO_QUERY_THROW );
781 Reference< XAnimationNode > xCloneNode( xClonable->createClone(), UNO_QUERY_THROW );
782
783 Any aEmpty;
784 xCloneNode->setBegin( aEmpty );
785
786
787 return xCloneNode;
788 }
789 catch( Exception& e )
790 {
791 (void)e;
792 DBG_ERROR("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
793 }
794 return xNode;
795 }
796
exportAnimNode(SvStream & rStrm,const Reference<XAnimationNode> & xNode,const::com::sun::star::uno::Reference<::com::sun::star::animations::XAnimationNode> *,const sal_Int32,const sal_Int16 nFillDefault)797 void AnimationExporter::exportAnimNode( SvStream& rStrm, const Reference< XAnimationNode >& xNode,
798 const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >*, const sal_Int32, const sal_Int16 nFillDefault )
799 {
800 EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
801 AnimationNode aAnim;
802 rtl_zeroMemory( &aAnim, sizeof( aAnim ) );
803
804 // attribute Restart
805 switch( xNode->getRestart() )
806 {
807 default:
808 case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
809 case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
810 case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
811 case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
812 }
813
814 // attribute Fill
815 // aAnim.mnFill = GetFillMode( xNode, pParent );
816 switch( nFillDefault )
817 {
818 default:
819 case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
820 case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
821 case AnimationFill::FREEZE : // aAnim.mnFill = 2; break;
822 case AnimationFill::HOLD : aAnim.mnFill = 3; break;
823 case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
824 }
825 // attribute Duration
826 double fDuration = 0.0;
827 com::sun::star::animations::Timing eTiming;
828 if ( xNode->getDuration() >>= eTiming )
829 {
830 if ( eTiming == Timing_INDEFINITE )
831 aAnim.mnDuration = -1;
832 }
833 else if ( xNode->getDuration() >>= fDuration )
834 {
835 aAnim.mnDuration = (sal_Int32)( fDuration * 1000.0 );
836 }
837 else
838 aAnim.mnDuration = -1;
839
840 // NodeType, NodeGroup
841 aAnim.mnNodeType = 1;
842 aAnim.mnGroupType = mso_Anim_GroupType_SEQ;
843 switch( xNode->getType() )
844 {
845 case AnimationNodeType::PAR : // PASSTROUGH!!! (as it was intended)
846 aAnim.mnGroupType = mso_Anim_GroupType_PAR;
847 case AnimationNodeType::SEQ :
848 {
849 // trying to get the nodetype
850 Sequence< NamedValue > aUserData = xNode->getUserData();
851 if ( aUserData.getLength() )
852 {
853 const NamedValue* p = aUserData.getConstArray();
854 sal_Int32 nLength = aUserData.getLength();
855 while( nLength-- )
856 {
857 if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) )
858 {
859 sal_Int16 nType = 0;
860 if ( p->Value >>= nType )
861 {
862 switch( nType )
863 {
864 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : aAnim.mnNodeType = 0x12; break;
865 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : aAnim.mnNodeType = 0x18; break;
866 /*
867 case ::com::sun::star::presentation::EffectNodeType::ON_CLICK :
868 case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS :
869 case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS :
870 case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE :
871 default:
872 */
873 }
874 }
875 break;
876 }
877 }
878 }
879 }
880 break;
881
882 case AnimationNodeType::ANIMATE :
883 case AnimationNodeType::SET :
884
885 case AnimationNodeType::CUSTOM :
886 case AnimationNodeType::ITERATE :
887 case AnimationNodeType::ANIMATEMOTION :
888 case AnimationNodeType::ANIMATECOLOR :
889 case AnimationNodeType::ANIMATETRANSFORM :
890 {
891 aAnim.mnGroupType = mso_Anim_GroupType_NODE;
892 aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
893 }
894 break;
895
896 case AnimationNodeType::AUDIO :
897 {
898 aAnim.mnGroupType = mso_Anim_GroupType_MEDIA;
899 aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
900 }
901 break;
902
903 case AnimationNodeType::TRANSITIONFILTER :
904 {
905 aAnim.mnGroupType = mso_Anim_GroupType_NODE;
906 aAnim.mnNodeType = mso_Anim_Behaviour_FILTER;
907 }
908 break;
909 }
910 rStrm << aAnim;
911 }
912
exportAnimPropertySet(SvStream & rStrm,const Reference<XAnimationNode> & xNode)913 sal_Int16 AnimationExporter::exportAnimPropertySet( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
914 {
915 sal_Int16 nNodeType = ::com::sun::star::presentation::EffectNodeType::DEFAULT;
916
917 EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
918 const ::com::sun::star::uno::Any* pAny[ DFF_ANIM_PROPERTY_ID_COUNT ];
919 rtl_zeroMemory( pAny, sizeof( pAny ) );
920
921 Reference< XAnimationNode > xMaster;
922
923 const Any aTrue( makeAny( (sal_Bool)sal_True ) );
924 Any aMasterRel, aOverride, aRunTimeContext;
925
926 // storing user data into pAny, to allow direct access later
927 Sequence< NamedValue > aUserData = xNode->getUserData();
928 if ( aUserData.getLength() )
929 {
930 const NamedValue* p = aUserData.getConstArray();
931 sal_Int32 nLength = aUserData.getLength();
932 while( nLength-- )
933 {
934 if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) )
935 {
936 pAny[ DFF_ANIM_NODE_TYPE ] = &(p->Value);
937 }
938 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-class" ) ) )
939 {
940 pAny[ DFF_ANIM_PRESET_CLASS ] = &(p->Value);
941 }
942 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-id" ) ) )
943 {
944 pAny[ DFF_ANIM_PRESET_ID ] = &(p->Value);
945 }
946 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-sub-type" ) ) )
947 {
948 pAny[ DFF_ANIM_PRESET_SUB_TYPE ] = &(p->Value);
949 }
950 else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "master-element" ) ) )
951 {
952 pAny[ DFF_ANIM_AFTEREFFECT ] = &aTrue;
953 p->Value >>= xMaster;
954 }
955 p++;
956 }
957 }
958
959 // calculate master-rel
960 if( xMaster.is() )
961 {
962 sal_Int32 nMasterRel = 2;
963 Reference< XChild > xNodeChild( xNode, UNO_QUERY );
964 Reference< XChild > xMasterChild( xMaster, UNO_QUERY );
965 if( xNodeChild.is() && xMasterChild.is() && (xNodeChild->getParent() == xMasterChild->getParent() ) )
966 nMasterRel = 0;
967
968 aMasterRel <<= nMasterRel;
969
970 pAny[ DFF_ANIM_MASTERREL ] = &aMasterRel;
971
972 aOverride <<= (sal_Int32)1;
973 pAny[ DFF_ANIM_OVERRIDE ] = &aOverride;
974
975 aRunTimeContext <<= (sal_Int32)1;
976 pAny[ DFF_ANIM_RUNTIMECONTEXT ] = &aRunTimeContext;
977 }
978
979 // the order is important
980 if ( pAny[ DFF_ANIM_NODE_TYPE ] )
981 {
982 if ( *pAny[ DFF_ANIM_NODE_TYPE ] >>= nNodeType )
983 {
984 sal_uInt32 nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK;
985 switch( nNodeType )
986 {
987 case ::com::sun::star::presentation::EffectNodeType::ON_CLICK : nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK; break;
988 case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_WITH_PREVIOUS; break;
989 case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS; break;
990 case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : nPPTNodeType = DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE; break;
991 case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : nPPTNodeType = DFF_ANIM_NODE_TYPE_TIMING_ROOT; break;
992 case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE: nPPTNodeType = DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ; break;
993 }
994 exportAnimPropertyuInt32( rStrm, DFF_ANIM_NODE_TYPE, nPPTNodeType, TRANSLATE_NONE );
995 }
996 }
997 sal_uInt32 nPresetId = 0;
998 sal_uInt32 nPresetSubType = 0;
999 sal_uInt32 nAPIPresetClass = EffectPresetClass::CUSTOM;
1000 sal_uInt32 nPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
1001 sal_Bool bPresetClass, bPresetId, bPresetSubType;
1002 bPresetClass = bPresetId = bPresetSubType = sal_False;
1003
1004 if ( pAny[ DFF_ANIM_PRESET_CLASS ] )
1005 {
1006 if ( *pAny[ DFF_ANIM_PRESET_CLASS ] >>= nAPIPresetClass )
1007 {
1008 sal_uInt8 nPPTPresetClass;
1009 switch( nAPIPresetClass )
1010 {
1011 case EffectPresetClass::ENTRANCE : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_ENTRANCE; break;
1012 case EffectPresetClass::EXIT : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EXIT; break;
1013 case EffectPresetClass::EMPHASIS : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EMPHASIS; break;
1014 case EffectPresetClass::MOTIONPATH : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MOTIONPATH; break;
1015 case EffectPresetClass::OLEACTION : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_OLE_ACTION; break;
1016 case EffectPresetClass::MEDIACALL : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MEDIACALL; break;
1017 default :
1018 nPPTPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
1019 }
1020 nPresetClass = nPPTPresetClass;
1021 bPresetClass = sal_True;
1022 }
1023 }
1024 if ( pAny[ DFF_ANIM_PRESET_ID ] )
1025 {
1026 rtl::OUString sPreset;
1027 if ( *pAny[ DFF_ANIM_PRESET_ID ] >>= sPreset )
1028 {
1029 if ( sPreset.match( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ppt_" ) ), 0 ) )
1030 {
1031 sal_Int32 nLast = sPreset.lastIndexOf( '_' );
1032 if ( ( nLast != -1 ) && ( ( nLast + 1 ) < sPreset.getLength() ) )
1033 {
1034 rtl::OUString aNumber( sPreset.copy( nLast + 1 ) );
1035 nPresetId = aNumber.toInt32();
1036 bPresetId = sal_True;
1037 }
1038 }
1039 else
1040 {
1041 const preset_maping* p = gPresetMaping;
1042 while( p->mpStrPresetId && ((p->mnPresetClass != (sal_Int32)nAPIPresetClass) || !sPreset.equalsAscii( p->mpStrPresetId )) )
1043 p++;
1044
1045 if( p->mpStrPresetId )
1046 {
1047 nPresetId = p->mnPresetId;
1048 bPresetId = sal_True;
1049 }
1050 }
1051 }
1052 }
1053
1054 if ( pAny[ DFF_ANIM_PRESET_SUB_TYPE ] )
1055 {
1056 rtl::OUString sPresetSubType;
1057 if ( *pAny[ DFF_ANIM_PRESET_SUB_TYPE ] >>= sPresetSubType )
1058 {
1059 nPresetSubType = ImplTranslatePresetSubType( nPresetClass, nPresetId, sPresetSubType );
1060 bPresetSubType = sal_True;
1061 }
1062 }
1063 if ( bPresetId )
1064 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_ID, nPresetId, TRANSLATE_NONE );
1065 if ( bPresetSubType )
1066 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_SUB_TYPE, nPresetSubType, TRANSLATE_NONE );
1067 if ( bPresetClass )
1068 exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_CLASS, nPresetClass, TRANSLATE_NONE );
1069
1070 if ( pAny[ DFF_ANIM_ID ] )
1071 {
1072 // TODO DFF_ANIM_ID
1073 }
1074
1075 if ( pAny[ DFF_ANIM_AFTEREFFECT ] )
1076 {
1077 sal_Bool bAfterEffect = sal_False;
1078 if ( *pAny[ DFF_ANIM_AFTEREFFECT ] >>= bAfterEffect )
1079 exportAnimPropertyByte( rStrm, DFF_ANIM_AFTEREFFECT, bAfterEffect, TRANSLATE_NONE );
1080 }
1081
1082 if ( pAny[ DFF_ANIM_RUNTIMECONTEXT ] )
1083 {
1084 sal_Int32 nRunTimeContext = 0;
1085 if ( *pAny[ DFF_ANIM_RUNTIMECONTEXT ] >>= nRunTimeContext )
1086 exportAnimPropertyuInt32( rStrm, DFF_ANIM_RUNTIMECONTEXT, nRunTimeContext, TRANSLATE_NONE );
1087 }
1088 if ( pAny[ DFF_ANIM_PATH_EDIT_MODE ] )
1089 {
1090 // TODO DFF_ANIM_ID
1091 }
1092
1093 if( !xMaster.is() )
1094 {
1095 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
1096 if( xColor.is() )
1097 {
1098 // sal_uInt32 nColorSpace = xColor->getColorSpace() == AnimationColorSpace::RGB ? 0 : 1;
1099 // exportAnimPropertyuInt32( rStrm, DFF_ANIM_COLORSPACE, nColorSpace, TRANSLATE_NONE );
1100
1101 sal_Bool bDirection = !xColor->getDirection();
1102 exportAnimPropertyuInt32( rStrm, DFF_ANIM_DIRECTION, bDirection, TRANSLATE_NONE );
1103 }
1104 }
1105
1106 if ( pAny[ DFF_ANIM_OVERRIDE ] )
1107 {
1108 sal_Int32 nOverride = 0;
1109 if ( *pAny[ DFF_ANIM_OVERRIDE ] >>= nOverride )
1110 exportAnimPropertyuInt32( rStrm, DFF_ANIM_OVERRIDE, nOverride, TRANSLATE_NONE );
1111 }
1112
1113 if ( pAny[ DFF_ANIM_MASTERREL ] )
1114 {
1115 sal_Int32 nMasterRel = 0;
1116 if ( *pAny[ DFF_ANIM_MASTERREL ] >>= nMasterRel )
1117 exportAnimPropertyuInt32( rStrm, DFF_ANIM_MASTERREL, nMasterRel, TRANSLATE_NONE );
1118 }
1119
1120 /* todo
1121 Reference< XAudio > xAudio( xNode, UNO_QUERY );
1122 if( xAudio.is() )
1123 {
1124 sal_Int16 nEndAfterSlide = 0;
1125 nEndAfterSlide = xAudio->getEndAfterSlide();
1126 exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
1127 }
1128 */
1129 Reference< XAnimate > xAnim( xNode, UNO_QUERY );
1130 if( xAnim.is() )
1131 {
1132 // TODO: DFF_ANIM_TIMEFILTER
1133 }
1134 if ( pAny[ DFF_ANIM_EVENT_FILTER ] )
1135 {
1136 // TODO DFF_ANIM_EVENT_FILTER
1137 }
1138 if ( pAny[ DFF_ANIM_VOLUME ] )
1139 {
1140 // TODO DFF_ANIM_VOLUME
1141 }
1142 return nNodeType;
1143 }
1144
exportAnimProperty(SvStream & rStrm,const sal_uInt16 nPropertyId,const::com::sun::star::uno::Any & rAny,const TranslateMode eTranslateMode)1145 sal_Bool AnimationExporter::exportAnimProperty( SvStream& rStrm, const sal_uInt16 nPropertyId, const ::com::sun::star::uno::Any& rAny, const TranslateMode eTranslateMode )
1146 {
1147 sal_Bool bRet = sal_False;
1148 if ( rAny.hasValue() )
1149 {
1150 switch( rAny.getValueType().getTypeClass() )
1151 {
1152 case ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT :
1153 case ::com::sun::star::uno::TypeClass_SHORT :
1154 case ::com::sun::star::uno::TypeClass_UNSIGNED_LONG :
1155 case ::com::sun::star::uno::TypeClass_LONG :
1156 {
1157 sal_Int32 nVal = 0;
1158 if ( rAny >>= nVal )
1159 {
1160 exportAnimPropertyuInt32( rStrm, nPropertyId, nVal, eTranslateMode );
1161 bRet = sal_True;
1162 }
1163 }
1164 break;
1165
1166 case ::com::sun::star::uno::TypeClass_DOUBLE :
1167 {
1168 double fVal = 0.0;
1169 if ( rAny >>= fVal )
1170 {
1171 exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
1172 bRet = sal_True;
1173 }
1174 }
1175 break;
1176 case ::com::sun::star::uno::TypeClass_FLOAT :
1177 {
1178 float fVal = 0.0;
1179 if ( rAny >>= fVal )
1180 {
1181 if ( eTranslateMode & TRANSLATE_NUMBER_TO_STRING )
1182 {
1183 Any aAny;
1184 rtl::OUString aNumber( rtl::OUString::valueOf( fVal ) );
1185 aAny <<= aNumber;
1186 exportAnimPropertyString( rStrm, nPropertyId, aNumber, eTranslateMode );
1187 }
1188 else
1189 {
1190 exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
1191 bRet = sal_True;
1192 }
1193 }
1194 }
1195 break;
1196 case ::com::sun::star::uno::TypeClass_STRING :
1197 {
1198 rtl::OUString aStr;
1199 if ( rAny >>= aStr )
1200 {
1201 exportAnimPropertyString( rStrm, nPropertyId, aStr, eTranslateMode );
1202 bRet = sal_True;
1203 }
1204 }
1205 break;
1206 default:
1207 break;
1208 }
1209 }
1210 return bRet;
1211 }
exportAnimPropertyString(SvStream & rStrm,const sal_uInt16 nPropertyId,const rtl::OUString & rVal,const TranslateMode eTranslateMode)1212 void AnimationExporter::exportAnimPropertyString( SvStream& rStrm, const sal_uInt16 nPropertyId, const rtl::OUString& rVal, const TranslateMode eTranslateMode )
1213 {
1214 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1215 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_UNISTRING;
1216 rStrm << nType;
1217 rtl::OUString aStr( rVal );
1218 if ( eTranslateMode != TRANSLATE_NONE )
1219 ImplTranslateAttribute( aStr, eTranslateMode );
1220 writeZString( rStrm, aStr );
1221 }
1222
exportAnimPropertyFloat(SvStream & rStrm,const sal_uInt16 nPropertyId,const double & rVal,const TranslateMode)1223 void AnimationExporter::exportAnimPropertyFloat( SvStream& rStrm, const sal_uInt16 nPropertyId, const double& rVal, const TranslateMode )
1224 {
1225 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1226 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_FLOAT;
1227 float fFloat = (float)rVal;
1228 rStrm << nType
1229 << fFloat;
1230 }
1231
exportAnimPropertyuInt32(SvStream & rStrm,const sal_uInt16 nPropertyId,const sal_uInt32 nVal,const TranslateMode)1232 void AnimationExporter::exportAnimPropertyuInt32( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt32 nVal, const TranslateMode )
1233 {
1234 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1235 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_INT32 ;
1236 rStrm << nType
1237 << nVal;
1238 }
1239
exportAnimPropertyByte(SvStream & rStrm,const sal_uInt16 nPropertyId,const sal_uInt8 nVal,const TranslateMode)1240 void AnimationExporter::exportAnimPropertyByte( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt8 nVal, const TranslateMode )
1241 {
1242 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
1243 sal_uInt8 nType = DFF_ANIM_PROP_TYPE_BYTE;
1244 rStrm << nType
1245 << nVal;
1246 }
1247
writeZString(SvStream & rStrm,const rtl::OUString & rVal)1248 void AnimationExporter::writeZString( SvStream& rStrm, const rtl::OUString& rVal )
1249 {
1250 sal_Int32 i;
1251 for ( i = 0; i < rVal.getLength(); i++ )
1252 rStrm << rVal[ i ];
1253 rStrm << (sal_Unicode)0;
1254 }
1255
exportAnimAction(SvStream & rStrm,const Reference<XAnimationNode> & xNode)1256 void AnimationExporter::exportAnimAction( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1257 {
1258 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAction );
1259
1260 sal_Int32 nConcurrent = 1;
1261 sal_Int32 nNextAction = 1;
1262 sal_Int32 nEndSync = 0;
1263 sal_Int32 nU4 = 0;
1264 sal_Int32 nU5 = 3;
1265
1266 sal_Int16 nAnimationEndSync = 0;
1267 if ( xNode->getEndSync() >>= nAnimationEndSync )
1268 {
1269 if ( nAnimationEndSync == AnimationEndSync::ALL )
1270 nEndSync = 1;
1271 }
1272 rStrm << nConcurrent
1273 << nNextAction
1274 << nEndSync
1275 << nU4
1276 << nU5;
1277
1278 }
1279
1280 // nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
1281 // nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
1282 // nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
exportAnimEvent(SvStream & rStrm,const Reference<XAnimationNode> & xNode,const sal_Int32 nFlags)1283 void AnimationExporter::exportAnimEvent( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Int32 nFlags )
1284 {
1285 sal_uInt16 i;
1286 for ( i = 0; i < 4; i++ )
1287 {
1288 sal_Int32 nU1 = 0;
1289 sal_Int32 nTrigger = 0;
1290 sal_Int32 nU3 = 0;
1291 sal_Int32 nBegin = 0;
1292
1293 sal_Bool bCreateEvent = sal_False;
1294 Any aSource;
1295
1296 switch( i )
1297 {
1298 case 0 :
1299 case 1 :
1300 {
1301 Any aAny;
1302 Event aEvent;
1303 com::sun::star::animations::Timing eTiming;
1304 if ( i == 0 )
1305 {
1306 if ( nFlags & 0x20 )
1307 {
1308 // taking the first child
1309 Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
1310 Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
1311 if ( xE.is() && xE->hasMoreElements() )
1312 {
1313 // while( xE->hasMoreElements() )
1314 {
1315 Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
1316 aAny = xClickNode->getBegin();
1317 }
1318 }
1319 }
1320 else if ( nFlags & 0x40 )
1321 {
1322 // begin has to be replaced with void, so don't do anything
1323 }
1324 else
1325 {
1326 aAny = xNode->getBegin();
1327 if ( nFlags & 0x10 ) // replace ON_NEXT with IDEFINITE
1328 {
1329 if ( ( aAny >>= aEvent ) && ( aEvent.Trigger == EventTrigger::ON_NEXT ) )
1330 {
1331 eTiming = Timing_INDEFINITE;
1332 aAny <<= eTiming;
1333 }
1334 }
1335 }
1336 }
1337 else
1338 aAny = xNode->getEnd();
1339
1340 double fTiming = 0.0;
1341 if ( aAny >>= aEvent )
1342 {
1343 bCreateEvent = sal_True;
1344 switch( aEvent.Trigger )
1345 {
1346 case EventTrigger::NONE : nTrigger = 0; break;
1347 case EventTrigger::ON_BEGIN : nTrigger = 1; break;
1348 case EventTrigger::ON_END : nTrigger = 2; break;
1349 case EventTrigger::BEGIN_EVENT : nTrigger = 3; break;
1350 case EventTrigger::END_EVENT : nTrigger = 4; nU1 = 2; nU3 = mnCurrentGroup; break;
1351 case EventTrigger::ON_CLICK : nTrigger = 5; break;
1352 case EventTrigger::ON_DBL_CLICK : nTrigger = 6; break;
1353 case EventTrigger::ON_MOUSE_ENTER : nTrigger = 7; break;
1354 case EventTrigger::ON_MOUSE_LEAVE : nTrigger = 8; break;
1355 case EventTrigger::ON_NEXT : nTrigger = 9; break;
1356 case EventTrigger::ON_PREV : nTrigger = 10; break;
1357 case EventTrigger::ON_STOP_AUDIO : nTrigger = 11; break;
1358 }
1359 if ( aEvent.Offset.hasValue() )
1360 {
1361 if ( aEvent.Offset >>= eTiming )
1362 {
1363 if ( eTiming == Timing_INDEFINITE )
1364 nBegin = -1;
1365 }
1366 else if ( aEvent.Offset >>= fTiming )
1367 nBegin = (sal_Int32)( fTiming * 1000.0 );
1368 }
1369 aSource = aEvent.Source;
1370 }
1371 else if ( aAny >>= eTiming )
1372 {
1373 bCreateEvent = sal_True;
1374 if ( eTiming == Timing_INDEFINITE )
1375 nBegin = -1;
1376 }
1377 else if ( aAny >>= fTiming )
1378 {
1379 bCreateEvent = sal_True;
1380 nBegin = (sal_Int32)( fTiming * 1000.0 );
1381 }
1382 }
1383 break;
1384
1385 case 2 :
1386 {
1387 if ( nFlags & ( 1 << i ) )
1388 {
1389 bCreateEvent = sal_True;
1390 nU1 = 1;
1391 nTrigger = 9;
1392 }
1393 }
1394 break;
1395 case 3 :
1396 {
1397 if ( nFlags & ( 1 << i ) )
1398 {
1399 bCreateEvent = sal_True;
1400 nU1 = 1;
1401 nTrigger = 10;
1402 }
1403 }
1404 break;
1405 };
1406 if ( bCreateEvent )
1407 {
1408 EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, i + 1 );
1409 {
1410 EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
1411 rStrm << nU1
1412 << nTrigger
1413 << nU3
1414 << nBegin;
1415 }
1416 exportAnimateTargetElement( rStrm, aSource, ( nFlags & ( 1 << i ) ) != 0 );
1417 }
1418 }
1419 }
1420
convertAnimateValue(const Any & rSourceValue,const rtl::OUString & rAttributeName) const1421 Any AnimationExporter::convertAnimateValue( const Any& rSourceValue, const rtl::OUString& rAttributeName ) const
1422 {
1423 rtl::OUString aDest;
1424 if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "X" ) )
1425 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Y" ) )
1426 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Width" ) )
1427 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Height" ) )
1428 )
1429 {
1430 rtl::OUString aStr;
1431 if ( rSourceValue >>= aStr )
1432 {
1433 ImplTranslateAttribute( aStr, TRANSLATE_MEASURE );
1434 aDest += aStr;
1435 }
1436 }
1437 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Rotate" ) ) // "r" or "style.rotation" ?
1438 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SkewX" ) )
1439 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Opacity" ) )
1440 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharHeight" ) )
1441 )
1442 {
1443 double fNumber = 0.0;
1444 if ( rSourceValue >>= fNumber )
1445 aDest += rtl::OUString::valueOf( fNumber );
1446 }
1447 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Color" ) )
1448 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FillColor" ) ) // "Fillcolor" or "FillColor" ?
1449 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "LineColor" ) )
1450 || rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharColor" ) )
1451 )
1452 {
1453 sal_Int32 nColor = 0;
1454 Sequence< double > aHSL( 3 );
1455 rtl::OUString aP( RTL_CONSTASCII_USTRINGPARAM( "," ) );
1456 if ( rSourceValue >>= aHSL )
1457 {
1458 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hsl(" ) );
1459 aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 0 ] / ( 360.0 / 255 ) ) );
1460 aDest += aP;
1461 aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 1 ] * 255.0 ) );
1462 aDest += aP;
1463 aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 2 ] * 255.0 ) );
1464 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
1465 }
1466 else if ( rSourceValue >>= nColor )
1467 {
1468 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "rgb(" ) );
1469 aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)nColor ) );
1470 aDest += aP;
1471 aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 8 ) ) );
1472 aDest += aP;
1473 aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 16 ) ) );
1474 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
1475 }
1476 }
1477 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FillStyle" ) ) )
1478 {
1479 ::com::sun::star::drawing::FillStyle eFillStyle;
1480 if ( rSourceValue >>= eFillStyle )
1481 {
1482 if ( eFillStyle == ::com::sun::star::drawing::FillStyle_NONE )
1483 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "none" ) ); // ?
1484 else
1485 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "solid" ) );
1486 }
1487 }
1488 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "LineStyle" ) ) )
1489 {
1490 ::com::sun::star::drawing::LineStyle eLineStyle;
1491 if ( rSourceValue >>= eLineStyle )
1492 {
1493 if ( eLineStyle == ::com::sun::star::drawing::LineStyle_NONE )
1494 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
1495 else
1496 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
1497 }
1498 }
1499 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharWeight" ) ) )
1500 {
1501 float fFontWeight = 0.0;
1502 if ( rSourceValue >>= fFontWeight )
1503 {
1504 if ( fFontWeight == com::sun::star::awt::FontWeight::BOLD )
1505 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "bold" ) );
1506 else
1507 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "normal" ) );
1508 }
1509 }
1510 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharUnderline" ) ) )
1511 {
1512 sal_Int16 nFontUnderline = 0;
1513 if ( rSourceValue >>= nFontUnderline )
1514 {
1515 if ( nFontUnderline == com::sun::star::awt::FontUnderline::NONE )
1516 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
1517 else
1518 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
1519 }
1520 }
1521 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharPosture" ) ) )
1522 {
1523 ::com::sun::star::awt::FontSlant eFontSlant;
1524 if ( rSourceValue >>= eFontSlant )
1525 {
1526 if ( eFontSlant == com::sun::star::awt::FontSlant_ITALIC )
1527 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "italic" ) );
1528 else
1529 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "normal" ) ); // ?
1530 }
1531 }
1532 else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Visibility" ) ) )
1533 {
1534 sal_Bool bVisible = sal_True;
1535 if ( rSourceValue >>= bVisible )
1536 {
1537 if ( bVisible )
1538 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "visible" ) );
1539 else
1540 aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hidden" ) );
1541 }
1542 }
1543 Any aRet;
1544 if ( aDest.getLength() )
1545 aRet <<= aDest;
1546 else
1547 aRet = rSourceValue;
1548 return aRet;
1549 }
1550
exportAnimateSet(SvStream & rStrm,const Reference<XAnimationNode> & xNode,int nAfterEffectType)1551 void AnimationExporter::exportAnimateSet( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
1552 {
1553 Reference< XAnimateSet > xSet( xNode, UNO_QUERY );
1554 if( xSet.is() )
1555 {
1556 EscherExContainer aAnimateSet( rStrm, DFF_msofbtAnimateSet, 0 );
1557 {
1558 EscherExAtom aAnimateSetData( rStrm, DFF_msofbtAnimateSetData );
1559 sal_uInt32 nId1 = 1; // ??
1560 sal_uInt32 nId2 = 1; // ??
1561 rStrm << nId1 << nId2;
1562 }
1563 Any aConvertedValue( convertAnimateValue( xSet->getTo(), xSet->getAttributeName() ) );
1564 if ( aConvertedValue.hasValue() )
1565 exportAnimProperty( rStrm, 1, aConvertedValue, TRANSLATE_NONE );
1566 exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
1567 }
1568 }
1569
GetValueTypeForAttributeName(const rtl::OUString & rAttributeName)1570 sal_uInt32 GetValueTypeForAttributeName( const rtl::OUString& rAttributeName )
1571 {
1572 sal_uInt32 nValueType = 0;
1573
1574 /*
1575 AnimationValueType::STRING == 0;
1576 AnimationValueType::NUMBER == 1;
1577 AnimationValueType::COLOR == 2;
1578 */
1579
1580 struct Entry
1581 {
1582 const sal_Char* pName;
1583 sal_uInt8 nType;
1584 };
1585 static const Entry lcl_attributeMap[] =
1586 {
1587 { "charcolor", 2 },
1588 { "charfontname", 0 },
1589 { "charheight", 1 },
1590 { "charposture", 0 },
1591 // TODO(Q1): This should prolly be changed in PPT import
1592 // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
1593 { "charrotation", 1 },
1594 { "charunderline", 0 },
1595 { "charweight", 0 },
1596 { "color", 2 },
1597 { "dimcolor", 2 },
1598 { "fillcolor", 2 },
1599 { "fillstyle", 0 },
1600 { "height", 1 },
1601 { "linecolor", 2 },
1602 { "linestyle", 0 },
1603 { "opacity", 0 },
1604 { "rotate", 1 },
1605 { "skewx", 1 },
1606 { "skewy", 1 },
1607 { "visibility", 1 },
1608 { "width", 1 },
1609 { "x", 1 },
1610 { "y", 1 },
1611 { NULL, 0 }
1612 };
1613 const Entry* pPtr = &lcl_attributeMap[ 0 ];
1614 while( pPtr->pName )
1615 {
1616 if ( rAttributeName.equalsIgnoreAsciiCaseAscii( pPtr->pName ) )
1617 {
1618 nValueType = pPtr->nType;
1619 break;
1620 }
1621 pPtr++;
1622 }
1623 DBG_ASSERT( pPtr->pName, "GetValueTypeForAttributeName, unknown property value!" );
1624 return nValueType;
1625 }
1626
exportAnimate(SvStream & rStrm,const Reference<XAnimationNode> & xNode)1627 void AnimationExporter::exportAnimate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1628 {
1629 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
1630 if ( xAnimate.is() )
1631 {
1632 Any aBy ( xAnimate->getBy() );
1633 Any aFrom( xAnimate->getFrom() );
1634 Any aTo ( xAnimate->getTo() );
1635
1636 EscherExContainer aContainer( rStrm, DFF_msofbtAnimate, 0 );
1637 {
1638 EscherExAtom aAnimateData( rStrm, DFF_msofbtAnimateData );
1639 sal_uInt32 nBits = 0x38;
1640 sal_Int16 nTmp = xAnimate->getCalcMode();
1641 sal_uInt32 nCalcMode = /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp == AnimationCalcMode::LINEAR) ? 1 : 0;
1642 nTmp = xAnimate->getValueType();
1643 sal_uInt32 nValueType = GetValueTypeForAttributeName( xAnimate->getAttributeName() );
1644
1645 if ( aBy.hasValue() )
1646 nBits |= 1;
1647 if ( aFrom.hasValue() )
1648 nBits |= 2;
1649 if ( aTo.hasValue() )
1650 nBits |= 4;
1651
1652 rStrm << nCalcMode
1653 << nBits
1654 << nValueType;
1655 }
1656 if ( aBy.hasValue() )
1657 exportAnimProperty( rStrm, 1, aBy, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1658 if ( aFrom.hasValue() )
1659 exportAnimProperty( rStrm, 2, aFrom, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1660 if ( aTo.hasValue() )
1661 exportAnimProperty( rStrm, 3, aTo, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
1662
1663 exportAnimateKeyPoints( rStrm, xAnimate );
1664 exportAnimateTarget( rStrm, xNode );
1665 }
1666 }
1667
exportAnimateTarget(SvStream & rStrm,const Reference<XAnimationNode> & xNode,const sal_uInt32 nForceAttributeNames,int nAfterEffectType)1668 void AnimationExporter::exportAnimateTarget( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_uInt32 nForceAttributeNames, int nAfterEffectType )
1669 {
1670 EscherExContainer aAnimateTarget( rStrm, DFF_msofbtAnimateTarget, 0 );
1671 Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
1672 if ( xAnimate.is() )
1673 {
1674 {
1675 EscherExAtom aAnimateTargetSettings( rStrm, DFF_msofbtAnimateTargetSettings, 0 );
1676 // nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
1677 // nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
1678 // nAccumulate 0 = none, 1 = always
1679 // nTransformType 0: "property" else "image"
1680 sal_uInt32 nBits = 0;
1681 sal_uInt32 nAdditive = 0;
1682 sal_uInt32 nAccumulate = 0;
1683 sal_uInt32 nTransformType = 0;
1684 if ( xAnimate.is() )
1685 {
1686 if ( xAnimate->getAttributeName().getLength() )
1687 nBits |= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
1688 sal_Int16 nAdditiveMode = xAnimate->getAdditive();
1689 if ( nAdditiveMode != AnimationAdditiveMode::BASE )
1690 {
1691 nBits |= 1;
1692 switch( nAdditiveMode )
1693 {
1694 case AnimationAdditiveMode::SUM : nAdditive = 1; break;
1695 case AnimationAdditiveMode::REPLACE : nAdditive = 2; break;
1696 case AnimationAdditiveMode::MULTIPLY : nAdditive = 3; break;
1697 case AnimationAdditiveMode::NONE : nAdditive = 4; break;
1698 }
1699 }
1700 if ( xAnimate->getAccumulate() )
1701 {
1702 nBits |= 2;
1703 nAccumulate = 1;
1704 }
1705 }
1706 rStrm << nBits
1707 << nAdditive
1708 << nAccumulate
1709 << nTransformType;
1710 }
1711 if ( xAnimate->getAttributeName().getLength() || nForceAttributeNames )
1712 {
1713 EscherExContainer aAnimateAttributeNames( rStrm, DFF_msofbtAnimateAttributeNames, 1 );
1714 rtl::OUString aAttributeName( xAnimate->getAttributeName() );
1715 if ( nForceAttributeNames )
1716 {
1717 switch( nForceAttributeNames )
1718 {
1719 case 1 : aAttributeName = rtl::OUString::createFromAscii( "r" ); break;
1720 }
1721 }
1722 sal_Int32 nIndex = 0;
1723 do
1724 {
1725 OUString aToken( aAttributeName.getToken( 0, ';', nIndex ) );
1726 exportAnimPropertyString( rStrm, 0, aToken, TRANSLATE_ATTRIBUTE );
1727 }
1728 while ( nIndex >= 0 );
1729 }
1730
1731 if( nAfterEffectType != AFTEREFFECT_NONE )
1732 {
1733 EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
1734 exportAnimPropertyuInt32( rStrm, 6, 1, TRANSLATE_NONE );
1735 if( nAfterEffectType == AFTEREFFECT_COLOR )
1736 {
1737 exportAnimPropertyuInt32( rStrm, 4, 0, TRANSLATE_NONE );
1738 exportAnimPropertyuInt32( rStrm, 5, 0, TRANSLATE_NONE );
1739 }
1740 }
1741 exportAnimateTargetElement( rStrm, aTarget.hasValue() ? aTarget : xAnimate->getTarget(), sal_False );
1742 }
1743 }
1744
exportAnimateTargetElement(SvStream & rStrm,const Any aAny,const sal_Bool bCreate2b01Atom)1745 void AnimationExporter::exportAnimateTargetElement( SvStream& rStrm, const Any aAny, const sal_Bool bCreate2b01Atom )
1746 {
1747 Reference< XShape > xShape;
1748 aAny >>= xShape;
1749 sal_uInt32 nRefMode = 0; // nRefMode == 2 -> Paragraph
1750 sal_Int32 begin = -1;
1751 sal_Int32 end = -1;
1752
1753 if( !xShape.is() )
1754 {
1755 ParagraphTarget aParaTarget;
1756 if( aAny >>= aParaTarget )
1757 xShape = aParaTarget.Shape;
1758 if ( xShape.is() )
1759 {
1760 // now calculating the character range for the paragraph
1761 sal_Int16 nParagraph = aParaTarget.Paragraph;
1762 Reference< XSimpleText > xText( xShape, UNO_QUERY );
1763 if ( xText.is() )
1764 {
1765 nRefMode = 2;
1766 Reference< XEnumerationAccess > xTextParagraphEnumerationAccess( xText, UNO_QUERY );
1767 if ( xTextParagraphEnumerationAccess.is() )
1768 {
1769 Reference< XEnumeration > xTextParagraphEnumeration( xTextParagraphEnumerationAccess->createEnumeration() );
1770 if ( xTextParagraphEnumeration.is() )
1771 {
1772 sal_Int16 nCurrentParagraph;
1773 begin = end = nCurrentParagraph = 0;
1774 while ( xTextParagraphEnumeration->hasMoreElements() )
1775 {
1776 Reference< XTextRange > xTextRange( xTextParagraphEnumeration->nextElement(), UNO_QUERY );
1777 if ( xTextRange.is() )
1778 {
1779 rtl::OUString aParaText( xTextRange->getString() );
1780 sal_Int32 nLength = aParaText.getLength() + 1;
1781 end += nLength;
1782 if ( nCurrentParagraph == nParagraph )
1783 break;
1784 nCurrentParagraph++;
1785 begin += nLength;
1786 }
1787 }
1788 }
1789 }
1790 }
1791 }
1792 }
1793 if ( xShape.is() || bCreate2b01Atom )
1794 {
1795 EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
1796 if ( xShape.is() )
1797 {
1798 EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
1799
1800 sal_uInt32 nRefType = 1; // TODO: nRefType == 2 -> Sound;
1801 sal_uInt32 nRefId = ((EscherSolverContainer&)mrSolverContainer).GetShapeId( xShape );
1802
1803 rStrm << nRefMode
1804 << nRefType
1805 << nRefId
1806 << begin
1807 << end;
1808 }
1809 if ( bCreate2b01Atom )
1810 {
1811 EscherExAtom a2b01Atom( rStrm, 0x2b01 );
1812 rStrm << (sal_uInt32)1; // ?
1813 }
1814 }
1815 }
1816
exportAnimateKeyPoints(SvStream & rStrm,const Reference<XAnimate> & xAnimate)1817 void AnimationExporter::exportAnimateKeyPoints( SvStream& rStrm, const Reference< XAnimate >& xAnimate )
1818 {
1819 Sequence< double > aKeyTimes( xAnimate->getKeyTimes() );
1820 Sequence< Any > aValues( xAnimate->getValues() );
1821 OUString aFormula( xAnimate->getFormula() );
1822 if ( aKeyTimes.getLength() )
1823 {
1824 EscherExContainer aAnimKeyPoints( rStrm, DFF_msofbtAnimKeyPoints );
1825 sal_Int32 i;
1826 for ( i = 0; i < aKeyTimes.getLength(); i++ )
1827 {
1828 {
1829 EscherExAtom aAnimKeyTime( rStrm, DFF_msofbtAnimKeyTime );
1830 sal_Int32 nKeyTime = (sal_Int32)( aKeyTimes[ i ] * 1000.0 );
1831 rStrm << nKeyTime;
1832 }
1833 Any aAny[ 2 ];
1834 if ( aValues[ i ].hasValue() )
1835 {
1836 ValuePair aPair;
1837 if ( aValues[ i ] >>= aPair )
1838 {
1839 aAny[ 0 ] = convertAnimateValue( aPair.First, xAnimate->getAttributeName() );
1840 aAny[ 1 ] = convertAnimateValue( aPair.Second, xAnimate->getAttributeName() );
1841 }
1842 else
1843 {
1844 aAny[ 0 ] = convertAnimateValue( aValues[ i ], xAnimate->getAttributeName() );
1845 }
1846 if ( !i && aFormula.getLength() )
1847 {
1848 ImplTranslateAttribute( aFormula, TRANSLATE_MEASURE );
1849 aAny[ 1 ] <<= aFormula;
1850 }
1851 exportAnimProperty( rStrm, 0, aAny[ 0 ], TRANSLATE_NONE );
1852 exportAnimProperty( rStrm, 1, aAny[ 1 ], TRANSLATE_NONE );
1853 }
1854 }
1855 }
1856 }
1857
exportAnimValue(SvStream & rStrm,const Reference<XAnimationNode> & xNode,const sal_Bool bExportAlways)1858 void AnimationExporter::exportAnimValue( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Bool bExportAlways )
1859 {
1860 Any aAny;
1861 // repeat count (0)
1862 double fRepeat = 0.0;
1863 float fRepeatCount = 0.0;
1864 com::sun::star::animations::Timing eTiming;
1865 aAny = xNode->getRepeatCount();
1866 if ( aAny >>= eTiming )
1867 {
1868 if ( eTiming == Timing_INDEFINITE )
1869 fRepeatCount = ((float)3.40282346638528860e+38);
1870 }
1871 else if ( aAny >>= fRepeat )
1872 fRepeatCount = (float)fRepeat;
1873 if ( fRepeatCount != 0.0 )
1874 {
1875 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1876 sal_uInt32 nType = 0;
1877 rStrm << nType
1878 << fRepeatCount;
1879 }
1880 // accelerate (3)
1881 float fAccelerate = (float)xNode->getAcceleration();
1882 if ( bExportAlways || ( fAccelerate != 0.0 ) )
1883 {
1884 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1885 sal_uInt32 nType = 3;
1886 rStrm << nType
1887 << fAccelerate;
1888 }
1889
1890 // decelerate (4)
1891 float fDecelerate = (float)xNode->getDecelerate();
1892 if ( bExportAlways || ( fDecelerate != 0.0 ) )
1893 {
1894 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1895 sal_uInt32 nType = 4;
1896 rStrm << nType
1897 << fDecelerate;
1898 }
1899
1900 // autoreverse (5)
1901 sal_Bool bAutoReverse = xNode->getAutoReverse();
1902 if ( bExportAlways || bAutoReverse )
1903 {
1904 EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
1905 sal_uInt32 nType = 5;
1906 sal_uInt32 nVal = bAutoReverse ? 1 : 0;
1907 rStrm << nType
1908 << nVal;
1909 }
1910 }
1911
exportTransitionFilter(SvStream & rStrm,const Reference<XAnimationNode> & xNode)1912 void AnimationExporter::exportTransitionFilter( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1913 {
1914 Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY );
1915 if ( xFilter.is() )
1916 {
1917 EscherExContainer aAnimateFilter( rStrm, DFF_msofbtAnimateFilter );
1918 {
1919 EscherExAtom aAnimateFilterData( rStrm, DFF_msofbtAnimateFilterData );
1920 sal_uInt32 nBits = 3; // bit 0 -> use AnimAttributeValue
1921 // bit 1 -> use nTransition
1922
1923 sal_uInt32 nTransition = xFilter->getMode() ? 0 : 1;
1924 rStrm << nBits
1925 << nTransition;
1926 }
1927 const sal_Char* pFilter = transition::find( xFilter->getTransition(), xFilter->getSubtype(), xFilter->getDirection() );
1928 if ( pFilter )
1929 {
1930 const OUString aStr( OUString::createFromAscii( pFilter ) );
1931 exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
1932 }
1933 exportAnimateTarget( rStrm, xNode );
1934 }
1935 }
1936
exportAnimateMotion(SvStream & rStrm,const Reference<XAnimationNode> & xNode)1937 void AnimationExporter::exportAnimateMotion( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1938 {
1939 Reference< XAnimateMotion > xMotion( xNode, UNO_QUERY );
1940 if ( xMotion.is() )
1941 {
1942 EscherExContainer aAnimateMotion( rStrm, DFF_msofbtAnimateMotion );
1943 {
1944 { //SJ: Ignored from import filter
1945 EscherExAtom aAnimateMotionData( rStrm, DFF_msofbtAnimateMotionData );
1946 sal_uInt32 nBits = 0x98;
1947 sal_uInt32 nOrigin = 0x2;
1948 float fByX = 100.0; // nBits&1
1949 float fByY = 100.0; // nBits&1
1950 float fFromX = 0.0; // nBits&2
1951 float fFromY = 0.0; // nBits&2
1952 float fToX = 100.0; // nBits&4
1953 float fToY = 100.0; // nBits&4
1954 rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nOrigin;
1955 }
1956 /* ?
1957 {
1958 EscherExAtom aF137( rStrm, 0xf137 );
1959 }
1960 */
1961 OUString aStr;
1962 if ( xMotion->getPath() >>= aStr )
1963 {
1964 if ( aStr.getLength() )
1965 exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
1966 }
1967 exportAnimateTarget( rStrm, xNode );
1968 }
1969 }
1970 }
1971
exportAnimateTransform(SvStream & rStrm,const Reference<XAnimationNode> & xNode)1972 void AnimationExporter::exportAnimateTransform( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
1973 {
1974 Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY );
1975 if ( xTransform.is() )
1976 {
1977 if ( xTransform->getTransformType() == AnimationTransformType::SCALE )
1978 {
1979 EscherExContainer aAnimateScale( rStrm, DFF_msofbtAnimateScale );
1980 {
1981 EscherExAtom aAnimateScaleData( rStrm, DFF_msofbtAnimateScaleData );
1982 sal_uInt32 nBits = 0;
1983 sal_uInt32 nZoomContents = 1;
1984 float fByX = 100.0;
1985 float fByY = 100.0;
1986 float fFromX = 0.0;
1987 float fFromY = 0.0;
1988 float fToX = 100.0;
1989 float fToY = 100.0;
1990
1991 double fX = 0.0, fY = 0.0;
1992 ValuePair aPair;
1993 if ( xTransform->getBy() >>= aPair )
1994 {
1995 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
1996 {
1997 nBits |= 1;
1998 fByX = (float)( fX * 100 );
1999 fByY = (float)( fY * 100 );
2000 }
2001 }
2002 if ( xTransform->getFrom() >>= aPair )
2003 {
2004 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
2005 {
2006 nBits |= 2;
2007 fFromX = (float)( fX * 100 );
2008 fFromY = (float)( fY * 100 );
2009 }
2010 }
2011 if( xTransform->getTo() >>= aPair )
2012 {
2013 if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
2014 {
2015 nBits |= 4;
2016 fToX = (float)( fX * 100 );
2017 fToY = (float)( fY * 100 );
2018 }
2019 }
2020
2021 // TODO: ZoomContents:
2022 //if( nBits & 8 )
2023 //( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
2024
2025 rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nZoomContents;
2026 }
2027 exportAnimateTarget( rStrm, xNode );
2028 }
2029 else if ( xTransform->getTransformType() == AnimationTransformType::ROTATE )
2030 {
2031 EscherExContainer aAnimateRotation( rStrm, DFF_msofbtAnimateRotation );
2032 {
2033 EscherExAtom aAnimateRotationData( rStrm, DFF_msofbtAnimateRotationData );
2034 sal_uInt32 nBits = 0;
2035 sal_uInt32 nU1 = 0;
2036 float fBy = 360.0;
2037 float fFrom = 0.0;
2038 float fTo = 360.0;
2039
2040 double fVal = 0.0;
2041 if ( xTransform->getBy() >>= fVal )
2042 {
2043 nBits |= 1;
2044 fBy = (float)fVal;
2045 }
2046 if ( xTransform->getFrom() >>= fVal )
2047 {
2048 nBits |= 2;
2049 fFrom = (float)fVal;
2050 }
2051 if ( xTransform->getTo() >>= fVal )
2052 {
2053 nBits |= 4;
2054 fTo = (float)fVal;
2055 }
2056 rStrm << nBits << fBy << fFrom << fTo << nU1;
2057 }
2058 exportAnimateTarget( rStrm, xNode, 1 );
2059 }
2060 }
2061 }
2062
getColorAny(const Any & rAny,const sal_Int16 nColorSpace,sal_Int32 & rMode,sal_Int32 & rA,sal_Int32 & rB,sal_Int32 & rC) const2063 sal_Bool AnimationExporter::getColorAny( const Any& rAny, const sal_Int16 nColorSpace, sal_Int32& rMode, sal_Int32& rA, sal_Int32& rB, sal_Int32& rC ) const
2064 {
2065 sal_Bool bIsColor = sal_True;
2066
2067 rMode = 0;
2068 if ( nColorSpace == AnimationColorSpace::HSL )
2069 rMode = 1;
2070
2071 sal_Int32 nColor = 0;
2072 Sequence< double > aHSL( 3 );
2073 if ( rAny >>= nColor ) // RGB color
2074 {
2075 rA = (sal_uInt8)( nColor >> 16 );
2076 rB = (sal_uInt8)( nColor >> 8 );
2077 rC = (sal_uInt8)( nColor );
2078 }
2079 else if ( rAny >>= aHSL ) // HSL
2080 {
2081 rA = (sal_Int32) ( aHSL[ 0 ] * 255.0 / 360.0 );
2082 rB = (sal_Int32) ( aHSL[ 1 ] * 255.0 );
2083 rC = (sal_Int32) ( aHSL[ 2 ] * 255.0 );
2084 }
2085 else
2086 bIsColor = sal_False;
2087 return bIsColor;
2088 }
2089
exportAnimateColor(SvStream & rStrm,const Reference<XAnimationNode> & xNode,int nAfterEffectType)2090 void AnimationExporter::exportAnimateColor( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
2091 {
2092 Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
2093 if ( xColor.is() )
2094 {
2095 EscherExContainer aAnimateColor( rStrm, DFF_msofbtAnimateColor );
2096 {
2097 EscherExAtom aAnimateColorData( rStrm, DFF_msofbtAnimateColorData );
2098 sal_uInt32 nBits = 8;
2099
2100 sal_Int32 nByMode, nByA, nByB, nByC;
2101 nByMode = nByA = nByB = nByC = 0;
2102
2103 sal_Int32 nFromMode, nFromA, nFromB, nFromC;
2104 nFromMode = nFromA = nFromB = nFromC = 0;
2105
2106 sal_Int32 nToMode, nToA, nToB, nToC;
2107 nToMode = nToA = nToB = nToC = 0;
2108
2109 sal_Int16 nColorSpace = xColor->getColorInterpolation();
2110
2111 Any aAny( xColor->getBy() );
2112 if ( aAny.hasValue() )
2113 {
2114 if ( getColorAny( aAny, nColorSpace, nByMode, nByA, nByB, nByC ) )
2115 nBits |= 0x11;
2116 }
2117 aAny = xColor->getFrom();
2118 if ( aAny.hasValue() )
2119 {
2120 if ( getColorAny( aAny, nColorSpace, nFromMode, nFromA, nFromB, nFromC ) )
2121 nBits |= 0x12;
2122 }
2123 aAny = xColor->getTo();
2124 if ( aAny.hasValue() )
2125 {
2126 if ( getColorAny( aAny, nColorSpace, nToMode, nToA, nToB, nToC ) )
2127 nBits |= 0x14;
2128 }
2129 rStrm << nBits
2130 << nByMode << nByA << nByB << nByC
2131 << nFromMode << nFromA << nFromB << nFromC
2132 << nToMode << nToA << nToB << nToC;
2133 }
2134 exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
2135 }
2136 }
2137
exportIterate(SvStream & rStrm,const Reference<XAnimationNode> & xNode)2138 void AnimationExporter::exportIterate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
2139 {
2140 Reference< XIterateContainer > xIterate( xNode, UNO_QUERY );
2141 if ( xIterate.is() )
2142 {
2143 EscherExAtom aAnimIteration( rStrm, DFF_msofbtAnimIteration );
2144
2145 float fInterval = 10.0;
2146 sal_Int32 nTextUnitEffect = 0;
2147 sal_Int32 nU1 = 1;
2148 sal_Int32 nU2 = 1;
2149 sal_Int32 nU3 = 0xe;
2150
2151 sal_Int16 nIterateType = xIterate->getIterateType();
2152 switch( nIterateType )
2153 {
2154 case TextAnimationType::BY_WORD : nTextUnitEffect = 1; break;
2155 case TextAnimationType::BY_LETTER : nTextUnitEffect = 2; break;
2156 }
2157
2158 fInterval = (float)xIterate->getIterateInterval();
2159
2160 // convert interval from absolute to percentage
2161 double fDuration = 0.0;
2162
2163 Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
2164 if( xEnumerationAccess.is() )
2165 {
2166 Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
2167 if( xEnumeration.is() )
2168 {
2169 while( xEnumeration->hasMoreElements() )
2170 {
2171 Reference< XAnimate > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
2172 if( xChildNode.is() )
2173 {
2174 double fChildBegin = 0.0;
2175 double fChildDuration = 0.0;
2176 xChildNode->getBegin() >>= fChildBegin;
2177 xChildNode->getDuration() >>= fChildDuration;
2178
2179 fChildDuration += fChildBegin;
2180 if( fChildDuration > fDuration )
2181 fDuration = fChildDuration;
2182 }
2183 }
2184 }
2185 }
2186
2187 if( fDuration )
2188 fInterval = (float)(100.0 * fInterval / fDuration);
2189
2190 rStrm << fInterval << nTextUnitEffect << nU1 << nU2 << nU3;
2191 aTarget = xIterate->getTarget();
2192 }
2193 }
2194
2195 } // namespace ppt;
2196
2197