xref: /AOO41X/main/sd/source/filter/eppt/pptexanimations.cxx (revision 67046194419f09d65bdfe10db866f47b22282683)
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 cought!" );
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