blob: 8da642a242049c6cf59ff53956cf5e8725a69d76 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"
#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
#include <com/sun/star/animations/AnimationFill.hpp>
#include <com/sun/star/animations/AnimationRestart.hpp>
#include <com/sun/star/animations/Timing.hpp>
#include <com/sun/star/animations/Event.hpp>
#include <com/sun/star/animations/AnimationEndSync.hpp>
#include <com/sun/star/animations/EventTrigger.hpp>
#include <com/sun/star/presentation/EffectNodeType.hpp>
#include <com/sun/star/presentation/EffectPresetClass.hpp>
#include <com/sun/star/animations/AnimationNodeType.hpp>
#include <com/sun/star/animations/AnimationTransformType.hpp>
#include <com/sun/star/animations/AnimationCalcMode.hpp>
#include <com/sun/star/animations/AnimationValueType.hpp>
#include <com/sun/star/util/XCloneable.hpp>
#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
#include <com/sun/star/animations/XAnimateSet.hpp>
#include <com/sun/star/animations/XAudio.hpp>
#include <com/sun/star/animations/XTransitionFilter.hpp>
#include <com/sun/star/animations/XAnimateColor.hpp>
#include <com/sun/star/animations/XAnimateMotion.hpp>
#include <com/sun/star/animations/XAnimateTransform.hpp>
#include <com/sun/star/animations/TransitionType.hpp>
#include <com/sun/star/animations/TransitionSubType.hpp>
#include <com/sun/star/animations/ValuePair.hpp>
#include <com/sun/star/animations/AnimationColorSpace.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/awt/FontUnderline.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/presentation/ParagraphTarget.hpp>
#include <com/sun/star/text/XSimpleText.hpp>
#include <com/sun/star/animations/XIterateContainer.hpp>
#include <com/sun/star/presentation/TextAnimationType.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <comphelper/processfactory.hxx>
#include <rtl/ustrbuf.hxx>
#ifndef _RTL_MEMORY_H_
#include <rtl/memory.hxx>
#endif
#include <vcl/vclenum.hxx>
#include <svx/svdotext.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/editobj.hxx>
#include <pptexanimations.hxx>
#include <osl/endian.h>
#include <algorithm>
using ::std::map;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::uno::Any;
using ::com::sun::star::container::XChild;
using ::com::sun::star::util::XCloneable;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::makeAny;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::beans::NamedValue;
using ::com::sun::star::container::XEnumerationAccess;
using ::com::sun::star::container::XEnumeration;
using ::com::sun::star::lang::XMultiServiceFactory;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::animations;
using namespace ::com::sun::star::presentation;
namespace ppt
{
void ImplTranslateAttribute( rtl::OUString& rString, const TranslateMode eTranslateMode )
{
if ( eTranslateMode != TRANSLATE_NONE )
{
if ( ( eTranslateMode & TRANSLATE_VALUE ) || ( eTranslateMode & TRANSLATE_ATTRIBUTE ) )
{
const ImplAttributeNameConversion* p = gImplConversionList;
while( p->mpAPIName )
{
if( rString.compareToAscii( p->mpAPIName ) == 0 )
break;
p++;
}
if( p->mpMSName )
{
if ( eTranslateMode & TRANSLATE_VALUE )
{
rString = rtl::OUString( (sal_Unicode)'#' );
rString += OUString::createFromAscii( p->mpMSName );
}
else
rString = OUString::createFromAscii( p->mpMSName );
}
}
else if ( eTranslateMode & TRANSLATE_MEASURE )
{
const sal_Char* pDest[] = { "#ppt_x", "#ppt_y", "#ppt_w", "#ppt_h", NULL };
const sal_Char* pSource[] = { "x", "y", "width", "height", NULL };
sal_Int32 nIndex = 0;
const sal_Char** ps = pSource;
const sal_Char** pd = pDest;
while( *ps )
{
const OUString aSearch( OUString::createFromAscii( *ps ) );
while( (nIndex = rString.indexOf( aSearch, nIndex )) != -1 )
{
sal_Int32 nLength = aSearch.getLength();
if( nIndex && (rString.getStr()[nIndex-1] == '#' ) )
{
nIndex--;
nLength++;
}
const OUString aNew( OUString::createFromAscii( *pd ) );
rString = rString.replaceAt( nIndex, nLength, aNew );
nIndex += aNew.getLength();
}
ps++;
pd++;
}
}
}
}
sal_uInt32 ImplTranslatePresetSubType( const sal_uInt32 nPresetClass, const sal_uInt32 nPresetId, const rtl::OUString& rPresetSubType )
{
sal_uInt32 nPresetSubType = 0;
sal_Bool bTranslated = sal_False;
if ( ( nPresetClass == (sal_uInt32)EffectPresetClass::ENTRANCE ) || ( nPresetClass == (sal_uInt32)EffectPresetClass::EXIT ) )
{
if ( nPresetId != 21 )
{
switch( nPresetId )
{
case 5 :
{
if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "downward" ) ) )
{
nPresetSubType = 5;
bTranslated = sal_True;
}
else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "across" ) ) )
{
nPresetSubType = 10;
bTranslated = sal_True;
}
}
break;
case 17 :
{
if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "across" ) ) )
{
nPresetSubType = 10;
bTranslated = sal_True;
}
}
break;
case 18 :
{
if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "right-to-top" ) ) )
{
nPresetSubType = 3;
bTranslated = sal_True;
}
else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "right-to-bottom" ) ) )
{
nPresetSubType = 6;
bTranslated = sal_True;
}
else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "left-to-top" ) ) )
{
nPresetSubType = 9;
bTranslated = sal_True;
}
else if ( rPresetSubType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "left-to-bottom" ) ) )
{
nPresetSubType = 12;
bTranslated = sal_True;
}
}
break;
}
}
if ( !bTranslated )
{
const convert_subtype* p = gConvertArray;
while( p->mpStrSubType )
{
if ( rPresetSubType.equalsAscii( p->mpStrSubType ) )
{
nPresetSubType = p->mnID;
bTranslated = sal_True;
break;
}
p++;
}
}
}
if ( !bTranslated )
nPresetSubType = (sal_uInt32)rPresetSubType.toInt32();
return nPresetSubType;
}
const sal_Char* transition::find( const sal_Int16 nType, const sal_Int16 nSubType, const sal_Bool bDirection )
{
const sal_Char* pRet = NULL;
int nFit = 0;
const transition* p = gTransitions;
while( p->mpName )
{
int nF = 0;
if ( nType == p->mnType )
nF += 4;
if ( nSubType == p->mnSubType )
nF += 2;
if ( bDirection == p->mbDirection )
nF += 1;
if ( nF > nFit )
{
pRet = p->mpName;
nFit = nF;
}
if ( nFit == 7 ) // maximum
break;
p++;
}
return pRet;
}
SvStream& operator<<(SvStream& rOut, AnimationNode& rNode )
{
rOut << rNode.mnU1;
rOut << rNode.mnRestart;
rOut << rNode.mnGroupType;
rOut << rNode.mnFill;
rOut << rNode.mnU3;
rOut << rNode.mnU4;
rOut << rNode.mnDuration;
rOut << rNode.mnNodeType;
return rOut;
}
AnimationExporter::AnimationExporter( const EscherSolverContainer& rSolverContainer, ppt::ExSoundCollection& rExSoundCollection ) :
mrSolverContainer ( rSolverContainer ),
mrExSoundCollection ( rExSoundCollection ),
mnCurrentGroup(0)
{
}
// --------------------------------------------------------------------
static sal_Int16 GetFillMode( const Reference< XAnimationNode >& xNode, const sal_Int16 nFillDefault )
{
sal_Int16 nFill = xNode->getFill();
//[bug 119699] <Animation> The animation effect "Emphasis->FlashBulb" play incorrectly in Aoo saves a .ppt to another .ppt and plays the saved one.
//[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.
if ((xNode->getType() == AnimationNodeType::ANIMATE)
||(xNode->getType() == AnimationNodeType::SET)
||(xNode->getType() == AnimationNodeType::TRANSITIONFILTER))
{
if ( nFill == AnimationFill::DEFAULT )
return nFill;
}
if ( ( nFill == AnimationFill::DEFAULT ) ||
( nFill == AnimationFill::INHERIT ) )
{
if ( nFill != AnimationFill::AUTO )
nFill = nFillDefault;
}
if( nFill == AnimationFill::AUTO )
{
nFill = AnimationFill::REMOVE;
sal_Bool bIsIndefiniteTiming = sal_True;
Any aAny = xNode->getDuration();
if( aAny.hasValue() )
{
Timing eTiming;
if( aAny >>= eTiming )
bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
}
if ( bIsIndefiniteTiming )
{
aAny = xNode->getEnd();
if( aAny.hasValue() )
{
Timing eTiming;
if( aAny >>= eTiming )
bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
}
if ( bIsIndefiniteTiming )
{
if ( !xNode->getRepeatCount().hasValue() )
{
aAny = xNode->getRepeatDuration();
if( aAny.hasValue() )
{
Timing eTiming;
if( aAny >>= eTiming )
bIsIndefiniteTiming = eTiming == Timing_INDEFINITE;
}
if ( bIsIndefiniteTiming )
nFill = AnimationFill::FREEZE;
}
}
}
}
return nFill;
}
void AnimationExporter::doexport( const Reference< XDrawPage >& xPage, SvStream& rStrm )
{
Reference< XAnimationNodeSupplier > xNodeSupplier( xPage, UNO_QUERY );
if( xNodeSupplier.is() )
{
const Reference< XAnimationNode > xRootNode( xNodeSupplier->getAnimationNode() );
if( xRootNode.is() )
{
processAfterEffectNodes( xRootNode );
exportNode( rStrm, xRootNode, NULL, DFF_msofbtAnimGroup, 1, 0, sal_False, AnimationFill::AUTO );
}
}
}
void AnimationExporter::processAfterEffectNodes( const Reference< XAnimationNode >& xRootNode )
{
try
{
Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
while( xEnumeration->hasMoreElements() )
{
Reference< XAnimationNode > xNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
Reference< XEnumerationAccess > xEnumerationAccess2( xNode, UNO_QUERY );
if ( xEnumerationAccess2.is() )
{
Reference< XEnumeration > xEnumeration2( xEnumerationAccess2->createEnumeration(), UNO_QUERY_THROW );
while( xEnumeration2->hasMoreElements() )
{
Reference< XAnimationNode > xChildNode( xEnumeration2->nextElement(), UNO_QUERY_THROW );
Reference< XEnumerationAccess > xEnumerationAccess3( xChildNode, UNO_QUERY_THROW );
Reference< XEnumeration > xEnumeration3( xEnumerationAccess3->createEnumeration(), UNO_QUERY_THROW );
while( xEnumeration3->hasMoreElements() )
{
Reference< XAnimationNode > xChildNode2( xEnumeration3->nextElement(), UNO_QUERY_THROW );
Reference< XEnumerationAccess > xEnumerationAccess4( xChildNode2, UNO_QUERY_THROW );
Reference< XEnumeration > xEnumeration4( xEnumerationAccess4->createEnumeration(), UNO_QUERY_THROW );
while( xEnumeration4->hasMoreElements() )
{
Reference< XAnimationNode > xChildNode3( xEnumeration4->nextElement(), UNO_QUERY_THROW );
switch( xChildNode3->getType() )
{
// found an after effect
case AnimationNodeType::SET:
case AnimationNodeType::ANIMATECOLOR:
{
Reference< XAnimationNode > xMaster;
Sequence< NamedValue > aUserData( xChildNode3->getUserData() );
sal_Int32 nLength = aUserData.getLength();
const NamedValue* p = aUserData.getConstArray();
while( nLength-- )
{
if( p->Name.equalsAscii( "master-element" ) )
{
p->Value >>= xMaster;
break;
}
p++;
}
AfterEffectNodePtr pAfterEffectNode( new AfterEffectNode( xChildNode3, xMaster ) );
maAfterEffectNodes.push_back( pAfterEffectNode );
}
break;
}
}
}
}
}
}
}
catch( Exception& e )
{
(void)e;
DBG_ERROR( "(@CL)AnimationExporter::processAfterEffectNodes(), exception cought!" );
}
}
bool AnimationExporter::isAfterEffectNode( const Reference< XAnimationNode >& xNode ) const
{
std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
while( aIter != aEnd )
{
if( (*aIter)->mxNode == xNode )
return true;
aIter++;
}
return false;
}
bool AnimationExporter::hasAfterEffectNode( const Reference< XAnimationNode >& xNode, Reference< XAnimationNode >& xAfterEffectNode ) const
{
std::list< AfterEffectNodePtr >::const_iterator aIter( maAfterEffectNodes.begin() );
const std::list< AfterEffectNodePtr >::const_iterator aEnd( maAfterEffectNodes.end() );
while( aIter != aEnd )
{
if( (*aIter)->mxMaster == xNode )
{
xAfterEffectNode = (*aIter)->mxNode;
return true;
}
aIter++;
}
return false;
}
// check if this group only contain empty groups. this may happen when
// after effect nodes are not exported at theire original position
bool AnimationExporter::isEmptyNode( const Reference< XAnimationNode >& xNode ) const
{
if( xNode.is() ) switch( xNode->getType() )
{
case AnimationNodeType::PAR :
case AnimationNodeType::SEQ :
case AnimationNodeType::ITERATE :
{
Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
if( xEnumerationAccess.is() )
{
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
if( xEnumeration.is() )
{
while( xEnumeration->hasMoreElements() )
{
Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
if( xChildNode.is() && !isEmptyNode( xChildNode ) )
return false;
}
}
}
}
break;
case AnimationNodeType::SET :
case AnimationNodeType::ANIMATECOLOR :
return isAfterEffectNode( xNode );
default:
return false;
}
return true;
}
void AnimationExporter::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 )
{
if( (nGroupLevel == 4) && isEmptyNode( xNode ) )
return;
if ( ( nContainerRecType == DFF_msofbtAnimGroup ) && ( nGroupLevel == 2 ) && isEmptyNode( xNode ) )
return;
if( nContainerRecType == DFF_msofbtAnimGroup )
mnCurrentGroup++;
sal_Bool bTakeBackInteractiveSequenceTimingForChild = sal_False;
sal_Int16 nFillDefault = GetFillMode( xNode, nFDef );
bool bSkipChildren = false;
Reference< XAnimationNode > xAudioNode;
static sal_uInt32 nAudioGroup;
{
EscherExContainer aContainer( rStrm, nContainerRecType, nInstance );
switch( xNode->getType() )
{
case AnimationNodeType::CUSTOM :
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
}
break;
case AnimationNodeType::PAR :
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
sal_Int32 nFlags = nGroupLevel == 2 ? 0x10 : 0;
if ( bTakeBackInteractiveSequenceTiming )
nFlags |= 0x40;
exportAnimEvent( rStrm, xNode, nFlags );
exportAnimValue( rStrm, xNode, nGroupLevel == 4 );
}
break;
case AnimationNodeType::SEQ :
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
sal_Int16 nNodeType = exportAnimPropertySet( rStrm, xNode );
sal_Int32 nFlags = 12;
if ( ( nGroupLevel == 1 ) && ( nNodeType == ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE ) )
{
nFlags |= 0x20;
bTakeBackInteractiveSequenceTimingForChild = sal_True;
}
exportAnimAction( rStrm, xNode );
exportAnimEvent( rStrm, xNode, nFlags );
exportAnimValue( rStrm, xNode, sal_False );
}
break;
case AnimationNodeType::ITERATE :
{
{
EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
AnimationNode aAnim;
rtl_zeroMemory( &aAnim, sizeof( aAnim ) );
aAnim.mnGroupType = mso_Anim_GroupType_PAR;
aAnim.mnNodeType = 1;
// attribute Restart
switch( xNode->getRestart() )
{
default:
case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
}
// attribute Fill
switch( xNode->getFill() )
{
default:
case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
case AnimationFill::FREEZE : aAnim.mnFill = 2; break;
case AnimationFill::HOLD : aAnim.mnFill = 3; break;
case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
}
rStrm << aAnim;
}
exportIterate( rStrm, xNode );
exportAnimPropertySet( rStrm, xNode );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
/*
EscherExContainer aContainer( rStrm, DFF_msofbtAnimGroup, 1 );
exportAnimNode( rStrm, xNode, pParent, nGroupLevel + 1, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
*/
}
break;
case AnimationNodeType::ANIMATE :
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
exportAnimate( rStrm, xNode );
}
break;
case AnimationNodeType::SET :
{
bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
if( (nGroupLevel != 4) || !bIsAfterEffectNode )
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimateSet( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_SET : AFTEREFFECT_NONE );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
}
else
{
bSkipChildren = true;
}
}
break;
case AnimationNodeType::ANIMATEMOTION :
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimateMotion( rStrm, xNode );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
}
break;
case AnimationNodeType::ANIMATECOLOR :
{
bool bIsAfterEffectNode( isAfterEffectNode( xNode ) );
if( (nGroupLevel != 4) || !bIsAfterEffectNode )
{
if( bIsAfterEffectNode )
xNode = createAfterEffectNodeClone( xNode );
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimateColor( rStrm, xNode, bIsAfterEffectNode ? AFTEREFFECT_COLOR : AFTEREFFECT_NONE );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
}
else
{
bSkipChildren = true;
}
}
break;
case AnimationNodeType::ANIMATETRANSFORM :
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimateTransform( rStrm, xNode );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
}
break;
case AnimationNodeType::TRANSITIONFILTER :
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
exportAnimEvent( rStrm, xNode, 0 );
exportAnimValue( rStrm, xNode, sal_False );
exportTransitionFilter( rStrm, xNode );
}
break;
case AnimationNodeType::AUDIO : // #i58428#
{
exportAnimNode( rStrm, xNode, pParent, nGroupLevel, nFillDefault );
exportAnimPropertySet( rStrm, xNode );
Reference< XAudio > xAudio( xNode, UNO_QUERY );
if( xAudio.is() )
{
Any aAny( xAudio->getSource() );
rtl::OUString aURL;
if ( ( aAny >>= aURL ) && ( aURL.getLength() ) )
{
sal_Int32 nU1 = 2;
sal_Int32 nTrigger = 3;
sal_Int32 nU3 = nAudioGroup;
sal_Int32 nBegin = 0;
{
EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 1 );
{
EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
rStrm << nU1 << nTrigger << nU3 << nBegin;
}
}
nU1 = 1;
nTrigger = 0xb;
nU3 = 0;
{
EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, 2 );
{
EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
rStrm << nU1 << nTrigger << nU3 << nBegin;
}
}
EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
{
sal_uInt32 nRefMode = 3;
sal_uInt32 nRefType = 2;
sal_uInt32 nRefId = mrExSoundCollection.GetId( aURL );
sal_Int32 begin = -1;
sal_Int32 end = -1;
EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
rStrm << nRefMode << nRefType << nRefId << begin << end;
}
}
}
exportAnimValue( rStrm, xNode, sal_False );
}
break;
}
if( !bSkipChildren )
{
// export after effect node if one exists for this node
Reference< XAnimationNode > xAfterEffectNode;
if( hasAfterEffectNode( xNode, xAfterEffectNode ) )
{
exportNode( rStrm, xAfterEffectNode, &xNode, DFF_msofbtAnimSubGoup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
}
Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
if( xEnumerationAccess.is() )
{
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
if( xEnumeration.is() )
{
while( xEnumeration->hasMoreElements() )
{
Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
if( xChildNode.is() )
{
if ( xChildNode->getType() == AnimationNodeType::AUDIO )
{
xAudioNode = xChildNode;
nAudioGroup = mnCurrentGroup;
}
else
exportNode( rStrm, xChildNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel + 1, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
}
}
}
}
}
}
if ( xAudioNode.is() )
exportNode( rStrm, xAudioNode, &xNode, DFF_msofbtAnimGroup, 1, nGroupLevel, bTakeBackInteractiveSequenceTimingForChild, nFillDefault );
if( xNode->getType() == AnimationNodeType::ITERATE )
aTarget = Any();
}
Reference< XAnimationNode > AnimationExporter::createAfterEffectNodeClone( const Reference< XAnimationNode >& xNode ) const
{
try
{
Reference< ::com::sun::star::util::XCloneable > xClonable( xNode, UNO_QUERY_THROW );
Reference< XAnimationNode > xCloneNode( xClonable->createClone(), UNO_QUERY_THROW );
Any aEmpty;
xCloneNode->setBegin( aEmpty );
return xCloneNode;
}
catch( Exception& e )
{
(void)e;
DBG_ERROR("(@CL)sd::ppt::AnimationExporter::createAfterEffectNodeClone(), could not create clone!" );
}
return xNode;
}
void AnimationExporter::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 )
{
EscherExAtom aAnimNodeExAtom( rStrm, DFF_msofbtAnimNode );
AnimationNode aAnim;
rtl_zeroMemory( &aAnim, sizeof( aAnim ) );
// attribute Restart
switch( xNode->getRestart() )
{
default:
case AnimationRestart::DEFAULT : aAnim.mnRestart = 0; break;
case AnimationRestart::ALWAYS : aAnim.mnRestart = 1; break;
case AnimationRestart::WHEN_NOT_ACTIVE : aAnim.mnRestart = 2; break;
case AnimationRestart::NEVER : aAnim.mnRestart = 3; break;
}
// attribute Fill
// aAnim.mnFill = GetFillMode( xNode, pParent );
switch( nFillDefault )
{
default:
case AnimationFill::DEFAULT : aAnim.mnFill = 0; break;
case AnimationFill::REMOVE : aAnim.mnFill = 1; break;
case AnimationFill::FREEZE : // aAnim.mnFill = 2; break;
case AnimationFill::HOLD : aAnim.mnFill = 3; break;
case AnimationFill::TRANSITION : aAnim.mnFill = 4; break;
}
// attribute Duration
double fDuration = 0.0;
com::sun::star::animations::Timing eTiming;
if ( xNode->getDuration() >>= eTiming )
{
if ( eTiming == Timing_INDEFINITE )
aAnim.mnDuration = -1;
}
else if ( xNode->getDuration() >>= fDuration )
{
aAnim.mnDuration = (sal_Int32)( fDuration * 1000.0 );
}
else
aAnim.mnDuration = -1;
// NodeType, NodeGroup
aAnim.mnNodeType = 1;
aAnim.mnGroupType = mso_Anim_GroupType_SEQ;
switch( xNode->getType() )
{
case AnimationNodeType::PAR : // PASSTROUGH!!! (as it was intended)
aAnim.mnGroupType = mso_Anim_GroupType_PAR;
case AnimationNodeType::SEQ :
{
// trying to get the nodetype
Sequence< NamedValue > aUserData = xNode->getUserData();
if ( aUserData.getLength() )
{
const NamedValue* p = aUserData.getConstArray();
sal_Int32 nLength = aUserData.getLength();
while( nLength-- )
{
if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) )
{
sal_Int16 nType = 0;
if ( p->Value >>= nType )
{
switch( nType )
{
case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : aAnim.mnNodeType = 0x12; break;
case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : aAnim.mnNodeType = 0x18; break;
/*
case ::com::sun::star::presentation::EffectNodeType::ON_CLICK :
case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS :
case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS :
case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE :
default:
*/
}
}
break;
}
}
}
}
break;
case AnimationNodeType::ANIMATE :
case AnimationNodeType::SET :
case AnimationNodeType::CUSTOM :
case AnimationNodeType::ITERATE :
case AnimationNodeType::ANIMATEMOTION :
case AnimationNodeType::ANIMATECOLOR :
case AnimationNodeType::ANIMATETRANSFORM :
{
aAnim.mnGroupType = mso_Anim_GroupType_NODE;
aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
}
break;
case AnimationNodeType::AUDIO :
{
aAnim.mnGroupType = mso_Anim_GroupType_MEDIA;
aAnim.mnNodeType = mso_Anim_Behaviour_ANIMATION;
}
break;
case AnimationNodeType::TRANSITIONFILTER :
{
aAnim.mnGroupType = mso_Anim_GroupType_NODE;
aAnim.mnNodeType = mso_Anim_Behaviour_FILTER;
}
break;
}
rStrm << aAnim;
}
sal_Int16 AnimationExporter::exportAnimPropertySet( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
{
sal_Int16 nNodeType = ::com::sun::star::presentation::EffectNodeType::DEFAULT;
EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
const ::com::sun::star::uno::Any* pAny[ DFF_ANIM_PROPERTY_ID_COUNT ];
rtl_zeroMemory( pAny, sizeof( pAny ) );
Reference< XAnimationNode > xMaster;
const Any aTrue( makeAny( (sal_Bool)sal_True ) );
Any aMasterRel, aOverride, aRunTimeContext;
// storing user data into pAny, to allow direct access later
Sequence< NamedValue > aUserData = xNode->getUserData();
if ( aUserData.getLength() )
{
const NamedValue* p = aUserData.getConstArray();
sal_Int32 nLength = aUserData.getLength();
while( nLength-- )
{
if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) )
{
pAny[ DFF_ANIM_NODE_TYPE ] = &(p->Value);
}
else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-class" ) ) )
{
pAny[ DFF_ANIM_PRESET_CLASS ] = &(p->Value);
}
else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-id" ) ) )
{
pAny[ DFF_ANIM_PRESET_ID ] = &(p->Value);
}
else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-sub-type" ) ) )
{
pAny[ DFF_ANIM_PRESET_SUB_TYPE ] = &(p->Value);
}
else if ( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "master-element" ) ) )
{
pAny[ DFF_ANIM_AFTEREFFECT ] = &aTrue;
p->Value >>= xMaster;
}
p++;
}
}
// calculate master-rel
if( xMaster.is() )
{
sal_Int32 nMasterRel = 2;
Reference< XChild > xNodeChild( xNode, UNO_QUERY );
Reference< XChild > xMasterChild( xMaster, UNO_QUERY );
if( xNodeChild.is() && xMasterChild.is() && (xNodeChild->getParent() == xMasterChild->getParent() ) )
nMasterRel = 0;
aMasterRel <<= nMasterRel;
pAny[ DFF_ANIM_MASTERREL ] = &aMasterRel;
aOverride <<= (sal_Int32)1;
pAny[ DFF_ANIM_OVERRIDE ] = &aOverride;
aRunTimeContext <<= (sal_Int32)1;
pAny[ DFF_ANIM_RUNTIMECONTEXT ] = &aRunTimeContext;
}
// the order is important
if ( pAny[ DFF_ANIM_NODE_TYPE ] )
{
if ( *pAny[ DFF_ANIM_NODE_TYPE ] >>= nNodeType )
{
sal_uInt32 nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK;
switch( nNodeType )
{
case ::com::sun::star::presentation::EffectNodeType::ON_CLICK : nPPTNodeType = DFF_ANIM_NODE_TYPE_ON_CLICK; break;
case ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_WITH_PREVIOUS; break;
case ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS : nPPTNodeType = DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS; break;
case ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE : nPPTNodeType = DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE; break;
case ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT : nPPTNodeType = DFF_ANIM_NODE_TYPE_TIMING_ROOT; break;
case ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE: nPPTNodeType = DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ; break;
}
exportAnimPropertyuInt32( rStrm, DFF_ANIM_NODE_TYPE, nPPTNodeType, TRANSLATE_NONE );
}
}
sal_uInt32 nPresetId = 0;
sal_uInt32 nPresetSubType = 0;
sal_uInt32 nAPIPresetClass = EffectPresetClass::CUSTOM;
sal_uInt32 nPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
sal_Bool bPresetClass, bPresetId, bPresetSubType;
bPresetClass = bPresetId = bPresetSubType = sal_False;
if ( pAny[ DFF_ANIM_PRESET_CLASS ] )
{
if ( *pAny[ DFF_ANIM_PRESET_CLASS ] >>= nAPIPresetClass )
{
sal_uInt8 nPPTPresetClass;
switch( nAPIPresetClass )
{
case EffectPresetClass::ENTRANCE : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_ENTRANCE; break;
case EffectPresetClass::EXIT : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EXIT; break;
case EffectPresetClass::EMPHASIS : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_EMPHASIS; break;
case EffectPresetClass::MOTIONPATH : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MOTIONPATH; break;
case EffectPresetClass::OLEACTION : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_OLE_ACTION; break;
case EffectPresetClass::MEDIACALL : nPPTPresetClass = DFF_ANIM_PRESS_CLASS_MEDIACALL; break;
default :
nPPTPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
}
nPresetClass = nPPTPresetClass;
bPresetClass = sal_True;
}
}
if ( pAny[ DFF_ANIM_PRESET_ID ] )
{
rtl::OUString sPreset;
if ( *pAny[ DFF_ANIM_PRESET_ID ] >>= sPreset )
{
if ( sPreset.match( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ppt_" ) ), 0 ) )
{
sal_Int32 nLast = sPreset.lastIndexOf( '_' );
if ( ( nLast != -1 ) && ( ( nLast + 1 ) < sPreset.getLength() ) )
{
rtl::OUString aNumber( sPreset.copy( nLast + 1 ) );
nPresetId = aNumber.toInt32();
bPresetId = sal_True;
}
}
else
{
const preset_maping* p = gPresetMaping;
while( p->mpStrPresetId && ((p->mnPresetClass != (sal_Int32)nAPIPresetClass) || !sPreset.equalsAscii( p->mpStrPresetId )) )
p++;
if( p->mpStrPresetId )
{
nPresetId = p->mnPresetId;
bPresetId = sal_True;
}
}
}
}
if ( pAny[ DFF_ANIM_PRESET_SUB_TYPE ] )
{
rtl::OUString sPresetSubType;
if ( *pAny[ DFF_ANIM_PRESET_SUB_TYPE ] >>= sPresetSubType )
{
nPresetSubType = ImplTranslatePresetSubType( nPresetClass, nPresetId, sPresetSubType );
bPresetSubType = sal_True;
}
}
if ( bPresetId )
exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_ID, nPresetId, TRANSLATE_NONE );
if ( bPresetSubType )
exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_SUB_TYPE, nPresetSubType, TRANSLATE_NONE );
if ( bPresetClass )
exportAnimPropertyuInt32( rStrm, DFF_ANIM_PRESET_CLASS, nPresetClass, TRANSLATE_NONE );
if ( pAny[ DFF_ANIM_ID ] )
{
// TODO DFF_ANIM_ID
}
if ( pAny[ DFF_ANIM_AFTEREFFECT ] )
{
sal_Bool bAfterEffect = sal_False;
if ( *pAny[ DFF_ANIM_AFTEREFFECT ] >>= bAfterEffect )
exportAnimPropertyByte( rStrm, DFF_ANIM_AFTEREFFECT, bAfterEffect, TRANSLATE_NONE );
}
if ( pAny[ DFF_ANIM_RUNTIMECONTEXT ] )
{
sal_Int32 nRunTimeContext = 0;
if ( *pAny[ DFF_ANIM_RUNTIMECONTEXT ] >>= nRunTimeContext )
exportAnimPropertyuInt32( rStrm, DFF_ANIM_RUNTIMECONTEXT, nRunTimeContext, TRANSLATE_NONE );
}
if ( pAny[ DFF_ANIM_PATH_EDIT_MODE ] )
{
// TODO DFF_ANIM_ID
}
if( !xMaster.is() )
{
Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
if( xColor.is() )
{
// sal_uInt32 nColorSpace = xColor->getColorSpace() == AnimationColorSpace::RGB ? 0 : 1;
// exportAnimPropertyuInt32( rStrm, DFF_ANIM_COLORSPACE, nColorSpace, TRANSLATE_NONE );
sal_Bool bDirection = !xColor->getDirection();
exportAnimPropertyuInt32( rStrm, DFF_ANIM_DIRECTION, bDirection, TRANSLATE_NONE );
}
}
if ( pAny[ DFF_ANIM_OVERRIDE ] )
{
sal_Int32 nOverride = 0;
if ( *pAny[ DFF_ANIM_OVERRIDE ] >>= nOverride )
exportAnimPropertyuInt32( rStrm, DFF_ANIM_OVERRIDE, nOverride, TRANSLATE_NONE );
}
if ( pAny[ DFF_ANIM_MASTERREL ] )
{
sal_Int32 nMasterRel = 0;
if ( *pAny[ DFF_ANIM_MASTERREL ] >>= nMasterRel )
exportAnimPropertyuInt32( rStrm, DFF_ANIM_MASTERREL, nMasterRel, TRANSLATE_NONE );
}
/* todo
Reference< XAudio > xAudio( xNode, UNO_QUERY );
if( xAudio.is() )
{
sal_Int16 nEndAfterSlide = 0;
nEndAfterSlide = xAudio->getEndAfterSlide();
exportAnimPropertyuInt32( rStrm, DFF_ANIM_ENDAFTERSLIDE, nEndAfterSlide, TRANSLATE_NONE );
}
*/
Reference< XAnimate > xAnim( xNode, UNO_QUERY );
if( xAnim.is() )
{
// TODO: DFF_ANIM_TIMEFILTER
}
if ( pAny[ DFF_ANIM_EVENT_FILTER ] )
{
// TODO DFF_ANIM_EVENT_FILTER
}
if ( pAny[ DFF_ANIM_VOLUME ] )
{
// TODO DFF_ANIM_VOLUME
}
return nNodeType;
}
sal_Bool AnimationExporter::exportAnimProperty( SvStream& rStrm, const sal_uInt16 nPropertyId, const ::com::sun::star::uno::Any& rAny, const TranslateMode eTranslateMode )
{
sal_Bool bRet = sal_False;
if ( rAny.hasValue() )
{
switch( rAny.getValueType().getTypeClass() )
{
case ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT :
case ::com::sun::star::uno::TypeClass_SHORT :
case ::com::sun::star::uno::TypeClass_UNSIGNED_LONG :
case ::com::sun::star::uno::TypeClass_LONG :
{
sal_Int32 nVal = 0;
if ( rAny >>= nVal )
{
exportAnimPropertyuInt32( rStrm, nPropertyId, nVal, eTranslateMode );
bRet = sal_True;
}
}
break;
case ::com::sun::star::uno::TypeClass_DOUBLE :
{
double fVal = 0.0;
if ( rAny >>= fVal )
{
exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
bRet = sal_True;
}
}
break;
case ::com::sun::star::uno::TypeClass_FLOAT :
{
float fVal = 0.0;
if ( rAny >>= fVal )
{
if ( eTranslateMode & TRANSLATE_NUMBER_TO_STRING )
{
Any aAny;
rtl::OUString aNumber( rtl::OUString::valueOf( fVal ) );
aAny <<= aNumber;
exportAnimPropertyString( rStrm, nPropertyId, aNumber, eTranslateMode );
}
else
{
exportAnimPropertyFloat( rStrm, nPropertyId, fVal, eTranslateMode );
bRet = sal_True;
}
}
}
break;
case ::com::sun::star::uno::TypeClass_STRING :
{
rtl::OUString aStr;
if ( rAny >>= aStr )
{
exportAnimPropertyString( rStrm, nPropertyId, aStr, eTranslateMode );
bRet = sal_True;
}
}
break;
default:
break;
}
}
return bRet;
}
void AnimationExporter::exportAnimPropertyString( SvStream& rStrm, const sal_uInt16 nPropertyId, const rtl::OUString& rVal, const TranslateMode eTranslateMode )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
sal_uInt8 nType = DFF_ANIM_PROP_TYPE_UNISTRING;
rStrm << nType;
rtl::OUString aStr( rVal );
if ( eTranslateMode != TRANSLATE_NONE )
ImplTranslateAttribute( aStr, eTranslateMode );
writeZString( rStrm, aStr );
}
void AnimationExporter::exportAnimPropertyFloat( SvStream& rStrm, const sal_uInt16 nPropertyId, const double& rVal, const TranslateMode )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
sal_uInt8 nType = DFF_ANIM_PROP_TYPE_FLOAT;
float fFloat = (float)rVal;
rStrm << nType
<< fFloat;
}
void AnimationExporter::exportAnimPropertyuInt32( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt32 nVal, const TranslateMode )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
sal_uInt8 nType = DFF_ANIM_PROP_TYPE_INT32 ;
rStrm << nType
<< nVal;
}
void AnimationExporter::exportAnimPropertyByte( SvStream& rStrm, const sal_uInt16 nPropertyId, const sal_uInt8 nVal, const TranslateMode )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAttributeValue, nPropertyId );
sal_uInt8 nType = DFF_ANIM_PROP_TYPE_BYTE;
rStrm << nType
<< nVal;
}
void AnimationExporter::writeZString( SvStream& rStrm, const rtl::OUString& rVal )
{
sal_Int32 i;
for ( i = 0; i < rVal.getLength(); i++ )
rStrm << rVal[ i ];
rStrm << (sal_Unicode)0;
}
void AnimationExporter::exportAnimAction( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimAction );
sal_Int32 nConcurrent = 1;
sal_Int32 nNextAction = 1;
sal_Int32 nEndSync = 0;
sal_Int32 nU4 = 0;
sal_Int32 nU5 = 3;
sal_Int16 nAnimationEndSync = 0;
if ( xNode->getEndSync() >>= nAnimationEndSync )
{
if ( nAnimationEndSync == AnimationEndSync::ALL )
nEndSync = 1;
}
rStrm << nConcurrent
<< nNextAction
<< nEndSync
<< nU4
<< nU5;
}
// nFlags Bit 6 = fixInteractiveSequenceTiming (for child)
// nFlags Bit 5 = fixInteractiveSequenceTiming (for root)
// nFlags Bit 4 = first node of main sequence -> begin event next has to be replaced to indefinite
void AnimationExporter::exportAnimEvent( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Int32 nFlags )
{
sal_uInt16 i;
for ( i = 0; i < 4; i++ )
{
sal_Int32 nU1 = 0;
sal_Int32 nTrigger = 0;
sal_Int32 nU3 = 0;
sal_Int32 nBegin = 0;
sal_Bool bCreateEvent = sal_False;
Any aSource;
switch( i )
{
case 0 :
case 1 :
{
Any aAny;
Event aEvent;
com::sun::star::animations::Timing eTiming;
if ( i == 0 )
{
if ( nFlags & 0x20 )
{
// taking the first child
Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW );
Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW );
if ( xE.is() && xE->hasMoreElements() )
{
// while( xE->hasMoreElements() )
{
Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY );
aAny = xClickNode->getBegin();
}
}
}
else if ( nFlags & 0x40 )
{
// begin has to be replaced with void, so don't do anything
}
else
{
aAny = xNode->getBegin();
if ( nFlags & 0x10 ) // replace ON_NEXT with IDEFINITE
{
if ( ( aAny >>= aEvent ) && ( aEvent.Trigger == EventTrigger::ON_NEXT ) )
{
eTiming = Timing_INDEFINITE;
aAny <<= eTiming;
}
}
}
}
else
aAny = xNode->getEnd();
double fTiming = 0.0;
if ( aAny >>= aEvent )
{
bCreateEvent = sal_True;
switch( aEvent.Trigger )
{
case EventTrigger::NONE : nTrigger = 0; break;
case EventTrigger::ON_BEGIN : nTrigger = 1; break;
case EventTrigger::ON_END : nTrigger = 2; break;
case EventTrigger::BEGIN_EVENT : nTrigger = 3; break;
case EventTrigger::END_EVENT : nTrigger = 4; nU1 = 2; nU3 = mnCurrentGroup; break;
case EventTrigger::ON_CLICK : nTrigger = 5; break;
case EventTrigger::ON_DBL_CLICK : nTrigger = 6; break;
case EventTrigger::ON_MOUSE_ENTER : nTrigger = 7; break;
case EventTrigger::ON_MOUSE_LEAVE : nTrigger = 8; break;
case EventTrigger::ON_NEXT : nTrigger = 9; break;
case EventTrigger::ON_PREV : nTrigger = 10; break;
case EventTrigger::ON_STOP_AUDIO : nTrigger = 11; break;
}
if ( aEvent.Offset.hasValue() )
{
if ( aEvent.Offset >>= eTiming )
{
if ( eTiming == Timing_INDEFINITE )
nBegin = -1;
}
else if ( aEvent.Offset >>= fTiming )
nBegin = (sal_Int32)( fTiming * 1000.0 );
}
aSource = aEvent.Source;
}
else if ( aAny >>= eTiming )
{
bCreateEvent = sal_True;
if ( eTiming == Timing_INDEFINITE )
nBegin = -1;
}
else if ( aAny >>= fTiming )
{
bCreateEvent = sal_True;
nBegin = (sal_Int32)( fTiming * 1000.0 );
}
}
break;
case 2 :
{
if ( nFlags & ( 1 << i ) )
{
bCreateEvent = sal_True;
nU1 = 1;
nTrigger = 9;
}
}
break;
case 3 :
{
if ( nFlags & ( 1 << i ) )
{
bCreateEvent = sal_True;
nU1 = 1;
nTrigger = 10;
}
}
break;
};
if ( bCreateEvent )
{
EscherExContainer aAnimEvent( rStrm, DFF_msofbtAnimEvent, i + 1 );
{
EscherExAtom aAnimTrigger( rStrm, DFF_msofbtAnimTrigger );
rStrm << nU1
<< nTrigger
<< nU3
<< nBegin;
}
exportAnimateTargetElement( rStrm, aSource, ( nFlags & ( 1 << i ) ) != 0 );
}
}
}
Any AnimationExporter::convertAnimateValue( const Any& rSourceValue, const rtl::OUString& rAttributeName ) const
{
rtl::OUString aDest;
if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "X" ) )
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Y" ) )
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Width" ) )
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Height" ) )
)
{
rtl::OUString aStr;
if ( rSourceValue >>= aStr )
{
ImplTranslateAttribute( aStr, TRANSLATE_MEASURE );
aDest += aStr;
}
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Rotate" ) ) // "r" or "style.rotation" ?
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SkewX" ) )
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Opacity" ) )
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharHeight" ) )
)
{
double fNumber = 0.0;
if ( rSourceValue >>= fNumber )
aDest += rtl::OUString::valueOf( fNumber );
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Color" ) )
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FillColor" ) ) // "Fillcolor" or "FillColor" ?
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "LineColor" ) )
|| rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharColor" ) )
)
{
sal_Int32 nColor = 0;
Sequence< double > aHSL( 3 );
rtl::OUString aP( RTL_CONSTASCII_USTRINGPARAM( "," ) );
if ( rSourceValue >>= aHSL )
{
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hsl(" ) );
aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 0 ] / ( 360.0 / 255 ) ) );
aDest += aP;
aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 1 ] * 255.0 ) );
aDest += aP;
aDest += rtl::OUString::valueOf( (sal_Int32)( aHSL[ 2 ] * 255.0 ) );
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
}
else if ( rSourceValue >>= nColor )
{
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "rgb(" ) );
aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)nColor ) );
aDest += aP;
aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 8 ) ) );
aDest += aP;
aDest += rtl::OUString::valueOf( (sal_Int32)( (sal_Int8)( nColor >> 16 ) ) );
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
}
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "FillStyle" ) ) )
{
::com::sun::star::drawing::FillStyle eFillStyle;
if ( rSourceValue >>= eFillStyle )
{
if ( eFillStyle == ::com::sun::star::drawing::FillStyle_NONE )
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "none" ) ); // ?
else
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "solid" ) );
}
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "LineStyle" ) ) )
{
::com::sun::star::drawing::LineStyle eLineStyle;
if ( rSourceValue >>= eLineStyle )
{
if ( eLineStyle == ::com::sun::star::drawing::LineStyle_NONE )
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
else
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
}
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharWeight" ) ) )
{
float fFontWeight = 0.0;
if ( rSourceValue >>= fFontWeight )
{
if ( fFontWeight == com::sun::star::awt::FontWeight::BOLD )
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "bold" ) );
else
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "normal" ) );
}
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharUnderline" ) ) )
{
sal_Int16 nFontUnderline = 0;
if ( rSourceValue >>= nFontUnderline )
{
if ( nFontUnderline == com::sun::star::awt::FontUnderline::NONE )
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
else
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
}
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CharPosture" ) ) )
{
::com::sun::star::awt::FontSlant eFontSlant;
if ( rSourceValue >>= eFontSlant )
{
if ( eFontSlant == com::sun::star::awt::FontSlant_ITALIC )
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "italic" ) );
else
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "normal" ) ); // ?
}
}
else if ( rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Visibility" ) ) )
{
sal_Bool bVisible = sal_True;
if ( rSourceValue >>= bVisible )
{
if ( bVisible )
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "visible" ) );
else
aDest += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hidden" ) );
}
}
Any aRet;
if ( aDest.getLength() )
aRet <<= aDest;
else
aRet = rSourceValue;
return aRet;
}
void AnimationExporter::exportAnimateSet( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
{
Reference< XAnimateSet > xSet( xNode, UNO_QUERY );
if( xSet.is() )
{
EscherExContainer aAnimateSet( rStrm, DFF_msofbtAnimateSet, 0 );
{
EscherExAtom aAnimateSetData( rStrm, DFF_msofbtAnimateSetData );
sal_uInt32 nId1 = 1; // ??
sal_uInt32 nId2 = 1; // ??
rStrm << nId1 << nId2;
}
Any aConvertedValue( convertAnimateValue( xSet->getTo(), xSet->getAttributeName() ) );
if ( aConvertedValue.hasValue() )
exportAnimProperty( rStrm, 1, aConvertedValue, TRANSLATE_NONE );
exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
}
}
sal_uInt32 GetValueTypeForAttributeName( const rtl::OUString& rAttributeName )
{
sal_uInt32 nValueType = 0;
/*
AnimationValueType::STRING == 0;
AnimationValueType::NUMBER == 1;
AnimationValueType::COLOR == 2;
*/
struct Entry
{
const sal_Char* pName;
sal_uInt8 nType;
};
static const Entry lcl_attributeMap[] =
{
{ "charcolor", 2 },
{ "charfontname", 0 },
{ "charheight", 1 },
{ "charposture", 0 },
// TODO(Q1): This should prolly be changed in PPT import
// { "charrotation", ATTRIBUTE_CHAR_ROTATION },
{ "charrotation", 1 },
{ "charunderline", 0 },
{ "charweight", 0 },
{ "color", 2 },
{ "dimcolor", 2 },
{ "fillcolor", 2 },
{ "fillstyle", 0 },
{ "height", 1 },
{ "linecolor", 2 },
{ "linestyle", 0 },
{ "opacity", 0 },
{ "rotate", 1 },
{ "skewx", 1 },
{ "skewy", 1 },
{ "visibility", 1 },
{ "width", 1 },
{ "x", 1 },
{ "y", 1 },
{ NULL, 0 }
};
const Entry* pPtr = &lcl_attributeMap[ 0 ];
while( pPtr->pName )
{
if ( rAttributeName.equalsIgnoreAsciiCaseAscii( pPtr->pName ) )
{
nValueType = pPtr->nType;
break;
}
pPtr++;
}
DBG_ASSERT( pPtr->pName, "GetValueTypeForAttributeName, unknown property value!" );
return nValueType;
}
void AnimationExporter::exportAnimate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
{
Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
if ( xAnimate.is() )
{
Any aBy ( xAnimate->getBy() );
Any aFrom( xAnimate->getFrom() );
Any aTo ( xAnimate->getTo() );
EscherExContainer aContainer( rStrm, DFF_msofbtAnimate, 0 );
{
EscherExAtom aAnimateData( rStrm, DFF_msofbtAnimateData );
sal_uInt32 nBits = 0x38;
sal_Int16 nTmp = xAnimate->getCalcMode();
sal_uInt32 nCalcMode = /* (nTmp == AnimationCalcMode::FORMULA) ? 2 : */ (nTmp == AnimationCalcMode::LINEAR) ? 1 : 0;
nTmp = xAnimate->getValueType();
sal_uInt32 nValueType = GetValueTypeForAttributeName( xAnimate->getAttributeName() );
if ( aBy.hasValue() )
nBits |= 1;
if ( aFrom.hasValue() )
nBits |= 2;
if ( aTo.hasValue() )
nBits |= 4;
rStrm << nCalcMode
<< nBits
<< nValueType;
}
if ( aBy.hasValue() )
exportAnimProperty( rStrm, 1, aBy, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
if ( aFrom.hasValue() )
exportAnimProperty( rStrm, 2, aFrom, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
if ( aTo.hasValue() )
exportAnimProperty( rStrm, 3, aTo, TRANSLATE_NUMBER_TO_STRING | TRANSLATE_MEASURE );
exportAnimateKeyPoints( rStrm, xAnimate );
exportAnimateTarget( rStrm, xNode );
}
}
void AnimationExporter::exportAnimateTarget( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_uInt32 nForceAttributeNames, int nAfterEffectType )
{
EscherExContainer aAnimateTarget( rStrm, DFF_msofbtAnimateTarget, 0 );
Reference< XAnimate > xAnimate( xNode, UNO_QUERY );
if ( xAnimate.is() )
{
{
EscherExAtom aAnimateTargetSettings( rStrm, DFF_msofbtAnimateTargetSettings, 0 );
// nBits %0001: additive, %0010: accumulate, %0100: attributeName, %1000: transformtype
// nAdditive 0 = base, 1 = sum, 2 = replace, 3 = multiply, 4 = none
// nAccumulate 0 = none, 1 = always
// nTransformType 0: "property" else "image"
sal_uInt32 nBits = 0;
sal_uInt32 nAdditive = 0;
sal_uInt32 nAccumulate = 0;
sal_uInt32 nTransformType = 0;
if ( xAnimate.is() )
{
if ( xAnimate->getAttributeName().getLength() )
nBits |= 4; // what is attributeName ?, maybe this is set if a DFF_msofbtAnimateAttributeNames is written
sal_Int16 nAdditiveMode = xAnimate->getAdditive();
if ( nAdditiveMode != AnimationAdditiveMode::BASE )
{
nBits |= 1;
switch( nAdditiveMode )
{
case AnimationAdditiveMode::SUM : nAdditive = 1; break;
case AnimationAdditiveMode::REPLACE : nAdditive = 2; break;
case AnimationAdditiveMode::MULTIPLY : nAdditive = 3; break;
case AnimationAdditiveMode::NONE : nAdditive = 4; break;
}
}
if ( xAnimate->getAccumulate() )
{
nBits |= 2;
nAccumulate = 1;
}
}
rStrm << nBits
<< nAdditive
<< nAccumulate
<< nTransformType;
}
if ( xAnimate->getAttributeName().getLength() || nForceAttributeNames )
{
EscherExContainer aAnimateAttributeNames( rStrm, DFF_msofbtAnimateAttributeNames, 1 );
rtl::OUString aAttributeName( xAnimate->getAttributeName() );
if ( nForceAttributeNames )
{
switch( nForceAttributeNames )
{
case 1 : aAttributeName = rtl::OUString::createFromAscii( "r" ); break;
}
}
sal_Int32 nIndex = 0;
do
{
OUString aToken( aAttributeName.getToken( 0, ';', nIndex ) );
exportAnimPropertyString( rStrm, 0, aToken, TRANSLATE_ATTRIBUTE );
}
while ( nIndex >= 0 );
}
if( nAfterEffectType != AFTEREFFECT_NONE )
{
EscherExContainer aAnimPropertySet( rStrm, DFF_msofbtAnimPropertySet );
exportAnimPropertyuInt32( rStrm, 6, 1, TRANSLATE_NONE );
if( nAfterEffectType == AFTEREFFECT_COLOR )
{
exportAnimPropertyuInt32( rStrm, 4, 0, TRANSLATE_NONE );
exportAnimPropertyuInt32( rStrm, 5, 0, TRANSLATE_NONE );
}
}
exportAnimateTargetElement( rStrm, aTarget.hasValue() ? aTarget : xAnimate->getTarget(), sal_False );
}
}
void AnimationExporter::exportAnimateTargetElement( SvStream& rStrm, const Any aAny, const sal_Bool bCreate2b01Atom )
{
Reference< XShape > xShape;
aAny >>= xShape;
sal_uInt32 nRefMode = 0; // nRefMode == 2 -> Paragraph
sal_Int32 begin = -1;
sal_Int32 end = -1;
if( !xShape.is() )
{
ParagraphTarget aParaTarget;
if( aAny >>= aParaTarget )
xShape = aParaTarget.Shape;
if ( xShape.is() )
{
// now calculating the character range for the paragraph
sal_Int16 nParagraph = aParaTarget.Paragraph;
Reference< XSimpleText > xText( xShape, UNO_QUERY );
if ( xText.is() )
{
nRefMode = 2;
Reference< XEnumerationAccess > xTextParagraphEnumerationAccess( xText, UNO_QUERY );
if ( xTextParagraphEnumerationAccess.is() )
{
Reference< XEnumeration > xTextParagraphEnumeration( xTextParagraphEnumerationAccess->createEnumeration() );
if ( xTextParagraphEnumeration.is() )
{
sal_Int16 nCurrentParagraph;
begin = end = nCurrentParagraph = 0;
while ( xTextParagraphEnumeration->hasMoreElements() )
{
Reference< XTextRange > xTextRange( xTextParagraphEnumeration->nextElement(), UNO_QUERY );
if ( xTextRange.is() )
{
rtl::OUString aParaText( xTextRange->getString() );
sal_Int32 nLength = aParaText.getLength() + 1;
end += nLength;
if ( nCurrentParagraph == nParagraph )
break;
nCurrentParagraph++;
begin += nLength;
}
}
}
}
}
}
}
if ( xShape.is() || bCreate2b01Atom )
{
EscherExContainer aAnimateTargetElement( rStrm, DFF_msofbtAnimateTargetElement );
if ( xShape.is() )
{
EscherExAtom aAnimReference( rStrm, DFF_msofbtAnimReference );
sal_uInt32 nRefType = 1; // TODO: nRefType == 2 -> Sound;
sal_uInt32 nRefId = ((EscherSolverContainer&)mrSolverContainer).GetShapeId( xShape );
rStrm << nRefMode
<< nRefType
<< nRefId
<< begin
<< end;
}
if ( bCreate2b01Atom )
{
EscherExAtom a2b01Atom( rStrm, 0x2b01 );
rStrm << (sal_uInt32)1; // ?
}
}
}
void AnimationExporter::exportAnimateKeyPoints( SvStream& rStrm, const Reference< XAnimate >& xAnimate )
{
Sequence< double > aKeyTimes( xAnimate->getKeyTimes() );
Sequence< Any > aValues( xAnimate->getValues() );
OUString aFormula( xAnimate->getFormula() );
if ( aKeyTimes.getLength() )
{
EscherExContainer aAnimKeyPoints( rStrm, DFF_msofbtAnimKeyPoints );
sal_Int32 i;
for ( i = 0; i < aKeyTimes.getLength(); i++ )
{
{
EscherExAtom aAnimKeyTime( rStrm, DFF_msofbtAnimKeyTime );
sal_Int32 nKeyTime = (sal_Int32)( aKeyTimes[ i ] * 1000.0 );
rStrm << nKeyTime;
}
Any aAny[ 2 ];
if ( aValues[ i ].hasValue() )
{
ValuePair aPair;
if ( aValues[ i ] >>= aPair )
{
aAny[ 0 ] = convertAnimateValue( aPair.First, xAnimate->getAttributeName() );
aAny[ 1 ] = convertAnimateValue( aPair.Second, xAnimate->getAttributeName() );
}
else
{
aAny[ 0 ] = convertAnimateValue( aValues[ i ], xAnimate->getAttributeName() );
}
if ( !i && aFormula.getLength() )
{
ImplTranslateAttribute( aFormula, TRANSLATE_MEASURE );
aAny[ 1 ] <<= aFormula;
}
exportAnimProperty( rStrm, 0, aAny[ 0 ], TRANSLATE_NONE );
exportAnimProperty( rStrm, 1, aAny[ 1 ], TRANSLATE_NONE );
}
}
}
}
void AnimationExporter::exportAnimValue( SvStream& rStrm, const Reference< XAnimationNode >& xNode, const sal_Bool bExportAlways )
{
Any aAny;
// repeat count (0)
double fRepeat = 0.0;
float fRepeatCount = 0.0;
com::sun::star::animations::Timing eTiming;
aAny = xNode->getRepeatCount();
if ( aAny >>= eTiming )
{
if ( eTiming == Timing_INDEFINITE )
fRepeatCount = ((float)3.40282346638528860e+38);
}
else if ( aAny >>= fRepeat )
fRepeatCount = (float)fRepeat;
if ( fRepeatCount != 0.0 )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
sal_uInt32 nType = 0;
rStrm << nType
<< fRepeatCount;
}
// accelerate (3)
float fAccelerate = (float)xNode->getAcceleration();
if ( bExportAlways || ( fAccelerate != 0.0 ) )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
sal_uInt32 nType = 3;
rStrm << nType
<< fAccelerate;
}
// decelerate (4)
float fDecelerate = (float)xNode->getDecelerate();
if ( bExportAlways || ( fDecelerate != 0.0 ) )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
sal_uInt32 nType = 4;
rStrm << nType
<< fDecelerate;
}
// autoreverse (5)
sal_Bool bAutoReverse = xNode->getAutoReverse();
if ( bExportAlways || bAutoReverse )
{
EscherExAtom aExAtom( rStrm, DFF_msofbtAnimValue );
sal_uInt32 nType = 5;
sal_uInt32 nVal = bAutoReverse ? 1 : 0;
rStrm << nType
<< nVal;
}
}
void AnimationExporter::exportTransitionFilter( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
{
Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY );
if ( xFilter.is() )
{
EscherExContainer aAnimateFilter( rStrm, DFF_msofbtAnimateFilter );
{
EscherExAtom aAnimateFilterData( rStrm, DFF_msofbtAnimateFilterData );
sal_uInt32 nBits = 3; // bit 0 -> use AnimAttributeValue
// bit 1 -> use nTransition
sal_uInt32 nTransition = xFilter->getMode() ? 0 : 1;
rStrm << nBits
<< nTransition;
}
const sal_Char* pFilter = transition::find( xFilter->getTransition(), xFilter->getSubtype(), xFilter->getDirection() );
if ( pFilter )
{
const OUString aStr( OUString::createFromAscii( pFilter ) );
exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
}
exportAnimateTarget( rStrm, xNode );
}
}
void AnimationExporter::exportAnimateMotion( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
{
Reference< XAnimateMotion > xMotion( xNode, UNO_QUERY );
if ( xMotion.is() )
{
EscherExContainer aAnimateMotion( rStrm, DFF_msofbtAnimateMotion );
{
{ //SJ: Ignored from import filter
EscherExAtom aAnimateMotionData( rStrm, DFF_msofbtAnimateMotionData );
sal_uInt32 nBits = 0x98;
sal_uInt32 nOrigin = 0x2;
float fByX = 100.0; // nBits&1
float fByY = 100.0; // nBits&1
float fFromX = 0.0; // nBits&2
float fFromY = 0.0; // nBits&2
float fToX = 100.0; // nBits&4
float fToY = 100.0; // nBits&4
rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nOrigin;
}
/* ?
{
EscherExAtom aF137( rStrm, 0xf137 );
}
*/
OUString aStr;
if ( xMotion->getPath() >>= aStr )
{
if ( aStr.getLength() )
exportAnimPropertyString( rStrm, 1, aStr, TRANSLATE_NONE );
}
exportAnimateTarget( rStrm, xNode );
}
}
}
void AnimationExporter::exportAnimateTransform( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
{
Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY );
if ( xTransform.is() )
{
if ( xTransform->getTransformType() == AnimationTransformType::SCALE )
{
EscherExContainer aAnimateScale( rStrm, DFF_msofbtAnimateScale );
{
EscherExAtom aAnimateScaleData( rStrm, DFF_msofbtAnimateScaleData );
sal_uInt32 nBits = 0;
sal_uInt32 nZoomContents = 1;
float fByX = 100.0;
float fByY = 100.0;
float fFromX = 0.0;
float fFromY = 0.0;
float fToX = 100.0;
float fToY = 100.0;
double fX = 0.0, fY = 0.0;
ValuePair aPair;
if ( xTransform->getBy() >>= aPair )
{
if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
{
nBits |= 1;
fByX = (float)( fX * 100 );
fByY = (float)( fY * 100 );
}
}
if ( xTransform->getFrom() >>= aPair )
{
if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
{
nBits |= 2;
fFromX = (float)( fX * 100 );
fFromY = (float)( fY * 100 );
}
}
if( xTransform->getTo() >>= aPair )
{
if ( ( aPair.First >>= fX ) && ( aPair.Second >>= fY ) )
{
nBits |= 4;
fToX = (float)( fX * 100 );
fToY = (float)( fY * 100 );
}
}
// TODO: ZoomContents:
//if( nBits & 8 )
//( fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" );
rStrm << nBits << fByX << fByY << fFromX << fFromY << fToX << fToY << nZoomContents;
}
exportAnimateTarget( rStrm, xNode );
}
else if ( xTransform->getTransformType() == AnimationTransformType::ROTATE )
{
EscherExContainer aAnimateRotation( rStrm, DFF_msofbtAnimateRotation );
{
EscherExAtom aAnimateRotationData( rStrm, DFF_msofbtAnimateRotationData );
sal_uInt32 nBits = 0;
sal_uInt32 nU1 = 0;
float fBy = 360.0;
float fFrom = 0.0;
float fTo = 360.0;
double fVal = 0.0;
if ( xTransform->getBy() >>= fVal )
{
nBits |= 1;
fBy = (float)fVal;
}
if ( xTransform->getFrom() >>= fVal )
{
nBits |= 2;
fFrom = (float)fVal;
}
if ( xTransform->getTo() >>= fVal )
{
nBits |= 4;
fTo = (float)fVal;
}
rStrm << nBits << fBy << fFrom << fTo << nU1;
}
exportAnimateTarget( rStrm, xNode, 1 );
}
}
}
sal_Bool AnimationExporter::getColorAny( const Any& rAny, const sal_Int16 nColorSpace, sal_Int32& rMode, sal_Int32& rA, sal_Int32& rB, sal_Int32& rC ) const
{
sal_Bool bIsColor = sal_True;
rMode = 0;
if ( nColorSpace == AnimationColorSpace::HSL )
rMode = 1;
sal_Int32 nColor = 0;
Sequence< double > aHSL( 3 );
if ( rAny >>= nColor ) // RGB color
{
rA = (sal_uInt8)( nColor >> 16 );
rB = (sal_uInt8)( nColor >> 8 );
rC = (sal_uInt8)( nColor );
}
else if ( rAny >>= aHSL ) // HSL
{
rA = (sal_Int32) ( aHSL[ 0 ] * 255.0 / 360.0 );
rB = (sal_Int32) ( aHSL[ 1 ] * 255.0 );
rC = (sal_Int32) ( aHSL[ 2 ] * 255.0 );
}
else
bIsColor = sal_False;
return bIsColor;
}
void AnimationExporter::exportAnimateColor( SvStream& rStrm, const Reference< XAnimationNode >& xNode, int nAfterEffectType )
{
Reference< XAnimateColor > xColor( xNode, UNO_QUERY );
if ( xColor.is() )
{
EscherExContainer aAnimateColor( rStrm, DFF_msofbtAnimateColor );
{
EscherExAtom aAnimateColorData( rStrm, DFF_msofbtAnimateColorData );
sal_uInt32 nBits = 8;
sal_Int32 nByMode, nByA, nByB, nByC;
nByMode = nByA = nByB = nByC = 0;
sal_Int32 nFromMode, nFromA, nFromB, nFromC;
nFromMode = nFromA = nFromB = nFromC = 0;
sal_Int32 nToMode, nToA, nToB, nToC;
nToMode = nToA = nToB = nToC = 0;
sal_Int16 nColorSpace = xColor->getColorInterpolation();
Any aAny( xColor->getBy() );
if ( aAny.hasValue() )
{
if ( getColorAny( aAny, nColorSpace, nByMode, nByA, nByB, nByC ) )
nBits |= 0x11;
}
aAny = xColor->getFrom();
if ( aAny.hasValue() )
{
if ( getColorAny( aAny, nColorSpace, nFromMode, nFromA, nFromB, nFromC ) )
nBits |= 0x12;
}
aAny = xColor->getTo();
if ( aAny.hasValue() )
{
if ( getColorAny( aAny, nColorSpace, nToMode, nToA, nToB, nToC ) )
nBits |= 0x14;
}
rStrm << nBits
<< nByMode << nByA << nByB << nByC
<< nFromMode << nFromA << nFromB << nFromC
<< nToMode << nToA << nToB << nToC;
}
exportAnimateTarget( rStrm, xNode, 0, nAfterEffectType );
}
}
void AnimationExporter::exportIterate( SvStream& rStrm, const Reference< XAnimationNode >& xNode )
{
Reference< XIterateContainer > xIterate( xNode, UNO_QUERY );
if ( xIterate.is() )
{
EscherExAtom aAnimIteration( rStrm, DFF_msofbtAnimIteration );
float fInterval = 10.0;
sal_Int32 nTextUnitEffect = 0;
sal_Int32 nU1 = 1;
sal_Int32 nU2 = 1;
sal_Int32 nU3 = 0xe;
sal_Int16 nIterateType = xIterate->getIterateType();
switch( nIterateType )
{
case TextAnimationType::BY_WORD : nTextUnitEffect = 1; break;
case TextAnimationType::BY_LETTER : nTextUnitEffect = 2; break;
}
fInterval = (float)xIterate->getIterateInterval();
// convert interval from absolute to percentage
double fDuration = 0.0;
Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY );
if( xEnumerationAccess.is() )
{
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY );
if( xEnumeration.is() )
{
while( xEnumeration->hasMoreElements() )
{
Reference< XAnimate > xChildNode( xEnumeration->nextElement(), UNO_QUERY );
if( xChildNode.is() )
{
double fChildBegin = 0.0;
double fChildDuration = 0.0;
xChildNode->getBegin() >>= fChildBegin;
xChildNode->getDuration() >>= fChildDuration;
fChildDuration += fChildBegin;
if( fChildDuration > fDuration )
fDuration = fChildDuration;
}
}
}
}
if( fDuration )
fInterval = (float)(100.0 * fInterval / fDuration);
rStrm << fInterval << nTextUnitEffect << nU1 << nU2 << nU3;
aTarget = xIterate->getTarget();
}
}
} // namespace ppt;