1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ppt97animations.hxx"
22 #include <svx/svdobj.hxx>
24 #include <tools/debug.hxx>
25 #include <svx/unoapi.hxx>
26 #include "EffectMigration.hxx"
27 #include <CustomAnimationPreset.hxx>
28 #include <com/sun/star/drawing/XShape.hpp>
29 #include <com/sun/star/presentation/TextAnimationType.hpp>
30 #include <com/sun/star/presentation/EffectNodeType.hpp>
31 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
33 using namespace ::com::sun::star
;
35 void Ppt97AnimationInfoAtom::ReadStream( SvStream
& rIn
)
37 rIn
.ReadUInt32( nDimColor
);
38 rIn
.ReadUInt32( nFlags
);
39 rIn
.ReadUInt32( nSoundRef
);
40 rIn
.ReadInt32( nDelayTime
);
41 rIn
.ReadUInt16( nOrderID
);
42 rIn
.ReadUInt16( nSlideCount
);
43 rIn
.ReadUChar( nBuildType
);
44 rIn
.ReadUChar( nFlyMethod
);
45 rIn
.ReadUChar( nFlyDirection
);
46 rIn
.ReadUChar( nAfterEffect
);
47 rIn
.ReadUChar( nSubEffect
);
48 rIn
.ReadUChar( nOLEVerb
);
49 rIn
.ReadUChar( nUnknown1
);
50 rIn
.ReadUChar( nUnknown2
);
53 #define MEMBER_CONSTRUCTOR_LIST() \
56 , m_bDirtyCache(true) \
59 , m_bHasSpecialDuration(false) \
60 , m_fDurationInSeconds(0.001)
62 Ppt97Animation::Ppt97Animation( SvStream
& rInputStream
)
63 : MEMBER_CONSTRUCTOR_LIST()
65 m_aAtom
.ReadStream( rInputStream
);
68 Ppt97Animation::Ppt97Animation( const Ppt97Animation
& rAnimation
)
69 : MEMBER_CONSTRUCTOR_LIST()
74 Ppt97Animation
& Ppt97Animation::operator= ( const Ppt97Animation
& rAnimation
)
76 m_aAtom
= rAnimation
.m_aAtom
;
77 m_aSoundFileUrl
= rAnimation
.m_aSoundFileUrl
;
78 m_bDirtyCache
= rAnimation
.m_bDirtyCache
;
79 m_aPresetId
= rAnimation
.m_aPresetId
;
80 m_aSubType
= rAnimation
.m_aSubType
;
81 m_bHasSpecialDuration
= rAnimation
.m_bHasSpecialDuration
;
82 m_fDurationInSeconds
= rAnimation
.m_fDurationInSeconds
;
87 Ppt97Animation::~Ppt97Animation()
91 bool Ppt97Animation::operator < ( const Ppt97Animation
& rAnimation
) const
93 return m_aAtom
.nOrderID
< rAnimation
.m_aAtom
.nOrderID
;
95 bool Ppt97Animation::operator > ( const Ppt97Animation
& rAnimation
) const
97 return m_aAtom
.nOrderID
> rAnimation
.m_aAtom
.nOrderID
;
99 bool Ppt97Animation::HasEffect() const
101 return m_aAtom
.nBuildType
!= 0;
103 bool Ppt97Animation::HasParagraphEffect() const
105 return m_aAtom
.nBuildType
> 1;
107 sal_Int32
Ppt97Animation::GetParagraphLevel() const
109 sal_Int32 nParagraphLevel
= 0;
110 if(m_aAtom
.nBuildType
>1)
111 nParagraphLevel
= m_aAtom
.nBuildType
-1;
112 return nParagraphLevel
;
114 bool Ppt97Animation::HasSoundEffect() const
116 return m_aAtom
.nSoundRef
&& m_aAtom
.nFlags
& 0x0010;
118 bool Ppt97Animation::HasStopPreviousSound() const
120 return m_aAtom
.nFlags
& 0x0040;
122 bool Ppt97Animation::HasReverseOrder() const
124 return m_aAtom
.nFlags
& 0x001;
126 bool Ppt97Animation::HasAnimateAssociatedShape() const
128 return m_aAtom
.nFlags
& 0x004000;
130 bool Ppt97Animation::HasAfterEffect() const
132 return m_aAtom
.nAfterEffect
!= 0;
134 bool Ppt97Animation::HasAfterEffect_ChangeColor() const
136 return m_aAtom
.nAfterEffect
== 1;
138 bool Ppt97Animation::HasAfterEffect_DimAtNextEffect() const
140 return m_aAtom
.nAfterEffect
== 2;
143 bool Ppt97Animation::HasAfterEffect_DimAfterEffect() const
145 return m_aAtom
.nAfterEffect
== 3;
148 void Ppt97Animation::SetSoundFileUrl( const OUString
& rSoundFileUrl
)
150 m_aSoundFileUrl
= rSoundFileUrl
;
153 double Ppt97Animation::GetDelayTimeInSeconds() const
155 return m_aAtom
.nDelayTime
!= 0X7FFFFFFF ? m_aAtom
.nDelayTime
/1000.0 : 0.0;
158 bool Ppt97Animation::GetSpecialDuration( double& rfDurationInSeconds
) const
161 if( m_bHasSpecialDuration
)
162 rfDurationInSeconds
= m_fDurationInSeconds
;
163 return m_bHasSpecialDuration
;
166 bool Ppt97Animation::GetSpecialTextIterationDelay( double& rfTextIterationDelay
) const
169 switch(this->GetTextAnimationType())
171 case presentation::TextAnimationType::BY_LETTER
:
172 rfTextIterationDelay
= 0.075;
175 case presentation::TextAnimationType::BY_WORD
:
176 rfTextIterationDelay
= 0.3;
185 void Ppt97Animation::SetDimColor( sal_Int32 nDimColor
)
187 m_aAtom
.nDimColor
= nDimColor
;
189 void Ppt97Animation::SetAnimateAssociatedShape( bool bAnimate
)
193 //the appear effect cannot be animated without text
194 if( this->GetPresetId() == "ooo-entrance-appear" )
196 //the random effect may be the appear effect and than has the same problem
197 if( this->GetPresetId() == "ooo-entrance-random" )
199 //this case is not 100% correct -> feel free to complete
200 //i consider this case as seldom and not that problematic and a simple correct fix is not in sight
201 DBG_WARNING("you tried to deselect the animation of the form for random animation-> this has been refused");
208 m_aAtom
.nFlags
= m_aAtom
.nFlags
| 0x004000;
209 else if( HasAnimateAssociatedShape() )
211 m_aAtom
.nFlags
= m_aAtom
.nFlags
^ 0x004000;
215 sal_Int16
Ppt97Animation::GetEffectNodeType() const //see com::sun::star::presentation::EffectNodeType
217 sal_Int16 nRet
= presentation::EffectNodeType::ON_CLICK
;
218 if( m_aAtom
.nFlags
& 0x04 )
220 nRet
= presentation::EffectNodeType::AFTER_PREVIOUS
;
225 sal_Int16
Ppt97Animation::GetTextAnimationType() const
227 sal_Int16 nRet
= presentation::TextAnimationType::BY_PARAGRAPH
;
228 switch( m_aAtom
.nSubEffect
)
233 nRet
= presentation::TextAnimationType::BY_LETTER
;
236 nRet
= presentation::TextAnimationType::BY_WORD
;
241 OUString
Ppt97Animation::GetPresetId() const
246 OUString
Ppt97Animation::GetPresetSubType() const
252 void Ppt97Animation::ClearCacheData() const
256 m_bHasSpecialDuration
= false;
257 m_fDurationInSeconds
= 0.001;
259 void Ppt97Animation::UpdateCacheData() const
268 m_bDirtyCache
= false;
272 switch( m_aAtom
.nFlyMethod
)
275 m_aPresetId
= "ooo-entrance-appear"; // --- appear ---
278 m_aPresetId
= "ooo-entrance-random"; // --- random ---
280 case 0x02: // --- blinds effect ---
282 switch ( m_aAtom
.nFlyDirection
)
285 m_aPresetId
= "ooo-entrance-venetian-blinds";
286 m_aSubType
= "horizontal"; // horizontal
289 m_aPresetId
= "ooo-entrance-venetian-blinds";
290 m_aSubType
= "vertical"; // vertical
295 case 0x03: // --- (hor/ver) shifted appear ---
297 switch ( m_aAtom
.nFlyDirection
)
300 m_aPresetId
= "ooo-entrance-checkerboard";
301 m_aSubType
= "across"; // vertical ???
304 m_aPresetId
= "ooo-entrance-checkerboard";
305 m_aSubType
= "downward"; // horizontal ???
311 m_aPresetId
= "ooo-entrance-dissolve-in";
313 case 0x08: // --- (hor/ver) lines ---
315 switch ( m_aAtom
.nFlyDirection
)
318 m_aPresetId
= "ooo-entrance-random-bars";
319 m_aSubType
= "vertical"; // horizontal ???
322 m_aPresetId
= "ooo-entrance-random-bars";
323 m_aSubType
= "horizontal"; // vertical ???
328 case 0x09: // --- diagonal ---
330 switch ( m_aAtom
.nFlyDirection
)
333 m_aPresetId
= "ooo-entrance-diagonal-squares";
334 m_aSubType
= "left-to-top"; // to left top
337 m_aPresetId
= "ooo-entrance-diagonal-squares";
338 m_aSubType
= "right-to-top"; // to right top
341 m_aPresetId
= "ooo-entrance-diagonal-squares";
342 m_aSubType
= "left-to-bottom"; // to left bottom
345 m_aPresetId
= "ooo-entrance-diagonal-squares";
346 m_aSubType
= "right-to-bottom"; // to right bottom
351 case 0x0a: // --- roll/wipe ---
353 switch ( m_aAtom
.nFlyDirection
)
356 m_aPresetId
= "ooo-entrance-wipe";
357 m_aSubType
= "from-right"; // from right
360 m_aPresetId
= "ooo-entrance-wipe";
361 m_aSubType
= "from-bottom"; // from bottom
364 m_aPresetId
= "ooo-entrance-wipe";
365 m_aSubType
= "from-left"; // from left
368 m_aPresetId
= "ooo-entrance-wipe";
369 m_aSubType
= "from-top"; // from top
374 case 0x0b: //--- fade in ---
376 switch ( m_aAtom
.nFlyDirection
)
379 m_aPresetId
= "ooo-entrance-box";
380 m_aSubType
= "out"; // from center
383 m_aPresetId
= "ooo-entrance-box";
384 m_aSubType
= "in"; // to center
389 case 0x0c: // --- text effects ---
391 switch ( m_aAtom
.nFlyDirection
)
394 m_aPresetId
= "ooo-entrance-fly-in";
395 m_aSubType
= "from-left";
399 m_aPresetId
= "ooo-entrance-fly-in";
400 m_aSubType
= "from-top";
403 m_aPresetId
= "ooo-entrance-fly-in";
404 m_aSubType
= "from-right";
407 m_aPresetId
= "ooo-entrance-fly-in";
408 m_aSubType
= "from-bottom";
411 m_aPresetId
= "ooo-entrance-fly-in";
412 m_aSubType
= "from-top-left";
415 m_aPresetId
= "ooo-entrance-fly-in";
416 m_aSubType
= "from-top-right";
419 m_aPresetId
= "ooo-entrance-fly-in";
420 m_aSubType
= "from-bottom-left";
423 m_aPresetId
= "ooo-entrance-fly-in";
424 m_aSubType
= "from-bottom-right";
426 case 0x8: // -- short text effects --
427 m_aPresetId
= "ooo-entrance-peek-in";
428 m_aSubType
= "from-left";
431 m_aPresetId
= "ooo-entrance-peek-in";
432 m_aSubType
= "from-bottom";
435 m_aPresetId
= "ooo-entrance-peek-in";
436 m_aSubType
= "from-right";
439 m_aPresetId
= "ooo-entrance-peek-in";
440 m_aSubType
= "from-top";
442 case 0xc: // -- slow text effects --
444 m_aPresetId
= "ooo-entrance-fly-in-slow";
445 m_aSubType
= "from-left";
450 m_aPresetId
= "ooo-entrance-fly-in-slow";
451 m_aSubType
= "from-top";
456 m_aPresetId
= "ooo-entrance-fly-in-slow";
457 m_aSubType
= "from-right";
462 m_aPresetId
= "ooo-entrance-fly-in-slow";
463 m_aSubType
= "from-bottom";
466 case 0x10: // --- zoom ---
467 m_aPresetId
= "ooo-entrance-zoom";
471 m_aPresetId
= "ooo-entrance-zoom";
472 m_aSubType
= "in-slightly";
475 m_aPresetId
= "ooo-entrance-zoom";
479 m_aPresetId
= "ooo-entrance-zoom";
480 m_aSubType
= "out-slightly";
483 m_aPresetId
= "ooo-entrance-zoom";
484 m_aSubType
= "in-from-screen-center";
487 m_aPresetId
= "ooo-entrance-zoom";
488 m_aSubType
= "out-from-screen-center";
490 case 0x16: // --- stretch ---
491 m_aPresetId
= "ooo-entrance-stretchy";
492 m_aSubType
= "across";
495 m_aPresetId
= "ooo-entrance-stretchy";
496 m_aSubType
= "from-left";
499 m_aPresetId
= "ooo-entrance-stretchy";
500 m_aSubType
= "from-top";
503 m_aPresetId
= "ooo-entrance-stretchy";
504 m_aSubType
= "from-right";
507 m_aPresetId
= "ooo-entrance-stretchy";
508 m_aSubType
= "from-bottom";
510 case 0x1b: // --- rotate ---
511 m_aPresetId
= "ooo-entrance-swivel";
512 m_aSubType
= "vertical";
514 case 0x1c: // --- spirale ---
515 m_aPresetId
= "ooo-entrance-spiral-in";
520 case 0x0d: // --- open/close ---
522 switch ( m_aAtom
.nFlyDirection
)
525 m_aPresetId
= "ooo-entrance-split";
526 m_aSubType
= "horizontal-out"; //horizontal open
529 m_aPresetId
= "ooo-entrance-split";
530 m_aSubType
= "horizontal-in"; //horizontal close
533 m_aPresetId
= "ooo-entrance-split";
534 m_aSubType
= "vertical-out"; // vertical open
537 m_aPresetId
= "ooo-entrance-split";
538 m_aSubType
= "vertical-in"; // vertical close
543 case 0x0e: // --- blink ---
545 m_aPresetId
= "ooo-entrance-flash-once";
546 switch ( m_aAtom
.nFlyDirection
)
549 m_fDurationInSeconds
= 0.075;
550 m_bHasSpecialDuration
= true;
553 m_fDurationInSeconds
= 0.5;
554 m_bHasSpecialDuration
= true;
557 m_fDurationInSeconds
= 1.0;
558 m_bHasSpecialDuration
= true;
565 m_aPresetId
= "ooo-entrance-appear";
566 OSL_FAIL("no effect mapped");
570 m_bDirtyCache
= false;
573 void Ppt97Animation::createAndSetCustomAnimationEffect( SdrObject
* pObj
)
576 if( !this->HasEffect() )
578 if( !pObj
|| !pObj
->GetPage() )
580 OSL_FAIL("no valid SdrObject or page found for ppt import");
584 uno::Reference
< drawing::XShape
> xShape
= GetXShapeForSdrObject( pObj
);
587 OSL_FAIL("no XShape interface found for ppt import");
590 ::sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->GetPage())->getMainSequence();
591 if( !pMainSequence
.get() )
593 OSL_FAIL("no MainSequence found for ppt import");
597 const ::sd::CustomAnimationPresets
& rPresets( ::sd::CustomAnimationPresets::getCustomAnimationPresets() );
598 ::sd::CustomAnimationPresetPtr
pPreset( rPresets
.getEffectDescriptor( this->GetPresetId() ) );
601 OSL_FAIL("no suitable preset found for ppt import");
605 //--------------start doing something
607 //1. ------ create an effect from the presets ------
608 ::sd::CustomAnimationEffectPtr
pEffect( new ::sd::CustomAnimationEffect( pPreset
->create( this->GetPresetSubType() ) ) );
611 DBG_ASSERT(pEffect
.get(),"no suitable effect found");
615 //2. ------ adapt the created effect ------
617 // set the shape targeted by this effect
618 pEffect
->setTarget( makeAny( xShape
) );
620 pEffect
->setBegin( this->GetDelayTimeInSeconds() );
622 // some effects need a different duration than that of the mapped preset effect
623 double fDurationInSeconds
= 1.0; //in seconds
624 if( this->GetSpecialDuration( fDurationInSeconds
) )
625 pEffect
->setDuration( fDurationInSeconds
);
628 if( this->HasAfterEffect() )
630 pEffect
->setHasAfterEffect( true );
631 if( this->HasAfterEffect_ChangeColor() )
632 pEffect
->setDimColor( uno::makeAny( this->GetDimColor() ) );
634 pEffect
->setAfterEffectOnNext( this->HasAfterEffect_DimAtNextEffect() );
638 if( this->HasSoundEffect() )
639 pEffect
->createAudio( uno::makeAny( m_aSoundFileUrl
) );
642 pEffect
->setIterateType( this->GetTextAnimationType() );
644 // some effects need a different delay between text iteration than that of the mapped preset effect
645 double fTextIterationDelay
= 1.0;
646 if( this->GetSpecialTextIterationDelay( fTextIterationDelay
) )
647 pEffect
->setIterateInterval( fTextIterationDelay
);
649 // is the effect started on click or after the last effect (Another possible value is EffectNodeType::WITH_PREVIOUS )
650 pEffect
->setNodeType( this->GetEffectNodeType() );
652 //set stop sound effect
653 if( this->HasStopPreviousSound() )
654 pEffect
->setStopAudio();
656 // append the effect to the main sequence
657 if( !this->HasParagraphEffect() )
659 // TODO: !this->HasAnimateAssociatedShape() can possibly have this set to ONLY_TEXT - see i#42737
660 pEffect
->setTargetSubItem( presentation::ShapeAnimationSubType::AS_WHOLE
);
663 //3. ------ put the created effect to the model and do some last changes fro paragraph effects ------
664 pMainSequence
->append( pEffect
);
665 if( this->HasParagraphEffect() )
667 sal_Int32 nParagraphLevel
= this->GetParagraphLevel();
668 double fDelaySeconds
= this->GetDelayTimeInSeconds();
669 bool bAnimateAssociatedShape
= this->HasAnimateAssociatedShape();//or only text
670 bool bTextReverse
= this->HasReverseOrder();
672 // now create effects for each paragraph
673 ::sd::CustomAnimationTextGroupPtr pGroup
= pMainSequence
->
674 createTextGroup( pEffect
, nParagraphLevel
, fDelaySeconds
, bAnimateAssociatedShape
, bTextReverse
);
678 const ::sd::EffectSequence
& rEffects
= pGroup
->getEffects();
679 ::sd::EffectSequence::const_iterator aIter
= rEffects
.begin();
681 ::sd::CustomAnimationEffectPtr pLastEffect
;
682 sal_Int32 nIndex
= 0;
683 for( ; aIter
!= rEffects
.end(); ++aIter
)
685 ::sd::CustomAnimationEffectPtr
pGroupEffect(*aIter
);
687 ////todo? if( nIndex > 1 && pLastEffect && this->HasSoundEffect() )
688 //// pLastEffect->setStopAudio();
691 pGroupEffect
->setNodeType( this->GetEffectNodeType() );
693 else if( nIndex
> 0 )
695 bool bAtParagraphBegin
= false;
697 bAtParagraphBegin
= pGroupEffect
->getParaDepth() < nParagraphLevel
;
699 bAtParagraphBegin
= !pLastEffect
|| pLastEffect
->getParaDepth() < nParagraphLevel
;
700 if( bAtParagraphBegin
)
701 pGroupEffect
->setNodeType( this->GetEffectNodeType() );
702 else if( this->GetTextAnimationType() == presentation::TextAnimationType::BY_PARAGRAPH
)
703 pGroupEffect
->setNodeType( presentation::EffectNodeType::WITH_PREVIOUS
);
705 pGroupEffect
->setNodeType( presentation::EffectNodeType::AFTER_PREVIOUS
);
707 pLastEffect
= pGroupEffect
;
712 pMainSequence
->rebuild();
715 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */