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