diff options
Diffstat (limited to 'sd/source/filter/ppt/pptinanimations.cxx')
-rwxr-xr-x | sd/source/filter/ppt/pptinanimations.cxx | 3890 |
1 files changed, 3890 insertions, 0 deletions
diff --git a/sd/source/filter/ppt/pptinanimations.cxx b/sd/source/filter/ppt/pptinanimations.cxx new file mode 100755 index 000000000000..10b0b152b8f4 --- /dev/null +++ b/sd/source/filter/ppt/pptinanimations.cxx @@ -0,0 +1,3890 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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/animations/AnimationAdditiveMode.hpp> +#include <com/sun/star/animations/XIterateContainer.hpp> +#include <com/sun/star/animations/XAnimateSet.hpp> +#include <com/sun/star/animations/XAudio.hpp> +#include <com/sun/star/animations/XCommand.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/ValuePair.hpp> +#include <com/sun/star/animations/AnimationColorSpace.hpp> +#include <com/sun/star/presentation/ShapeAnimationSubType.hpp> +#include <com/sun/star/presentation/EffectCommands.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/presentation/TextAnimationType.hpp> +#include <comphelper/processfactory.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/math.hxx> + +#include <vcl/vclenum.hxx> +#include <svx/svdotext.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <pptinanimations.hxx> +#include <pptatom.hxx> +#include "pptin.hxx" +#include <algorithm> + +using ::std::map; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Any; +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::drawing; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +namespace sd +{ +extern Reference< XInterface > RandomAnimationNode_createInstance( sal_Int16 nPresetClass ); +} + +namespace ppt +{ + +const transition* transition::find( const OUString& rName ) +{ + const transition* p = gTransitions; + + while( p->mpName ) + { + if( rName.compareToAscii( p->mpName ) == 0 ) + return p; + + p++; + } + + return NULL; +} + +// ==================================================================== + + + +// ==================================================================== + +SvStream& operator>>(SvStream& rIn, AnimationNode& rNode ) +{ + rIn >> rNode.mnU1; + rIn >> rNode.mnRestart; + rIn >> rNode.mnGroupType; + rIn >> rNode.mnFill; + rIn >> rNode.mnU3; + rIn >> rNode.mnU4; + rIn >> rNode.mnDuration; + rIn >> rNode.mnNodeType; + + return rIn; +} + +// ==================================================================== + +static bool convertMeasure( OUString& rString ) +{ + bool bRet = false; + + const sal_Char* pSource[] = { "ppt_x", "ppt_y", "ppt_w", "ppt_h", NULL }; + const sal_Char* pDest[] = { "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(); + bRet = true; + } + ps++; + pd++; + } + + return bRet; +} + + +// ==================================================================== + +bool PropertySet::hasProperty( sal_Int32 nProperty ) const +{ + return maProperties.find( nProperty ) != maProperties.end(); +} + +// -------------------------------------------------------------------- + +Any PropertySet::getProperty( sal_Int32 nProperty ) const +{ + PropertySetMap_t::const_iterator aIter( maProperties.find( nProperty ) ); + if( aIter != maProperties.end() ) + return (*aIter).second; + else + return Any(); +} + +// ==================================================================== + +/** this adds an any to another any. + if rNewValue is empty, rOldValue is returned. + if rOldValue is empty, rNewValue is returned. + if rOldValue contains a value, a sequence with rOldValue and rNewValue is returned. + if rOldValue contains a sequence, a new sequence with the old sequence and rNewValue is returned. +*/ +static Any addToSequence( const Any& rOldValue, const Any& rNewValue ) +{ + if( !rNewValue.hasValue() ) + { + return rOldValue; + } + else if( !rOldValue.hasValue() ) + { + return rNewValue; + } + else + { + Sequence< Any > aNewSeq; + if( rOldValue >>= aNewSeq ) + { + sal_Int32 nSize = aNewSeq.getLength(); + aNewSeq.realloc(nSize+1); + aNewSeq[nSize] = rNewValue; + } + else + { + aNewSeq.realloc(2); + aNewSeq[0] = rOldValue; + aNewSeq[1] = rNewValue; + } + return makeAny( aNewSeq ); + } +} + +// ==================================================================== + +AnimationImporter::AnimationImporter( ImplSdPPTImport* pPPTImport, SvStream& rStCtrl ) +: mpPPTImport( pPPTImport ), mrStCtrl( rStCtrl ) +{ +} + +// -------------------------------------------------------------------- + +void AnimationImporter::import( const Reference< XDrawPage >& xPage, const DffRecordHeader& rProgTagContentHd ) +{ +#ifdef DBG_ANIM_LOG + mpFile = fopen( "c:\\output.xml", "w+" ); + //mpFile = stdout; +#endif + dump("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + + Reference< XAnimationNodeSupplier > xNodeSupplier( xPage, UNO_QUERY ); + if( xNodeSupplier.is() ) + { + mxRootNode = xNodeSupplier->getAnimationNode(); + if( mxRootNode.is() ) + { + Reference< XAnimationNode > xParent; + + const Atom* pAtom = Atom::import( rProgTagContentHd, mrStCtrl ); + if( pAtom ) + { + importAnimationContainer( pAtom, xParent ); + } + + processAfterEffectNodes(); + } + } + +#ifdef DBG_ANIM_LOG + fclose( mpFile ); +#endif +} + +// -------------------------------------------------------------------- + +void AnimationImporter::processAfterEffectNodes() +{ + std::for_each( maAfterEffectNodes.begin(), maAfterEffectNodes.end(), sd::stl_process_after_effect_node_func ); +} + +// -------------------------------------------------------------------- + +Reference< XAnimationNode > AnimationImporter::createNode( const Atom* pAtom, const AnimationNode& rNode ) +{ + const char* pServiceName = NULL; + + switch( rNode.mnGroupType ) + { + case mso_Anim_GroupType_PAR: + if( pAtom->hasChildAtom( DFF_msofbtAnimIteration ) ) + pServiceName = "com.sun.star.animations.IterateContainer"; + else + pServiceName = "com.sun.star.animations.ParallelTimeContainer"; + break; + case mso_Anim_GroupType_SEQ: + pServiceName = "com.sun.star.animations.SequenceTimeContainer"; + break; + case mso_Anim_GroupType_NODE: + { + switch( rNode.mnNodeType ) + { + case mso_Anim_Behaviour_FILTER: +/* + pServiceName = "com.sun.star.animations.TransitionFilter"; + break; +*/ + case mso_Anim_Behaviour_ANIMATION: + if( pAtom->hasChildAtom( DFF_msofbtAnimateSet ) ) + pServiceName = "com.sun.star.animations.AnimateSet"; + else if( pAtom->hasChildAtom( DFF_msofbtAnimateColor ) ) + pServiceName = "com.sun.star.animations.AnimateColor"; + else if( pAtom->hasChildAtom( DFF_msofbtAnimateScale ) ) + pServiceName = "com.sun.star.animations.AnimateTransform"; + else if( pAtom->hasChildAtom( DFF_msofbtAnimateRotation ) ) + pServiceName = "com.sun.star.animations.AnimateTransform"; + else if( pAtom->hasChildAtom( DFF_msofbtAnimateMotion ) ) + pServiceName = "com.sun.star.animations.AnimateMotion"; + else if( pAtom->hasChildAtom( DFF_msofbtAnimateFilter ) ) + pServiceName = "com.sun.star.animations.TransitionFilter"; + else if( pAtom->hasChildAtom( DFF_msofbtAnimCommand ) ) + pServiceName = "com.sun.star.animations.Command"; + else + pServiceName = "com.sun.star.animations.Animate"; + break; + } + break; + } + case mso_Anim_GroupType_MEDIA: + pServiceName = "com.sun.star.animations.Audio"; + break; + + default: + pServiceName = "com.sun.star.animations.Animate"; + break; + } + + Reference< XAnimationNode > xNode; + if( pServiceName ) + { + const OUString aServiceName( OUString::createFromAscii(pServiceName) ); + Reference< XInterface > xFac( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName) ); + xNode.set(xFac , UNO_QUERY ); + } + + DBG_ASSERT( xNode.is(), "sd::AnimationImporter::createNode(), node creation failed!" ); + return xNode; +} + +// -------------------------------------------------------------------- + +static bool is_random( const AnimationNode& rNode, const PropertySet& rSet, sal_Int32& rPresetClass ) +{ + if( rNode.mnGroupType != mso_Anim_GroupType_PAR ) + return false; + + if( !rSet.hasProperty( DFF_ANIM_PRESET_ID ) || !rSet.hasProperty( DFF_ANIM_PRESET_CLASS ) ) + return false; + + sal_Int32 nPresetId = 0; + if( !(rSet.getProperty( DFF_ANIM_PRESET_ID ) >>= nPresetId) || (nPresetId != 24) ) + return false; + + sal_Int32 nPresetClass = 0; + if( !(rSet.getProperty( DFF_ANIM_PRESET_CLASS ) >>= nPresetClass) ) + return false; + + switch( nPresetClass ) + { + case DFF_ANIM_PRESS_CLASS_ENTRANCE: rPresetClass = EffectPresetClass::ENTRANCE; return true; + case DFF_ANIM_PRESS_CLASS_EXIT: rPresetClass = EffectPresetClass::EXIT; return true; + } + return false; +} + + +void AnimationImporter::importAnimationContainer( const Atom* pAtom, const Reference< XAnimationNode >& xParent ) +{ + if( pAtom->seekToContent() ) + { + AnimationNode aNode; + const Atom* pAnimationNodeAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimNode ); + if( pAnimationNodeAtom && pAnimationNodeAtom->seekToContent() ) + mrStCtrl >> aNode; + + PropertySet aSet; + const Atom* pAnimationPropertySetAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimPropertySet ); + if( pAnimationPropertySetAtom ) + importPropertySetContainer( pAnimationPropertySetAtom, aSet ); + + Reference< XAnimationNode > xNode; + + if( xParent.is() ) + { + sal_Int32 nPresetClass; + if( is_random( aNode, aSet, nPresetClass ) ) + { + // create a random animation node with the given preset class + xNode.set( sd::RandomAnimationNode_createInstance( (sal_Int16)nPresetClass ), UNO_QUERY ); + } + + if( !xNode.is() ) + { + // create a node for the given atom + xNode = createNode( pAtom, aNode ); + } + } + else + { + // if we have no parent we fill the root node + xNode = mxRootNode; + } + + // import if we have a node and its not random + if( xNode.is() ) + { + fillNode( xNode, aNode, aSet ); + + switch( aNode.mnGroupType ) + { + case mso_Anim_GroupType_PAR: + { + dump( "<par" ); + dump( aNode ); + dump( aSet ); + importTimeContainer( pAtom, xNode ); + dump( "</par>\n" ); + + // for iteration containers, map target from childs to iteration + Reference< XIterateContainer > xIter( xNode, UNO_QUERY ); + if( xIter.is() ) + { + double fDuration = 0.0; + Any aTarget, aEmpty; + 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( !aTarget.hasValue() ) + aTarget = xChildNode->getTarget(); + + xChildNode->setTarget( aEmpty ); + } + } + } + } + + xIter->setTarget( aTarget ); + + double fIterateInterval = xIter->getIterateInterval() * fDuration / 100; + xIter->setIterateInterval( fIterateInterval ); + } + } + break; + + case mso_Anim_GroupType_SEQ: + { + dump( "<seq" ); + dump( aNode ); + dump( aSet ); + importTimeContainer( pAtom, xNode ); + dump( "</seq>\n" ); + + if( aSet.hasProperty( DFF_ANIM_NODE_TYPE ) ) + { + sal_Int32 nPPTNodeType = 0; + if( aSet.getProperty( DFF_ANIM_NODE_TYPE ) >>= nPPTNodeType ) + { + switch(nPPTNodeType) + { + case DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE: + fixMainSequenceTiming( xNode ); + break; + case DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ: + fixInteractiveSequenceTiming( xNode ); + break; + } + } + } + } + break; + + case mso_Anim_GroupType_NODE: + { +#ifdef DBG_ANIM_LOG + if( pAtom->hasChildAtom( DFF_msofbtAnimateSet ) ) + { + dump( "<set" ); + } + else if( pAtom->hasChildAtom( DFF_msofbtAnimateColor ) ) + { + dump( "<animateColor" ); + } + else if( pAtom->hasChildAtom( DFF_msofbtAnimateScale ) ) + { + dump( "<animateScale" ); + } + else if( pAtom->hasChildAtom( DFF_msofbtAnimateRotation ) ) + { + dump( "<animateRotation" ); + } + else if( pAtom->hasChildAtom( DFF_msofbtAnimateMotion ) ) + { + dump( "<animateMotion" ); + } + else if( pAtom->hasChildAtom( DFF_msofbtAnimate ) ) + { + dump( "<animate" ); + } + else if( pAtom->hasChildAtom( DFF_msofbtAnimateFilter ) ) + { + dump( "<animateFilter" ); + } + else if( pAtom->hasChildAtom( DFF_msofbtAnimCommand ) ) + { + dump( "<command" ); + } + else + { + DBG_ERROR( "unknown node atom!" ); + dump_atom_header( pAtom, true, false ); + dump_atom( pAtom ); + dump_atom_header( pAtom, false, false ); + break; + } + dump( aNode ); + dump( aSet ); +#endif + importAnimationNodeContainer( pAtom, xNode ); + if( !convertAnimationNode( xNode, xParent ) ) + xNode = 0; + dump( "/>\n"); + + } + break; + + case mso_Anim_GroupType_MEDIA: + { + dump( "<audio" ); + dump( aNode ); + dump( aSet ); + importAudioContainer( pAtom, xNode ); + dump( "</audio>\n" ); + } + break; + + default: + DBG_ERROR( "unknown group atom!" ); + + dump_atom_header( pAtom, true, false ); + dump_atom( pAtom ); + dump_atom_header( pAtom, false, false ); + break; + + } + } + + if( xParent.is() && xNode.is() ) + { + Reference< XTimeContainer > xParentContainer( xParent, UNO_QUERY ); + DBG_ASSERT( xParentContainer.is(), "parent is no container, then why do I have a child here?" ); + if( xParentContainer.is() ) + { + xParentContainer->appendChild( xNode ); + } + } + } +} + +// -------------------------------------------------------------------- +void AnimationImporter::fixMainSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +{ + try + { + bool bFirst = true; + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + + Event aEvent; + aEvent.Trigger = EventTrigger::ON_NEXT; + aEvent.Repeat = 0; + xClickNode->setBegin( makeAny( aEvent ) ); + + if( bFirst ) + { + bFirst = false; + Reference< XEnumerationAccess > xEA2( xClickNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE2( xEA2->createEnumeration(), UNO_QUERY_THROW ); + if( xE2->hasMoreElements() ) + { + // with node + xE2->nextElement() >>= xEA2; + if( xEA2.is() ) + xE2.query( xEA2->createEnumeration() ); + else + xE2.clear(); + + if( xE2.is() && xE2->hasMoreElements() ) + { + Reference< XAnimationNode > xEffectNode( xE2->nextElement(), UNO_QUERY_THROW ); + const Sequence< NamedValue > aUserData( xEffectNode->getUserData() ); + const NamedValue* p = aUserData.getConstArray(); + sal_Int32 nLength = aUserData.getLength(); + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) ) + { + sal_Int16 nNodeType = 0; + p->Value >>= nNodeType; + if( nNodeType != ::com::sun::star::presentation::EffectNodeType::ON_CLICK ) + { + // first effect does not start on click, so correct + // first click nodes begin to 0s + xClickNode->setBegin( makeAny( (double)0.0 ) ); + break; + } + } + p++; + } + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::AnimationImporter::fixMainSequenceTiming(), exception caught!" ); + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::fixInteractiveSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +{ + try + { + Any aBegin( xNode->getBegin() ); + Any aEmpty; + xNode->setBegin( aEmpty ); + + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + xClickNode->setBegin( aBegin ); + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::AnimationImporter::fixInteractiveSequenceTiming(), exception caught!" ); + } +} + +// -------------------------------------------------------------------- + +bool AnimationImporter::convertAnimationNode( const Reference< XAnimationNode >& xNode, const Reference< XAnimationNode >& xParent ) +{ + Reference< XAnimate > xAnimate( xNode, UNO_QUERY ); + if( !xAnimate.is() ) + return true; + + if( !xAnimate->getTarget().hasValue() ) + return false; + + const sal_Int16 nNodeType = xNode->getType(); + + if( nNodeType == AnimationNodeType::TRANSITIONFILTER ) + return true; + + OUString aAttributeName( xAnimate->getAttributeName() ); + + if( (nNodeType == AnimationNodeType::SET) && aAttributeName.equalsAscii( "fill.on" ) ) + return false; + + const ImplAttributeNameConversion* p = gImplConversionList; + + MS_AttributeNames eAttribute = MS_UNKNOWN; + + if( (nNodeType == AnimationNodeType::ANIMATEMOTION) || + (nNodeType == AnimationNodeType::ANIMATETRANSFORM) ) + { + OUString aEmpty; + aAttributeName = aEmpty; + } + else + { + while( p->mpMSName ) + { + if( aAttributeName.compareToAscii( p->mpMSName ) == 0 ) + break; + + p++; + } + + DBG_ASSERT( p->mpMSName || (aAttributeName.getLength() == 0), "sd::AnimationImporter::convertAnimationNode(), unknown attribute!" ); +#ifdef DBG_ANIM_LOG + if( p->mpMSName == 0 ) dump( "<error text=\"sd::AnimationImporter::convertAnimationNode(), unknown attribute!\"/>\n" ); +#endif + + eAttribute = p->meAttribute; + + if( p->mpAPIName ) + aAttributeName = OUString::createFromAscii( p->mpAPIName ); + } + + xAnimate->setAttributeName( aAttributeName ); + + if( eAttribute != MS_UNKNOWN ) + { + Any aAny( xAnimate->getFrom() ); + if( aAny.hasValue() ) + { + if( convertAnimationValue( eAttribute, aAny ) ) + xAnimate->setFrom( aAny ); + } + + aAny = xAnimate->getBy(); + if( aAny.hasValue() ) + { + if( convertAnimationValue( eAttribute, aAny ) ) + xAnimate->setBy( aAny ); + } + + aAny = xAnimate->getTo(); + if( aAny.hasValue() ) + { + if( convertAnimationValue( eAttribute, aAny ) ) + xAnimate->setTo( aAny ); + } + + Sequence< Any > aValues( xAnimate->getValues() ); + sal_Int32 nValues = aValues.getLength(); + if( nValues ) + { + Any* p2 = aValues.getArray(); + while( nValues-- ) + convertAnimationValue( eAttribute, *p2++ ); + + xAnimate->setValues( aValues ); + } + + OUString aFormula( xAnimate->getFormula() ); + if( aFormula.getLength() ) + { + if( convertMeasure( aFormula ) ) + xAnimate->setFormula( aFormula ); + } + } + + // check for after-affect + Sequence< NamedValue > aUserData( xNode->getUserData() ); + NamedValue* pValue = aUserData.getArray(); + NamedValue* pLastValue = pValue; + sal_Int32 nLength = aUserData.getLength(), nRemoved = 0; + + sal_Bool bAfterEffect = false; + sal_Int32 nMasterRel = 0; + for( ; nLength--; pValue++ ) + { + if( pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("after-effect") ) ) + { + pValue->Value >>= bAfterEffect; + nRemoved++; + } + else if( pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("master-rel") ) ) + { + pValue->Value >>= nMasterRel; + nRemoved++; + } + else + { + if( nRemoved ) + *pLastValue = *pValue; + pLastValue++; + } + } + + if( nRemoved ) + { + aUserData.realloc( aUserData.getLength() - nRemoved ); + xNode->setUserData( aUserData ); + } + + // if its an after effect node, add it to the list for + // later processing + // after effect nodes are not inserted at their import + // position, so return false in this case + if( bAfterEffect ) + { + if( nMasterRel != 2 ) + { + Event aEvent; + + aEvent.Source <<= xParent; + aEvent.Trigger = EventTrigger::END_EVENT; + aEvent.Repeat = 0; + + xNode->setBegin( makeAny( aEvent ) ); + } + + // add to after effect nodes for later processing + sd::AfterEffectNode aNode( xNode, xParent, nMasterRel == 2 ); + maAfterEffectNodes.push_back( aNode ); + return false; + } + + return true; +} + +static int lcl_gethex( int nChar ) +{ + if( nChar >= '0' && nChar <= '9' ) + return nChar - '0'; + else if( nChar >= 'a' && nChar <= 'f' ) + return nChar - 'a' + 10; + else if( nChar >= 'A' && nChar <= 'F' ) + return nChar - 'A' + 10; + else + return 0; +} + +bool AnimationImporter::convertAnimationValue( MS_AttributeNames eAttribute, Any& rValue ) +{ + bool bRet = false; + switch( eAttribute ) + { + case MS_PPT_X: + case MS_PPT_Y: + case MS_PPT_W: + case MS_PPT_H: + { + OUString aString; + + if( rValue.getValueType() == ::getCppuType((const ValuePair*)0) ) + { + ValuePair aValuePair; + if( rValue >>= aValuePair ) + { + if( aValuePair.First >>= aString ) + { + if( convertMeasure( aString ) ) + { + aValuePair.First <<= aString; + bRet = true; + } + } + + if( aValuePair.Second >>= aString ) + { + if( convertMeasure( aString ) ) + { + aValuePair.Second <<= aString; + bRet = true; + } + } + } + } + else if( rValue.getValueType() == ::getCppuType((const OUString*)0) ) + { + if( rValue >>= aString ) + { + bRet = convertMeasure( aString ); + + if( bRet ) + rValue <<= aString; + } + } + } + break; + + case MS_XSHEAR: + case MS_R: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= aString.toDouble(); + bRet = true; + } + } + break; + + case MS_STYLEROTATION: + { + if( rValue.getValueType() == ::getCppuType((const OUString*)0) ) + { + OUString aString; + rValue >>= aString; + rValue <<= (sal_Int16)aString.toDouble(); + bRet = true; + } + else if( rValue.getValueType() == ::getCppuType((const double*)0) ) + { + double fValue = 0.0; + rValue >>= fValue; + rValue <<= (sal_Int16)fValue; + bRet = true; + } + } + break; + + case MS_FILLCOLOR: + case MS_STROKECOLOR: + case MS_STYLECOLOR: + case MS_PPT_C: + { + OUString aString; + if( rValue >>= aString ) + { + if( aString.getLength() >= 7 && aString[0] == '#' ) + { + Color aColor; + aColor.SetRed( (UINT8)(lcl_gethex( aString[1] ) * 16 + lcl_gethex( aString[2] )) ); + aColor.SetGreen( (UINT8)(lcl_gethex( aString[3] ) * 16 + lcl_gethex( aString[4] )) ); + aColor.SetBlue( (UINT8)(lcl_gethex( aString[5] ) * 16 + lcl_gethex( aString[6] )) ); + rValue <<= (sal_Int32)aColor.GetColor(); + bRet = true; + } + else if( aString.matchAsciiL( "rgb(", 4, 0 ) ) + { + aString = aString.copy( 4, aString.getLength() - 5 ); + Color aColor; + sal_Int32 index = 0; + aColor.SetRed( (UINT8)aString.getToken( 0, (sal_Unicode)',', index ).toInt32() ); + aColor.SetGreen( (UINT8)aString.getToken( 0, (sal_Unicode)',', index ).toInt32() ); + aColor.SetRed( (UINT8)aString.getToken( 0, (sal_Unicode)',', index ).toInt32() ); + rValue <<= (sal_Int32)aColor.GetColor(); + bRet = true; + } + else if( aString.matchAsciiL( "hsl(", 4, 0 ) ) + { + sal_Int32 index = 0; + sal_Int32 nA = aString.getToken( 0, (sal_Unicode)',', index ).toInt32(); + sal_Int32 nB = aString.getToken( 0, (sal_Unicode)',', index ).toInt32(); + sal_Int32 nC = aString.getToken( 0, (sal_Unicode)',', index ).toInt32(); + dump( "hsl(%ld", nA ); + dump( ",%ld", nB ); + dump( ",%ld)", nC ); + Sequence< double > aHSL( 3 ); + aHSL[0] = nA * 360.0/255.0; + aHSL[1] = nB / 255.0; + aHSL[2] = nC / 255.0; + rValue <<= aHSL; + bRet = true; + } + } + } + break; + + case MS_FILLTYPE: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= aString.equalsAscii( "solid" ) ? FillStyle_SOLID : FillStyle_NONE; + bRet = true; + } + } + break; + + case MS_STROKEON: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= aString.equalsAscii( "true" ) ? ::com::sun::star::drawing::LineStyle_SOLID : ::com::sun::star::drawing::LineStyle_NONE; + bRet = true; + } + } + break; + + case MS_FONTWEIGHT: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= aString.equalsAscii( "bold" ) ? com::sun::star::awt::FontWeight::BOLD : com::sun::star::awt::FontWeight::NORMAL; + bRet = true; + } + } + break; + + case MS_STYLEFONTSTYLE: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= aString.equalsAscii( "italic" ) ? com::sun::star::awt::FontSlant_ITALIC : com::sun::star::awt::FontSlant_NONE; + bRet = true; + } + } + break; + + case MS_STYLEUNDERLINE: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= aString.equalsAscii( "true" ) ? com::sun::star::awt::FontUnderline::SINGLE : com::sun::star::awt::FontUnderline::NONE; + bRet = true; + } + } + break; + + case MS_STYLEOPACITY: + case MS_STYLEFONTSIZE: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= (float)aString.toDouble(); + bRet = true; + } + } + break; + + case MS_STYLEVISIBILITY: + { + OUString aString; + if( rValue >>= aString ) + { + rValue <<= aString.equalsAscii( "visible" ) ? sal_True : sal_False; + bRet = true; + } + } + break; + default: + break; + } + + return bRet; +} + +// -------------------------------------------------------------------- + +static OUString getConvertedSubType( sal_Int16 nPresetClass, sal_Int32 nPresetId, sal_Int32 nPresetSubType ) +{ + const sal_Char* pStr = 0; + + if( (nPresetClass == EffectPresetClass::ENTRANCE) || (nPresetClass == EffectPresetClass::EXIT) ) + { + // skip wheel effect + if( nPresetId != 21 ) + { + if( nPresetId == 5 ) + { + // checkerboard + switch( nPresetSubType ) + { + case 5: pStr = "downward"; break; + case 10: pStr = "across"; break; + } + } + else if( nPresetId == 17 ) + { + // stretch + if( nPresetSubType == 10 ) + pStr = "across"; + } + else if( nPresetId == 18 ) + { + // strips + switch( nPresetSubType ) + { + case 3: pStr = "right-to-top"; break; + case 6: pStr = "right-to-bottom"; break; + case 9: pStr = "left-to-top"; break; + case 12: pStr = "left-to-bottom"; break; + } + } + + if( pStr == 0 ) + { + const convert_subtype* p = gConvertArray; + + while( p->mpStrSubType ) + { + if( p->mnID == nPresetSubType ) + { + pStr = p->mpStrSubType; + break; + } + p++; + } + } + } + } + + if( pStr ) + return OUString::createFromAscii( pStr ); + else + return OUString::valueOf( nPresetSubType ); +} + +// -------------------------------------------------------------------- + +void AnimationImporter::fillNode( Reference< XAnimationNode >& xNode, const AnimationNode& rNode, const PropertySet& rSet ) +{ + sal_Bool bAfterEffect = false; + + // attribute Restart + if( rNode.mnRestart ) + { + sal_Int16 nRestart = AnimationRestart::DEFAULT; + switch( rNode.mnRestart ) + { + case 1: nRestart = AnimationRestart::ALWAYS; break; + case 2: nRestart = AnimationRestart::WHEN_NOT_ACTIVE; break; + case 3: nRestart = AnimationRestart::NEVER; break; + } + xNode->setRestart( nRestart ); + } + + // attribute Fill + if( rNode.mnFill ) + { + sal_Int16 nFill = AnimationFill::DEFAULT; + switch( rNode.mnFill ) + { + case 1: nFill = AnimationFill::REMOVE; break; + case 2: nFill = AnimationFill::FREEZE; break; + case 3: nFill = AnimationFill::HOLD; break; + case 4: nFill = AnimationFill::TRANSITION; break; + } + xNode->setFill( nFill ); + } + + // attribute Duration + if( rNode.mnDuration ) + { + Any aDuration; + if( rNode.mnDuration > 0 ) + { + aDuration <<= (double)(rNode.mnDuration / 1000.0); + } + else if( rNode.mnDuration < 0 ) + { + aDuration <<= Timing_INDEFINITE; + } + xNode->setDuration( aDuration ); + } + + // TODO: DFF_ANIM_PATH_EDIT_MODE + if( rSet.hasProperty( DFF_ANIM_PATH_EDIT_MODE ) ) + { + sal_Int32 nPathEditMode ; + if( rSet.getProperty( DFF_ANIM_PATH_EDIT_MODE ) >>= nPathEditMode ) + { + } + } + + // set user data + Sequence< NamedValue > aUserData; + + // attribute Type + if( rSet.hasProperty( DFF_ANIM_NODE_TYPE ) ) + { + sal_Int32 nPPTNodeType = 0; + if( rSet.getProperty( DFF_ANIM_NODE_TYPE ) >>= nPPTNodeType ) + { + sal_Int16 nNodeType = ::com::sun::star::presentation::EffectNodeType::DEFAULT; + switch( nPPTNodeType ) + { + case DFF_ANIM_NODE_TYPE_ON_CLICK: nNodeType = ::com::sun::star::presentation::EffectNodeType::ON_CLICK; break; + case DFF_ANIM_NODE_TYPE_WITH_PREVIOUS: nNodeType = ::com::sun::star::presentation::EffectNodeType::WITH_PREVIOUS; break; + case DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS: nNodeType = ::com::sun::star::presentation::EffectNodeType::AFTER_PREVIOUS; break; + case DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE: nNodeType = ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE; break; + case DFF_ANIM_NODE_TYPE_TIMING_ROOT: nNodeType = ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT; break; + case DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ:nNodeType = ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE; break; + } + + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); + aUserData[nSize].Value <<= nNodeType; + } + } + + if( rSet.hasProperty( DFF_ANIM_GROUP_ID ) ) + { + sal_Int32 nGroupId; + if( rSet.getProperty( DFF_ANIM_GROUP_ID ) >>= nGroupId ) + { + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "group-id" ) ); + aUserData[nSize].Value <<= nGroupId; + } + } + + sal_Int16 nEffectPresetClass = EffectPresetClass::CUSTOM; + sal_Int32 nPresetId = 0; + + if( rSet.hasProperty( DFF_ANIM_PRESET_CLASS ) ) + { + sal_Int32 nPresetClass = 0; + if ( rSet.getProperty( DFF_ANIM_PRESET_CLASS ) >>= nPresetClass ) + { + switch( nPresetClass ) + { + case DFF_ANIM_PRESS_CLASS_ENTRANCE: nEffectPresetClass = EffectPresetClass::ENTRANCE; break; + case DFF_ANIM_PRESS_CLASS_EXIT: nEffectPresetClass = EffectPresetClass::EXIT; break; + case DFF_ANIM_PRESS_CLASS_EMPHASIS: nEffectPresetClass = EffectPresetClass::EMPHASIS; break; + case DFF_ANIM_PRESS_CLASS_MOTIONPATH: nEffectPresetClass = EffectPresetClass::MOTIONPATH; break; + case DFF_ANIM_PRESS_CLASS_OLE_ACTION: nEffectPresetClass = EffectPresetClass::OLEACTION; break; + case DFF_ANIM_PRESS_CLASS_MEDIACALL: nEffectPresetClass = EffectPresetClass::MEDIACALL; break; + } + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "preset-class" ) ); + aUserData[nSize].Value <<= nEffectPresetClass; + } + } + + if( rSet.hasProperty( DFF_ANIM_PRESET_ID ) ) + { + if( rSet.getProperty( DFF_ANIM_PRESET_ID ) >>= nPresetId ) + { + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "preset-id" ) ); + + const preset_maping* p = gPresetMaping; + while( p->mpStrPresetId && ((p->mnPresetClass != nEffectPresetClass) || (p->mnPresetId != nPresetId )) ) + p++; + + if( p->mpStrPresetId ) + { + aUserData[nSize].Value <<= OUString::createFromAscii( p->mpStrPresetId ); + } + else + { + OUStringBuffer sBuffer; + sBuffer.appendAscii( "ppt_" ); + switch( nEffectPresetClass ) + { + case EffectPresetClass::ENTRANCE: sBuffer.appendAscii( "entrance_" ); break; + case EffectPresetClass::EXIT: sBuffer.appendAscii( "exit_" ); break; + case EffectPresetClass::EMPHASIS: sBuffer.appendAscii( "emphasis_" ); break; + case EffectPresetClass::MOTIONPATH: sBuffer.appendAscii( "motionpath_" ); break; + case EffectPresetClass::OLEACTION: sBuffer.appendAscii( "oleaction_" ); break; + case EffectPresetClass::MEDIACALL: sBuffer.appendAscii( "mediacall_" ); break; + } + sBuffer.append( nPresetId ); + + aUserData[nSize].Value <<= sBuffer.makeStringAndClear(); + } + } + } + + if( rSet.hasProperty( DFF_ANIM_PRESET_SUB_TYPE ) ) + { + sal_Int32 nPresetSubType = 0; + if( (rSet.getProperty( DFF_ANIM_PRESET_SUB_TYPE ) >>= nPresetSubType) ) + { + if( nPresetSubType ) + { + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "preset-sub-type" ) ); + aUserData[nSize].Value <<= getConvertedSubType( nEffectPresetClass, nPresetId, nPresetSubType ); + } + } + } + + if( rSet.hasProperty( DFF_ANIM_AFTEREFFECT ) ) + { + if( rSet.getProperty( DFF_ANIM_AFTEREFFECT ) >>= bAfterEffect ) + { + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "after-effect" ) ); + aUserData[nSize].Value <<= bAfterEffect; + } + } + + if( bAfterEffect && rSet.hasProperty( DFF_ANIM_MASTERREL ) ) + { + sal_Int32 nMasterRel = 2; + if( rSet.getProperty( DFF_ANIM_MASTERREL ) >>= nMasterRel ) + { + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "master-rel" ) ); + aUserData[nSize].Value <<= nMasterRel; + } + } + + xNode->setUserData( aUserData ); + + // TODO: DFF_ANIM_ID + if( rSet.hasProperty( DFF_ANIM_ID ) ) + { + rtl::OUString aString; + rSet.getProperty( DFF_ANIM_ID ) >>= aString; + if( aString.getLength() ) + { + } + } + + // TODO: DFF_ANIM_EVENT_FILTER + if( rSet.hasProperty( DFF_ANIM_EVENT_FILTER ) ) + { + rtl::OUString aString; + rSet.getProperty( DFF_ANIM_EVENT_FILTER ) >>= aString; + if( aString.getLength() ) + { + } + } + + // DFF_ANIM_TIMEFILTER + if( rSet.hasProperty( DFF_ANIM_TIMEFILTER ) ) + { + Reference< XAnimate > xAnim( xNode, UNO_QUERY ); + if( xAnim.is() ) + { + rtl::OUString aString; + rSet.getProperty( DFF_ANIM_TIMEFILTER ) >>= aString; + if( aString.getLength() ) + { + sal_Int32 nElements = 1; // a non empty string has at least one value + + sal_Int32 fromIndex = 0; + while(true) + { + fromIndex = aString.indexOf( (sal_Unicode)';', fromIndex ); + if( fromIndex == -1 ) + break; + + fromIndex++; + nElements++; + } + + Sequence< TimeFilterPair > aTimeFilter( nElements ); + + TimeFilterPair* pValues = aTimeFilter.getArray(); + sal_Int32 nIndex = 0; + while( (nElements--) && (nIndex >= 0) ) + { + const OUString aToken( aString.getToken( 0, ';', nIndex ) ); + + sal_Int32 nPos = aToken.indexOf( ',' ); + if( nPos >= 0 ) + { + pValues->Time = aToken.copy( 0, nPos ).toDouble(); + pValues->Progress = aToken.copy( nPos+1, aToken.getLength() - nPos - 1 ).toDouble(); + } + pValues++; + } + + xAnim->setTimeFilter( aTimeFilter ); + } + } + } + +/* todo + Reference< XAudio > xAudio( xNode, UNO_QUERY ); + if( xAudio.is() ) + { + if( rSet.hasProperty( DFF_ANIM_ENDAFTERSLIDE ) ) + { + sal_Int16 nEndAfterSlide = 0; + if( rSet.getProperty( DFF_ANIM_ENDAFTERSLIDE ) >>= nEndAfterSlide ) + xAudio->setEndAfterSlide( nEndAfterSlide ); + } + + if( rSet.hasProperty( DFF_ANIM_VOLUME ) ) + { + double fVolume = 1.0; + rSet.getProperty( DFF_ANIM_VOLUME ) >>= fVolume; + xAudio->setVolume( fVolume ); + } + } +*/ + Reference< XAnimateColor > xColor( xNode, UNO_QUERY ); + if( xColor.is() ) + { + if( rSet.hasProperty( DFF_ANIM_DIRECTION ) ) + { + sal_Bool bDirection = sal_False; + if( rSet.getProperty( DFF_ANIM_DIRECTION ) >>= bDirection ) + xColor->setDirection( (sal_Bool)!bDirection ); + } + + if( rSet.hasProperty( DFF_ANIM_COLORSPACE ) ) + { + sal_Int32 nColorSpace = 0; + rSet.getProperty( DFF_ANIM_COLORSPACE ) >>= nColorSpace; + xColor->setColorInterpolation( (nColorSpace == 0) ? AnimationColorSpace::RGB : AnimationColorSpace::HSL ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importTimeContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( pAtom && xNode.is(), "invalid call to ppt::AnimationImporter::importTimeContainer()!"); + if( pAtom && xNode.is() ) + { + importAnimationEvents( pAtom, xNode ); + importAnimationValues( pAtom, xNode ); + importAnimationActions( pAtom, xNode ); + + dump(">\n"); + + // import sub containers + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimNode: + case DFF_msofbtAnimEvent: + case DFF_msofbtAnimValue: + case DFF_msofbtAnimAction: + case DFF_msofbtAnimPropertySet: + break; + + case DFF_msofbtAnimSubGoup : + { + if( pChildAtom->hasChildAtom( DFF_msofbtAnimCommand ) ) + { + const OUString aServiceName( OUString::createFromAscii("com.sun.star.animations.Command") ); + Reference< XAnimationNode > xChildNode( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName), UNO_QUERY ); + importAnimationNodeContainer( pChildAtom, xChildNode ); + Reference< XTimeContainer > xParentContainer( xNode, UNO_QUERY ); + if( xParentContainer.is() && xChildNode.is() ) + xParentContainer->appendChild( xChildNode ); + } + else + { + importAnimationContainer( pChildAtom, xNode ); + } + } + break; + case DFF_msofbtAnimGroup : + { + importAnimationContainer( pChildAtom, xNode ); + } + break; + case DFF_msofbtAnimIteration: + { + if( pChildAtom->seekToContent() ) + { + float fInterval; + sal_Int32 nTextUnitEffect, nU1, nU2, nU3; + + mrStCtrl >> fInterval >> nTextUnitEffect >> nU1 >> nU2 >> nU3; + + Reference< XIterateContainer > xIter( xNode, UNO_QUERY ); + if( xIter.is() ) + { + sal_Int16 nIterateType = TextAnimationType::BY_PARAGRAPH; + switch( nTextUnitEffect ) + { + case 1: nIterateType = TextAnimationType::BY_WORD; break; + case 2: nIterateType = TextAnimationType::BY_LETTER; break; + } + xIter->setIterateType( nIterateType ); + xIter->setIterateInterval( (double)fInterval ); + } + + dump( "<iterate" ); + dump( " iterateType=\"%s\"", (nTextUnitEffect == 0) ? "byElement" : (nTextUnitEffect == 1) ? "byWord" : "byLetter" ); + dump( " iterateInterval=\"%g\"", fInterval ); + dump( " u1=\"%ld\"", nU1 ); + dump( " u2=\"%ld\"", nU2 ); + dump( " u3=\"%ld\"/>\n", nU3 ); + } + } + break; + + case 0xf136: + { +#ifdef DBG_ANIM_LOG + sal_uInt32 nU1, nU2; + mrStCtrl >> nU1 >> nU2; + + fprintf( mpFile, "<unknown_0xf136 nU1=\"%ld\" nU2=\"%ld\"/>\n", nU1, nU2 ); +#endif + } + break; + + default: + { + dump_atom_header( pChildAtom, true, false ); + dump_atom( pChildAtom ); + dump_atom_header( pChildAtom, false, false ); + } + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimationNodeContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( pAtom && xNode.is(), "invalid call to ppt::AnimationImporter::importAnimationNodeContainer()!"); + if( pAtom && xNode.is() ) + { + importAnimationEvents( pAtom, xNode ); + importAnimationValues( pAtom, xNode ); + importAnimationActions( pAtom, xNode ); + + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimNode: + case DFF_msofbtAnimEvent: + case DFF_msofbtAnimValue: + case DFF_msofbtAnimAction: + case DFF_msofbtAnimPropertySet: + break; + + case DFF_msofbtAnimateFilter: + importAnimateFilterContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimateSet: + importAnimateSetContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimate: + importAnimateContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimateScale: + importAnimateScaleContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimateColor: + importAnimateColorContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimateRotation: + importAnimateRotationContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimateMotion: + importAnimateMotionContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimCommand: + importCommandContainer( pChildAtom, xNode ); + break; + + default: + { + dump_atom_header( pChildAtom, true, false ); + dump_atom( pChildAtom ); + dump_atom_header( pChildAtom, false, false ); + } + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateFilterContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateFilter && xFilter.is(), "invalid call to ppt::AnimationImporter::importAnimateFilterContainer()!"); + if( pAtom && xFilter.is() ) + { + sal_uInt32 nBits = 0; + + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimateFilterData: + { + sal_uInt32 transition; + mrStCtrl >> nBits; + mrStCtrl >> transition; + + if( nBits & 1 ) + xFilter->setMode( transition == 0 ); + + dump( " transition=\"%s\"", (transition == 0) ? "in" : "out" ); + } + break; + + case DFF_msofbtAnimAttributeValue: + { + if( (nBits & 2 ) && ( pChildAtom->getInstance() == 1 ) ) + { + Any aAny; + if ( importAttributeValue( pChildAtom, aAny ) ) + { + rtl::OUString filter; + aAny >>= filter; + + dump( " filter=\"%s\"", filter ); + + const transition* pTransition = transition::find( filter ); + if( pTransition ) + { + xFilter->setTransition( pTransition->mnType ); + xFilter->setSubtype( pTransition->mnSubType ); + xFilter->setDirection( pTransition->mbDirection ); + } + else + { + DBG_ERROR( "unknown transition!" ); + } + } + } + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateAttributeTargetContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateTarget, "invalid call to ppt::AnimationImporter::importAnimateAttributeTargetContainer()!"); + + Any aTarget; + + Reference< XAnimate > xAnimate( xNode, UNO_QUERY ); + + bool bWrongContext = false; + + if( pAtom ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimPropertySet: + { + PropertySet aSet; + importPropertySetContainer( pChildAtom, aSet ); + if( aSet.hasProperty( DFF_ANIM_RUNTIMECONTEXT ) ) + { + OUString aContext; + if( aSet.getProperty( DFF_ANIM_RUNTIMECONTEXT ) >>= aContext ) + { + if( !aContext.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("PPT") ) ) + bWrongContext = true; + } + } + + dump( aSet ); + } + break; + + case DFF_msofbtAnimateTargetSettings: + { + if( xAnimate.is() ) + { + sal_uInt32 nBits; + sal_uInt32 nAdditive; + sal_uInt32 nAccumulate; + sal_uInt32 nTransformType; + + mrStCtrl >> nBits >> nAdditive >> nAccumulate >> nTransformType; + + // 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" + + if( nBits & 3 ) + { + if( xAnimate.is() ) + { + if( nBits & 1 ) + { + sal_Int16 nTemp = AnimationAdditiveMode::BASE; + switch( nAdditive ) + { + case 1: nTemp = AnimationAdditiveMode::SUM; break; + case 2: nTemp = AnimationAdditiveMode::REPLACE; break; + case 3: nTemp = AnimationAdditiveMode::MULTIPLY; break; + case 4: nTemp = AnimationAdditiveMode::NONE; break; + } + xAnimate->setAdditive( nTemp ); + } + + if( nBits & 2 ) + { + xAnimate->setAccumulate( (nAccumulate == 0) ? sal_True : sal_False ); + } + } + } +#ifdef DBG_ANIM_LOG + if( nBits & 1 ) + fprintf( mpFile, " additive=\"%s\"", (nAdditive == 0) ? "base" : (nAdditive == 2) ? "replace" : (nAdditive == 1) ? "sum" : (nAdditive == 3 ) ? "multiply" : (nAdditive == 4) ? "none" : "unknown" ); + + if( nBits & 2 ) + fprintf( mpFile, " accumulate=\"%s\"", (nAccumulate == 0) ? "none" : "always" ); + + if( nBits & 8 ) + fprintf( mpFile, " transformType=\"%s\"", (nTransformType == 0) ? "property" : "image" ); +#endif + } + } + break; + + case DFF_msofbtAnimateAttributeNames: + { + if( xAnimate.is() ) + { + OUString aAttributeName; + importAttributeNamesContainer( pChildAtom, aAttributeName ); + if( xAnimate.is() ) + xAnimate->setAttributeName( aAttributeName ); + dump( " attributeName=\"%s\"", aAttributeName ); + } + } + break; + + case DFF_msofbtAnimateTargetElement: + { + sal_Int16 nSubType; + importTargetElementContainer( pChildAtom, aTarget, nSubType ); + if( xAnimate.is() ) + xAnimate->setSubItem( nSubType ); + + dump( " target=\"" ); + dump_target( aTarget ); + dump( "\"" ); + } + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } + + if( bWrongContext ) + aTarget.clear(); + + if( xAnimate.is() ) + xAnimate->setTarget( aTarget ); + else + { + Reference< XCommand > xCommand( xNode, UNO_QUERY ); + if( xCommand.is() ) + xCommand->setTarget( aTarget ); + } +} + +// -------------------------------------------------------------------- + +sal_Int16 AnimationImporter::implGetColorSpace( sal_Int32 nMode, sal_Int32 /*nA*/, sal_Int32 /*nB*/, sal_Int32 /*nC*/ ) +{ + switch( nMode ) + { + case 2: // index + // FALLTHROUGH intended + default: + // FALLTHROUGH intended + case 0: // rgb + return AnimationColorSpace::RGB; + + case 1: // hsl + return AnimationColorSpace::HSL; + } +} + +// -------------------------------------------------------------------- + +Any AnimationImporter::implGetColorAny( sal_Int32 nMode, sal_Int32 nA, sal_Int32 nB, sal_Int32 nC ) +{ + switch( nMode ) + { + case 0: // rgb + { + dump( "rgb(%ld", nA ); + dump( ",%ld", nB ); + dump( ",%ld)", nC ); + Color aColor( (UINT8)nA, (UINT8)nB, (UINT8)nC ); + return makeAny( (sal_Int32)aColor.GetRGBColor() ); + } + case 1: // hsl + { + dump( "hsl(%ld", nA ); + dump( ",%ld", nB ); + dump( ",%ld)", nC ); + Sequence< double > aHSL( 3 ); + aHSL[0] = nA * 360.0/255.0; + aHSL[1] = nB / 255.0; + aHSL[2] = nC / 255.0; + return makeAny( aHSL ); + } + + case 2: // index + { + Color aColor; + mpPPTImport->GetColorFromPalette((USHORT)nA, aColor ); + dump( "index(%ld", nA ); + dump( " [%ld", (sal_Int32)aColor.GetRed() ); + dump( ",%ld", (sal_Int32)aColor.GetGreen() ); + dump( ",%ld])", (sal_Int32)aColor.GetBlue() ); + return makeAny( (sal_Int32)aColor.GetRGBColor() ); + } + + default: + { + dump( "unknown_%ld(", nMode ); + dump( "%ld", nA ); + dump( ",%ld", nB ); + dump( ",%ld)", nC ); + DBG_ERROR( "ppt::implGetColorAny(), unhandled color type" ); + + Any aAny; + return aAny; + } + } +} + +void AnimationImporter::importAnimateColorContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAnimateColor > xColor( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateColor && xColor.is(), "invalid call to ppt::AnimationImporter::importAnimateColorContainer()!"); + if( pAtom && xColor.is() ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimateColorData: + { + sal_uInt32 nBits; + sal_Int32 nByMode, nByA, nByB, nByC; + sal_Int32 nFromMode, nFromA, nFromB, nFromC; + sal_Int32 nToMode, nToA, nToB, nToC; + mrStCtrl >> nBits; + mrStCtrl >> nByMode >> nByA >> nByB >> nByC; + mrStCtrl >> nFromMode >> nFromA >> nFromB >> nFromC; + mrStCtrl >> nToMode >> nToA >> nToB >> nToC; + + if( nBits & 1 ) + { + dump( " by=\"" ); + xColor->setBy( implGetColorAny( nByMode, nByA, nByB, nByC ) ); + xColor->setColorInterpolation( implGetColorSpace( nByMode, nByA, nByB, nByC ) ); + dump( "\""); + } + + if( nBits & 2 ) + { + dump( " from=\"" ); + xColor->setFrom( implGetColorAny( nFromMode, nFromA, nFromB, nFromC ) ); + xColor->setColorInterpolation( implGetColorSpace( nFromMode, nFromA, nFromB, nFromC ) ); + dump( "\""); + } + + if( nBits & 4 ) + { + dump( " to=\"" ); + xColor->setTo( implGetColorAny( nToMode, nToA, nToB, nToC ) ); + xColor->setColorInterpolation( implGetColorSpace( nToMode, nToA, nToB, nToC ) ); + dump( "\""); + } + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateSetContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAnimateSet > xSet( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateSet && xSet.is(), "invalid call to ppt::AnimationImporter::importAnimateSetContainer()!"); + if( pAtom && xSet.is() ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimateSetData: + { + sal_Int32 nU1, nU2; + mrStCtrl >> nU1 >> nU2; + + dump( " set_1=\"%ld\"", nU1 ), + dump( " set_2=\"%ld\"", nU2 ); + } + break; + + case DFF_msofbtAnimAttributeValue: + { + Any aTo; + if ( importAttributeValue( pChildAtom, aTo ) ) + { + xSet->setTo( aTo ); + + dump( " value=\"" ); + dump( aTo ); + dump( "\"" ); + } + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAnimate > xAnim( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimate && xAnim.is(), "invalid call to ppt::AnimationImporter::importAnimateContainer()!"); + if( pAtom && xAnim.is() ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimateData: + { + sal_uInt32 nCalcmode, nBits, nValueType; + mrStCtrl >> nCalcmode >> nBits >> nValueType; + + if( nBits & 0x08 ) + { + sal_Int16 n = (nCalcmode == 1) ? AnimationCalcMode::LINEAR : /* (nCalcmode == 2) ? AnimationCalcMode::FORMULA : */ AnimationCalcMode::DISCRETE; + xAnim->setCalcMode( n ); + dump( " calcmode=\"%s\"", (nCalcmode == 0) ? "discrete" : (nCalcmode == 1) ? "linear" : (nCalcmode == 2) ? "formula" : "unknown" ); + } + + if( nBits & 0x30 ) + { + sal_Int16 n = (nValueType == 1) ? AnimationValueType::NUMBER : (nValueType == 2 ) ? AnimationValueType::COLOR : AnimationValueType::STRING; + xAnim->setValueType( n ); + dump( " valueType=\"%s\"", (nValueType == 0) ? "string" : (nValueType == 1) ? "number" : (nValueType == 2) ? "color" : "unknown" ); + } + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimKeyPoints: + importAnimateKeyPoints( pChildAtom, xNode ); + break; + + case DFF_msofbtAnimAttributeValue: + { + Any a; + if ( importAttributeValue( pChildAtom, a ) ) + { + switch( pChildAtom->getInstance() ) + { + case 1: xAnim->setBy( a ); dump( " by=\"" ); break; + case 2: xAnim->setFrom( a ); dump( " from=\"" ); break; + case 3: xAnim->setTo( a ); dump( " to=\"" ); break; + default: + dump( " unknown_value=\"" ); + } + + dump( a ); + dump( "\"" ); + } + } + break; + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateMotionContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAnimateMotion > xMotion( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateMotion && xMotion.is(), "invalid call to ppt::AnimationImporter::importAnimateMotionContainer()!"); + if( pAtom && xMotion.is() ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimateMotionData: + { + sal_uInt32 nBits, nOrigin; + float fByX, fByY, fFromX, fFromY, fToX, fToY; + + mrStCtrl >> nBits >> fByX >> fByY >> fFromX >> fFromY >> fToX >> fToY >> nOrigin; + +#ifdef DBG_ANIM_LOG + if( nBits & 1 ) + fprintf( mpFile, " by=\"%g,%g\"", (double)fByX, (double)fByY ); + + if( nBits & 2 ) + fprintf( mpFile, " from=\"%g,%g\"", (double)fFromX, (double)fFromY ); + + if( nBits & 4 ) + fprintf( mpFile, " to=\"%g,%g\"", (double)fToX, (double)fToY ); + + if( nBits & 8 ) + fprintf( mpFile, " origin=\"%s\"", (nOrigin == 1) ? "parent" : (nOrigin == 2) ? "layout" : "unknown" ); + +#endif + } + break; + + case DFF_msofbtAnimAttributeValue: + { + Any aPath; + if ( importAttributeValue( pChildAtom, aPath ) ) + { + rtl::OUString aStr; + if ( aPath >>= aStr ) + { + aStr = aStr.replace( 'E', ' ' ); + aStr = aStr.trim(); + aPath <<= aStr; + xMotion->setPath( aPath ); + dump( " path=\"" ); + dump( aPath ); + dump( "\"" ); + } + } + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importCommandContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XCommand > xCommand( xNode, UNO_QUERY ); + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimCommand && xCommand.is(), "invalid call to ppt::AnimationImporter::importCommandContainer()!"); + if( pAtom && xCommand.is() ) + { + sal_Int32 nBits = 0, nType = 0; + Any aValue; + + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtCommandData: + { + sal_Int32 nCommandType; + // looks like U1 is a bitset, bit 1 enables the type and bit 2 enables + // a propertyvalue that follows + mrStCtrl >> nBits; + mrStCtrl >> nCommandType; + + if( nBits && 1 ) + { + dump( " type=\"%s\"", (nCommandType == 0) ? "event" : ( nCommandType == 1) ? "call" : "verb" ); + } + } + break; + + case DFF_msofbtAnimAttributeValue: + { + if ( importAttributeValue( pChildAtom, aValue ) ) + { + if( nBits && 2 ) + { + dump( " cmd=\"" ); + dump( aValue ); + dump( "\"" ); + } + } + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + + if( nBits & 3 ) + { + OUString aParam; + aValue >>= aParam; + + sal_Int16 nCommand = EffectCommands::CUSTOM; + + NamedValue aParamValue; + + switch( nType ) + { + case 0: // event + case 1: // call + if( aParam.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "onstopaudio" ) ) ) + { + nCommand = EffectCommands::STOPAUDIO; + } + else if( aParam.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("play") ) ) + { + nCommand = EffectCommands::PLAY; + } + else if( aParam.compareToAscii( RTL_CONSTASCII_STRINGPARAM("playFrom") ) == 0 ) + { + const OUString aMediaTime( aParam.copy( 9, aParam.getLength() - 10 ) ); + rtl_math_ConversionStatus eStatus; + double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); + if( eStatus == rtl_math_ConversionStatus_Ok ) + { + aParamValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("MediaTime")); + aParamValue.Value <<= fMediaTime; + } + nCommand = EffectCommands::PLAY; + } + else if( aParam.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("togglePause") ) ) + { + nCommand = EffectCommands::TOGGLEPAUSE; + } + else if( aParam.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("stop") ) ) + { + nCommand = EffectCommands::STOP; + } + break; + case 2: // verb + { + aParamValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Verb")); + aParamValue.Value <<= aParam.toInt32(); + + nCommand = EffectCommands::VERB; + } + break; + } + + xCommand->setCommand( nCommand ); + if( nCommand == EffectCommands::CUSTOM ) + { + DBG_ERROR("sd::AnimationImporter::importCommandContainer(), unknown command!"); + aParamValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("UserDefined")); + aParamValue.Value <<= aParam; + } + + if( aParamValue.Value.hasValue() ) + { + Sequence< NamedValue > aParamSeq( &aParamValue, 1 ); + xCommand->setParameter( makeAny( aParamSeq ) ); + } + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAudioContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAudio > xAudio( xNode, UNO_QUERY ); + DBG_ASSERT( pAtom && xAudio.is() && + ( (pAtom->getType() == DFF_msofbtAnimGroup) || + (pAtom->getType() == DFF_msofbtAnimSubGoup) ), "invalid call to ppt::AnimationImporter::importAudioContainer()!"); + if( pAtom && xAudio.is() ) + { + importAnimationEvents( pAtom, xNode ); + importAnimationValues( pAtom, xNode ); + importAnimationActions( pAtom, xNode ); + + dump(">\n"); + + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimNode: + case DFF_msofbtAnimEvent: + case DFF_msofbtAnimValue: + case DFF_msofbtAnimAction: + case DFF_msofbtAnimPropertySet: + break; + + case DFF_msofbtAnimAttributeValue: + { + Any aValue; + if ( importAttributeValue( pChildAtom, aValue ) ) + { + dump( " value=\"" ); + dump( aValue ); + dump( "\"" ); + } + } + break; + + case DFF_msofbtAnimateTargetElement: + { + sal_Int16 nSubType; + Any aSource; + importTargetElementContainer( pChildAtom, aSource, nSubType ); + if( xAudio.is() ) + xAudio->setSource( aSource ); + } + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + + // TODO: What to do with them? + Any aEmpty; + xAudio->setBegin( aEmpty ); + xAudio->setEnd( aEmpty ); + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateScaleContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateScale && xTransform.is(), "invalid call to ppt::AnimationImporter::importAnimateScaleContainer()!"); + if( pAtom && xTransform.is() ) + { + xTransform->setTransformType( AnimationTransformType::SCALE ); + + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimateScaleData: + { + sal_uInt32 nBits, nZoomContents; + float fByX, fByY, fFromX, fFromY, fToX, fToY; + + // nBits %001: by, %010: from, %100: to, %1000: zoomContents(bool) + mrStCtrl >> nBits >> fByX >> fByY >> fFromX >> fFromY >> fToX >> fToY >> nZoomContents; + + ValuePair aPair; + // 'from' value + if( nBits & 2 ) + { + aPair.First <<= (double)fFromX / 100.0; + aPair.Second <<= (double)fFromY / 100.0; + xTransform->setFrom( makeAny( aPair ) ); + } + + // 'to' value + if( nBits & 4 ) + { + aPair.First <<= (double)fToX / 100.0; + aPair.Second <<= (double)fToY / 100.0; + xTransform->setTo( makeAny( aPair ) ); + } + + // 'by' value + if( nBits & 1 ) + { + aPair.First <<= (double)fByX / 100.0; + aPair.Second <<= (double)fByY / 100.0; + + if( nBits & 2 ) + { + // 'from' value given, import normally + xTransform->setBy( makeAny( aPair ) ); + } + else + { + // mapping 'by' to 'to', if no 'from' is + // given. This is due to a non-conformity in + // PPT, which exports animateScale effects + // with a sole 'by' value, but with the + // semantics of a sole 'to' animation + xTransform->setTo( makeAny( aPair ) ); + } + } + + +#ifdef DBG_ANIM_LOG + if( nBits & 1 ) + fprintf( mpFile, " by=\"%g,%g\"", (double)fByX, (double)fByY ); + + if( nBits & 2 ) + fprintf( mpFile, " from=\"%g,%g\"", (double)fFromX, (double)fFromY ); + + if( nBits & 4 ) + fprintf( mpFile, " to=\"%g,%g\"", (double)fToX, (double)fToY ); + + if( nBits & 8 ) + fprintf( mpFile, " zoomContents=\"%s\"", nZoomContents ? "true" : "false" ); +#endif + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateRotationContainer( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAnimateTransform > xTransform( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimateRotation && xTransform.is(), "invalid call to ppt::AnimationImporter::importAnimateRotationContainer()!"); + if( pAtom && xTransform.is() ) + { + xTransform->setTransformType( AnimationTransformType::ROTATE ); + + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + if( !pChildAtom->isContainer() ) + { + if( !pChildAtom->seekToContent() ) + break; + } + + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimateRotationData: + { + sal_uInt32 nBits, nU1; + float fBy, fFrom, fTo; + + // nBits %001: by, %010: from, %100: to, %1000: zoomContents(bool) + mrStCtrl >> nBits >> fBy >> fFrom >> fTo >> nU1; + + if( nBits & 1 ) + xTransform->setBy( makeAny( (double) fBy ) ); + + if( nBits & 2 ) + xTransform->setFrom( makeAny( (double) fFrom ) ); + + if( nBits & 4 ) + xTransform->setTo( makeAny( (double) fTo ) ); + +#ifdef DBG_ANIM_LOG + if( nBits & 1 ) + fprintf( mpFile, " by=\"%g\"", (double)fBy ); + + if( nBits & 2 ) + fprintf( mpFile, " from=\"%g\"", (double)fFrom ); + + if( nBits & 4 ) + fprintf( mpFile, " to=\"%g\"", (double)fTo ); + + if( nU1 ) + fprintf( mpFile, " rotation_1=\"%ld\"", nU1 ); +#endif + } + break; + + case DFF_msofbtAnimateTarget: + importAnimateAttributeTargetContainer( pChildAtom, xNode ); + break; + + default: + dump( " unknown_atom=\"%ld\"", (sal_Int32)pChildAtom->getType() ); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} +// -------------------------------------------------------------------- + +bool AnimationImporter::importAttributeNamesContainer( const Atom* pAtom, OUString& rAttributeNames ) +{ + OUStringBuffer aNames; + + DBG_ASSERT( pAtom && (pAtom->getType() == DFF_msofbtAnimateAttributeNames), "invalid call to ppt::AnimationImporter::importAttributeName()!" ); + if( pAtom ) + { + const Atom* pAttributeValueAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimAttributeValue ); + + while( pAttributeValueAtom ) + { + Any aAny; + if ( importAttributeValue( pAttributeValueAtom, aAny ) ) + { + OUString aName; + if( aAny >>= aName ) + { + if( aNames.getLength() ) + aNames.append( (sal_Unicode)';' ); + + aNames.append( aName ); + } + } + else + { + DBG_ERROR( "error during ppt::AnimationImporter::importAttributeName()!" ); + } + + pAttributeValueAtom = pAtom->findNextChildAtom( DFF_msofbtAnimAttributeValue, pAttributeValueAtom ); + } + } + + rAttributeNames = aNames.makeStringAndClear(); + return true; +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimationValues( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( pAtom, "invalid call to ppt::AnimationImporter::importAnimationValues()!" ); + + if( pAtom ) + { + const Atom* pValueAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimValue ); + + while( pValueAtom && pValueAtom->seekToContent() ) + { + sal_uInt32 nType; + mrStCtrl >> nType; + switch( nType ) + { + case 0: + { + float fRepeat; + mrStCtrl >> fRepeat; + xNode->setRepeatCount( (fRepeat < ((float)3.40282346638528860e+38)) ? makeAny( (double)fRepeat ) : makeAny( Timing_INDEFINITE ) ); + +#ifdef DBG_ANIM_LOG + if( (fRepeat < ((float)3.40282346638528860e+38)) ) + { + dump( " repeat=\"%g\"", (double)fRepeat ); + } + else + { + dump( " repeat=\"indefinite\"" ); + } +#endif + } + break; + + case 3: + { + float faccelerate; + mrStCtrl >> faccelerate; + xNode->setAcceleration( faccelerate ); + dump( " accelerate=\"%g\"", (double)faccelerate ); + } + break; + + case 4: + { + float fdecelerate; + mrStCtrl >> fdecelerate; + xNode->setDecelerate( fdecelerate ); + dump( " decelerate=\"%g\"", (double)fdecelerate ); + } + break; + + case 5: + { + sal_Int32 nAutoreverse; + mrStCtrl >> nAutoreverse; + xNode->setAutoReverse( nAutoreverse != 0 ); + dump( " autoreverse=\"%#lx\"", nAutoreverse ); + } + break; + + default: + { + sal_uInt32 nUnknown; + mrStCtrl >> nUnknown; +#ifdef DBG_ANIM_LOG + fprintf(mpFile, " attribute_%d=\"%#lx\"", nType, nUnknown ); +#endif + } + break; + } + + pValueAtom = pAtom->findNextChildAtom( DFF_msofbtAnimValue, pValueAtom ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimateKeyPoints( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + Reference< XAnimate > xAnim( xNode, UNO_QUERY ); + + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimKeyPoints && xAnim.is(), "invalid call to ppt::AnimationImporter::importAnimateKeyPoints()!" ); + + if( pAtom && xAnim.is() ) + { + // first count keytimes + const Atom* pIter = NULL; + int nKeyTimes = 0; + + while( (pIter = pAtom->findNextChildAtom( DFF_msofbtAnimKeyTime, pIter )) != 0 ) + nKeyTimes++; + + Sequence< double > aKeyTimes( nKeyTimes ); + Sequence< Any > aValues( nKeyTimes ); + OUString aFormula; + + pIter = pAtom->findFirstChildAtom(DFF_msofbtAnimKeyTime); + int nKeyTime; + sal_Int32 nTemp; + for( nKeyTime = 0; (nKeyTime < nKeyTimes) && pIter; nKeyTime++ ) + { + if( pIter->seekToContent() ) + { + mrStCtrl >> nTemp; + double fTemp = (double)nTemp / 1000.0; + aKeyTimes[nKeyTime] = fTemp; + + const Atom* pValue = pAtom->findNextChildAtom(pIter); + if( pValue && pValue->getType() == DFF_msofbtAnimAttributeValue ) + { + Any aValue1, aValue2; + if( importAttributeValue( pValue, aValue1 ) ) + { + pValue = pAtom->findNextChildAtom(pValue); + if( pValue && pValue->getType() == DFF_msofbtAnimAttributeValue ) + importAttributeValue( pValue, aValue2 ); + + bool bCouldBeFormula = false; + bool bHasValue = aValue2.hasValue(); + if( bHasValue ) + { + if( aValue2.getValueType() == ::getCppuType((const OUString*)0) ) + { + OUString aTest; + aValue2 >>= aTest; + bHasValue = aTest.getLength() != 0; + bCouldBeFormula = true; + } + } + + if( bHasValue && bCouldBeFormula && (aValue1.getValueType() == ::getCppuType((const double*)0)) ) + { + aValue2 >>= aFormula; + bHasValue = false; + } + + if( bHasValue ) + { + aValues[nKeyTime] = makeAny( ValuePair( aValue1, aValue2 ) ); + } + else + { + aValues[nKeyTime] = aValue1; + } + } + } + } + pIter = pAtom->findNextChildAtom(DFF_msofbtAnimKeyTime, pIter); + } + +#ifdef DBG_ANIM_LOG + dump( " keyTimes=\"" ); + for( int i=0; i<nKeyTimes; ++i ) + dump( "%f;", aKeyTimes[i] ); + + if( aFormula.getLength() ) + { + dump( "formula=\"%s", aFormula ); + } + + dump( "\" values=\"" ); + double nVal; + OUString aStr; + for( int i=0; i<nKeyTimes; ++i ) + { + if( i != 0 ) + dump( ";" ); + + if( aValues[i] >>= aStr ) + dump( "%s", + ::rtl::OUStringToOString( aStr, + RTL_TEXTENCODING_ASCII_US ).getStr() ); + else if( aValues[i] >>= nVal ) + dump( "%f", nVal ); + else + { + ValuePair aValuePair; + + if( aValues[i] >>= aValuePair ) + { + if( aValuePair.First >>= aStr ) + dump( "%s", + ::rtl::OUStringToOString( aStr, + RTL_TEXTENCODING_ASCII_US ).getStr() ); + else if( aValuePair.First >>= nVal ) + dump( "%f", nVal ); + else + dump( "%X", (sal_Int32)&aValuePair.First ); + + if( aValuePair.Second >>= aStr ) + dump( ",%s", + ::rtl::OUStringToOString( aStr, + RTL_TEXTENCODING_ASCII_US ).getStr() ); + else if( aValuePair.Second >>= nVal ) + dump( ",%f", nVal ); + else + dump( ",%X", (sal_Int32)&aValuePair.Second ); + } + } + } + dump( "\"" ); +#endif + + xAnim->setKeyTimes( aKeyTimes ); + xAnim->setValues( aValues ); + xAnim->setFormula( aFormula ); + } +} + +// -------------------------------------------------------------------- + +bool AnimationImporter::importAttributeValue( const Atom* pAtom, Any& rAny ) +{ + DBG_ASSERT( pAtom && pAtom->getType() == DFF_msofbtAnimAttributeValue, "invalid call to ppt::AnimationImporter::importAttributeValue()!" ); + + bool bOk = false; + + if( pAtom && pAtom->seekToContent() ) + { + sal_uInt32 nRecLen = pAtom->getLength(); + if ( nRecLen >= 1 ) + { + sal_Int8 nType; + mrStCtrl >> nType; + switch( nType ) + { + case DFF_ANIM_PROP_TYPE_BYTE : + { + if ( nRecLen == 2 ) + { + sal_uInt8 nByte; + mrStCtrl >> nByte; + rAny <<= nByte; + + bOk = true; + } + } + break; + + case DFF_ANIM_PROP_TYPE_INT32 : + { + if ( nRecLen == 5 ) + { + sal_uInt32 nInt32; + mrStCtrl >> nInt32; + rAny <<= nInt32; + + bOk = true; + } + } + break; + + case DFF_ANIM_PROP_TYPE_FLOAT: + { + if( nRecLen == 5 ) + { + float fFloat; + mrStCtrl >> fFloat; + rAny <<= (double)fFloat; + + bOk = true; + } + } + break; + + case DFF_ANIM_PROP_TYPE_UNISTRING : + { + if ( ( nRecLen & 1 ) && ( nRecLen > 1 ) ) + { + String aString; + mpPPTImport->MSDFFReadZString( mrStCtrl, aString, nRecLen - 1, sal_True ); + rtl::OUString aOUString( aString ); + rAny <<= aOUString; + + bOk = true; + } + } + break; + } + } + } + + DBG_ASSERT( bOk, "invalid value inside ppt::AnimationImporter::importAttributeValue()!" ); + return bOk; +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimationEvents( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( xNode.is() && pAtom, "invalid call to ppt::AnimationImporter::importAnimationEvents()!" ); + + Any aBegin, aEnd, aNext, aPrev; + + const Atom* pEventAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimEvent ); + while( pEventAtom ) + { + Any* pEvents = NULL; + + switch( pEventAtom->getInstance() ) + { + case 1: pEvents = &aBegin; break; + case 2: pEvents = &aEnd; break; + case 3: pEvents = &aNext; break; + case 4: pEvents = &aPrev; break; + } + + if( pEvents ) + { + Event aEvent; + aEvent.Trigger = EventTrigger::NONE; + aEvent.Repeat = 0; + + const Atom* pChildAtom = pEventAtom->findFirstChildAtom(); + + while( pChildAtom && pChildAtom->seekToContent() ) + { + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimTrigger: + { + sal_Int32 nU1, nTrigger, nU3, nBegin; + mrStCtrl >> nU1; + mrStCtrl >> nTrigger; + mrStCtrl >> nU3; + mrStCtrl >> nBegin; + + switch( nTrigger ) + { + case 0: aEvent.Trigger = EventTrigger::NONE; break; + case 1: aEvent.Trigger = EventTrigger::ON_BEGIN; break; + case 2: aEvent.Trigger = EventTrigger::ON_END; break; + case 3: aEvent.Trigger = EventTrigger::BEGIN_EVENT; break; + case 4: aEvent.Trigger = EventTrigger::END_EVENT; break; + case 5: aEvent.Trigger = EventTrigger::ON_CLICK; break; + case 6: aEvent.Trigger = EventTrigger::ON_DBL_CLICK; break; + case 7: aEvent.Trigger = EventTrigger::ON_MOUSE_ENTER; break; + case 8: aEvent.Trigger = EventTrigger::ON_MOUSE_LEAVE; break; + case 9: aEvent.Trigger = EventTrigger::ON_NEXT; break; + case 10: aEvent.Trigger = EventTrigger::ON_PREV; break; + case 11: aEvent.Trigger = EventTrigger::ON_STOP_AUDIO; break; + } + + if( (nBegin != 0) || (aEvent.Trigger == EventTrigger::NONE) ) + aEvent.Offset = (nBegin == -1) ? makeAny( Timing_INDEFINITE ) : makeAny( (double)(nBegin / 1000.0) ); + } + break; + case DFF_msofbtAnimateTargetElement: + { + sal_Int16 nSubType; + importTargetElementContainer( pChildAtom, aEvent.Source, nSubType ); + } + break; + default: + { + DBG_ERROR("unknown atom inside ppt::AnimationImporter::importAnimationEvents()!"); + } + } + + pChildAtom = pEventAtom->findNextChildAtom( pChildAtom ); + } + + *pEvents = addToSequence( *pEvents, (aEvent.Trigger == EventTrigger::NONE) ? aEvent.Offset : makeAny( aEvent ) ); + } + + pEventAtom = pAtom->findNextChildAtom( DFF_msofbtAnimEvent, pEventAtom ); + } + + xNode->setBegin( aBegin ); + xNode->setEnd( aEnd ); + // TODO: xNode->setNext( aNext ); + // TODO: xNode->setPrev( aNext ); + +#ifdef DBG_ANIM_LOG + if( aBegin.hasValue() ) + { + dump( " begin=\"" ); + dump( aBegin ); + dump( "\"" ); + } + + if( aEnd.hasValue() ) + { + dump( " end=\"" ); + dump( aEnd ); + dump( "\"" ); + } + + if( aNext.hasValue() ) + { + dump( " next=\"" ); + dump( aNext ); + dump( "\"" ); + } + + if( aPrev.hasValue() ) + { + dump( " prev=\"" ); + dump( aPrev ); + dump( "\"" ); + } +#endif +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importAnimationActions( const Atom* pAtom, const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( pAtom && xNode.is(), "invalid call to ppt::AnimationImporter::importAnimationActions()!"); + + if( pAtom ) + { + const Atom* pActionAtom = pAtom->findFirstChildAtom( DFF_msofbtAnimAction ); + + if( pActionAtom && pActionAtom->seekToContent() ) + { + sal_Int32 nConcurrent, nNextAction, nEndSync, nU4, nU5; + mrStCtrl >> nConcurrent; + mrStCtrl >> nNextAction; + mrStCtrl >> nEndSync; + mrStCtrl >> nU4; + mrStCtrl >> nU5; + + if( nEndSync == 1 ) + xNode->setEndSync( makeAny( AnimationEndSync::ALL ) ); + + #ifdef DBG_ANIM_LOG + dump( " concurrent=\"%s\"", nConcurrent == 0 ? "disabled" : (nConcurrent == 1 ? "enabled" : "unknown") ); + + dump( " nextAction=\"%s\"", nNextAction == 0 ? "none" : (nNextAction == 1 ? "seek" : "unknown") ); + + if( nEndSync != 0 ) + { + dump( " endSync=\"%s\"", nEndSync == 1 ? "all" : "unknown" ); + } + + dump( " action_4=\"%#lx\"", nU4 ); + dump( " action_5=\"%#lx\"", nU5 ); + #endif + } + } +} + +// -------------------------------------------------------------------- + +sal_Int32 AnimationImporter::importTargetElementContainer( const Atom* pAtom, Any& rTarget, sal_Int16& rSubType ) +{ + rSubType = ShapeAnimationSubType::AS_WHOLE; + sal_Int32 nRefMode = -1; + + DBG_ASSERT( pAtom && (pAtom->getType() == DFF_msofbtAnimateTargetElement), "invalid call to ppt::AnimationImporter::importTargetElementContainer()!" ); + if( pAtom ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + while( pChildAtom && pChildAtom->seekToContent() ) + { + switch( pChildAtom->getType() ) + { + case DFF_msofbtAnimReference: + { + sal_Int32 nRefType,nRefId; + sal_Int32 begin,end; + mrStCtrl >> nRefMode; + mrStCtrl >> nRefType; + mrStCtrl >> nRefId; + mrStCtrl >> begin; + mrStCtrl >> end; + + switch( nRefType ) + { + case 1: // shape + { + SdrObject* pSdrObject = mpPPTImport->getShapeForId( nRefId ); + if( pSdrObject == NULL ) + break; + + rTarget <<= pSdrObject->getUnoShape(); + + switch( nRefMode ) + { +// default case 0: rSubType = ShapeAnimationSubType::AS_WHOLE; break; + case 6: rSubType = ShapeAnimationSubType::ONLY_BACKGROUND; break; + case 8: rSubType = ShapeAnimationSubType::ONLY_TEXT; break; + case 2: // one paragraph + { + if( ((begin == -1) && (end == -1)) || !pSdrObject->ISA( SdrTextObj ) ) + break; + + SdrTextObj* pTextObj = static_cast< SdrTextObj* >( pSdrObject ); + + const OutlinerParaObject* pOPO = pTextObj->GetOutlinerParaObject(); + if( pOPO == NULL ) + break; + + const EditTextObject& rEditTextObject = pOPO->GetTextObject(); + + const USHORT nParaCount = rEditTextObject.GetParagraphCount(); + + USHORT nPara = 0; + + while( (nPara < nParaCount) && (begin > 0) ) + { + sal_Int32 nParaLength = rEditTextObject.GetText( nPara ).Len() + 1; + begin -= nParaLength; + end -= nParaLength; + nPara++; + } + + if( nPara < nParaCount ) + { + ParagraphTarget aParaTarget; + rTarget >>= aParaTarget.Shape; + aParaTarget.Paragraph = nPara; + rTarget = makeAny( aParaTarget ); + + rSubType = ShapeAnimationSubType::ONLY_TEXT; + dump( " paragraph %d,", (sal_Int32)nPara); + dump( " %d characters", (sal_Int32)end ); + } + } + } + } + break; + + case 2: // sound + { + OUString aSoundURL( ((ImplSdPPTImport*)mpPPTImport)->ReadSound( nRefId ) ); + rTarget <<= aSoundURL; + dump( " srcRef=\"%s\"", aSoundURL ); + } + break; + case 3: // audio object + case 4: // video object + { + SdrObject* pSdrObject = mpPPTImport->getShapeForId( nRefId ); + if( pSdrObject == NULL ) + break; + + rTarget <<= pSdrObject->getUnoShape(); + } + break; + default: + DBG_ERROR("unknown reference type"); + } + + +// dump( " ref=\"%s\"", nRefMode == 3 ? "source" : ( nRefMode == 0 ? "target" : "unknown" ) ); +// dump( " type=\"%s\"", nRefType == 1 ? "shape" : ( nRefType == 2 ? "sound": "unknown" ) ); +// dump( " id=\"%lu\"", (sal_Int32)nRefId ); +#ifdef DBG_ANIM_LOG + if((begin != -1) || (end != -1) ) + { +// dump( " text_begin=\"%ld\"", begin ); +// dump( " text_end=\"%ld\"", end ); + } +#endif + } + break; + case 0x2b01: + { + sal_Int32 nU1; + mrStCtrl >> nU1; + + // HINT: nU1 == 1 : target document. ? +// dump( " unknown_0x2b01=\"%#lx\"", nU1 ); + } + break; + default: + DBG_ERROR("unknwon atom inside ppt::AnimationImporter::importTargetElementContainer()!"); + break; + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + + } + } + + return nRefMode; +} + +// -------------------------------------------------------------------- + +void AnimationImporter::importPropertySetContainer( const Atom* pAtom, PropertySet& rSet ) +{ + DBG_ASSERT( pAtom && (pAtom->getType() == DFF_msofbtAnimPropertySet), "invalid call to ppt::AnimationImporter::importPropertySetContainer()!" ); + + if( pAtom ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + while( pChildAtom ) + { + if( pChildAtom->getType() == DFF_msofbtAnimAttributeValue ) + { + Any aAny; + importAttributeValue( pChildAtom, aAny ); + rSet.maProperties[ pChildAtom->getInstance() ] = aAny; + } + else + { + DBG_ERROR("unknwon atom inside ppt::AnimationImporter::importPropertySetContainer()!"); + } + + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } +} + +// ==================================================================== + +#ifdef DBG_ANIM_LOG +void AnimationImporter::dump_atom_header( const Atom* pAtom, bool bOpen, bool bAppend ) +{ + if( pAtom ) + { + const char* pTitle; + + bool bUnknown = false; + + switch( pAtom->getType() ) + { + case DFF_msofbtAnimEvent: pTitle = "AnimEvent"; break; + case DFF_msofbtAnimTrigger: pTitle = "AnimTrigger"; break; + case DFF_msofbtAnimateMotion: pTitle = "AnimateMotion"; break; + case DFF_msofbtAnimPropertySet: pTitle = "AnimPropertySet"; break; + case DFF_msofbtAnimateAttributeNames: pTitle = "AnimAttributeName"; break; + case DFF_msofbtAnimAttributeValue: pTitle = "AnimAttributeValue"; break; + case DFF_msofbtAnimGroup: pTitle = "AnimGroup"; break; + case DFF_msofbtAnimNode: pTitle = "AnimNode"; break; + case DFF_msofbtAnimValue: pTitle = "AnimValue"; break; + case DFF_msofbtAnimateFilter: pTitle = "animateFilter"; break; + case DFF_msofbtAnimate: pTitle = "animate"; break; + case DFF_msofbtAnimateSet: pTitle = "set"; break; + case DFF_msofbtAnimKeyTime: pTitle = "AnimKeyTime"; break; + case DFF_msofbtAnimKeyPoints: pTitle = "AnimKeyPoints"; break; + case DFF_msofbtAnimReference: pTitle = "AnimReference"; break; + case DFF_msofbtAnimateTargetElement: pTitle = "AnimTargetElementContainer"; break; + case DFF_msofbtAnimAction: pTitle = "AnimAction"; break; + case DFF_msofbtAnimCommand: pTitle = "AnimCommand"; break; + case DFF_msofbtAnimateTarget: pTitle = "TransformationTarget"; break; + case DFF_msofbtAnimateTargetSettings: pTitle = "TransformationTargetSettings"; break; + case DFF_msofbtAnimIteration: pTitle = "iterate"; break; + case DFF_msofbtAnimateColorData: pTitle = "colorData"; break; + case DFF_msofbtAnimateScaleData: pTitle = "scaleData"; break; + case DFF_msofbtAnimateSetData: pTitle = "setData"; break; + + default: + { + static char buffer[128]; + sprintf( buffer, "unknown_%#x", pAtom->getType() ); + pTitle = buffer; + } + } + + if( bOpen ) + { + fprintf(mpFile, "<%s", pTitle ); + + fprintf(mpFile, " instance=\"%hu\"%s", + pAtom->getInstance(), + bAppend ? "" : ">\n"); + } + else + { + if( bAppend ) + fprintf(mpFile,"/>\n"); + else + fprintf(mpFile, "</%s>\n", pTitle ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::dump( UINT32 nLen, bool bNewLine ) +{ + char * faul = "0123456789abcdef"; + + UINT32 i = 0; + int b = 0; + sal_Int8 nData; + + for( i = 0; i < nLen; i++ ) + { + mrStCtrl >> nData; + + fprintf( mpFile, "%c%c ", faul[ (nData >> 4) & 0x0f ], faul[ nData & 0x0f ] ); + + b++; + if( bNewLine && (b == 32) ) + { + fprintf(mpFile,"\n"); + b = 0; + } + } + if( (b != 0) && bNewLine ) + fprintf(mpFile,"\n"); +} + +// -------------------------------------------------------------------- + +void AnimationImporter::dump_atom( const Atom* pAtom, bool bNewLine ) +{ + if( pAtom ) + { + if( pAtom->isContainer() ) + { + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + while( pChildAtom ) + { + if( pChildAtom->getType() == DFF_msofbtAnimAttributeValue ) + { + fprintf(mpFile, "<attributeValue instance=\"%hu\"", pChildAtom->getInstance() ); + + Any aValue; + if( importAttributeValue( pChildAtom, aValue ) ) + { + sal_Int32 nInt; + rtl::OUString aString; + double fDouble; + + if( aValue >>= nInt ) + { + fprintf(mpFile, " value=\"%ld\"", nInt ); + } + else if( aValue >>= aString ) + { + UniString aTmp( aString ); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf(mpFile, " value=\"%s\"", aStr.GetBuffer() ); + } + else if( aValue >>= fDouble ) + { + fprintf(mpFile, " value=\"%g\"", fDouble ); + } + } + else + { + if( pChildAtom->seekToContent() ) + { + fprintf(mpFile, " value=\"" ); + dump_atom( pChildAtom, false ); + fprintf(mpFile, "\""); + } + } + + fprintf(mpFile, "/>\n" ); + } + else + { + dump_atom_header( pChildAtom, true, pChildAtom->getType() == DFF_msofbtAnimAttributeValue ); + dump_atom( pChildAtom ); + dump_atom_header( pChildAtom, false, pChildAtom->getType() == DFF_msofbtAnimAttributeValue ); + } + + pChildAtom = pAtom->findNextChildAtom(pChildAtom); + } + } + else if( pAtom->seekToContent() ) + { + dump( pAtom->getLength(), bNewLine ); + } + } +} + +// -------------------------------------------------------------------- + +void AnimationImporter::dump_anim_group( const Atom* pAtom, const AnimationNode& rNode, const PropertySet& rSet, bool bOpen ) +{ + fprintf( mpFile, bOpen ? "<" : "</" ); + + switch( rNode.mnGroupType ) + { + case mso_Anim_GroupType_PAR: + fprintf( mpFile, "par" ); + break; + case mso_Anim_GroupType_SEQ: + fprintf( mpFile, "seq" ); + break; + case mso_Anim_GroupType_NODE: + switch( rNode.mnNodeType ) + { + case mso_Anim_Behaviour_FILTER: + fprintf( mpFile, "animateFilter" ); + break; + case mso_Anim_Behaviour_ANIMATION: + if( pAtom->hasChildAtom( DFF_msofbtAnimateSet ) ) + fprintf( mpFile, "set" ); + else if( pAtom->hasChildAtom( DFF_msofbtAnimateColor ) ) + fprintf( mpFile, "animateColor" ); + else if( pAtom->hasChildAtom( DFF_msofbtAnimateScale ) ) + fprintf( mpFile, "animateScale" ); + else if( pAtom->hasChildAtom( DFF_msofbtAnimateRotation ) ) + fprintf( mpFile, "animateRotation" ); + else if( pAtom->hasChildAtom( DFF_msofbtAnimateMotion ) ) + fprintf( mpFile, "animateMotion" ); + else if( pAtom->hasChildAtom( DFF_msofbtAnimCommand ) ) + fprintf( mpFile, "command" ); + else + fprintf( mpFile, "animation" ); + break; + default: + { + fprintf( mpFile, "unknown_node_%#lx", rNode.mnNodeType ); + } + break; + } + break; + case mso_Anim_GroupType_MEDIA: + fprintf( mpFile, "media" ); + break; + default: + fprintf( mpFile, "unknown_group_%#lx", rNode.mnGroupType ); + break; + } + + if( bOpen ) + { + dump( rNode ); + dump( rSet ); + } + + fprintf(mpFile,">\n"); +} + +void AnimationImporter::dump( const AnimationNode& rNode ) +{ + // dump animation node + if( rNode.mnRestart != 0 ) + { + fprintf(mpFile," restart=\"%s\"", + rNode.mnRestart == 1 ? "always" : (rNode.mnRestart == 2 ? "whenOff" : (rNode.mnRestart == 3 ? "never" : "unknown")) ); + } + + if( rNode.mnFill ) + { + fprintf(mpFile," fill=\"%s\"", + rNode.mnFill == 1 ? "remove" : (rNode.mnFill == 3 ? "hold" : (rNode.mnFill == 2 ? "freeze" : "unknown")) ); + } + + if( rNode.mnDuration > 0 ) + { + double fSeconds = rNode.mnDuration; + fSeconds /= 1000.0; + fprintf(mpFile, " dur=\"%g\"", fSeconds); + } + else if( rNode.mnDuration < 0 ) + { + fprintf(mpFile, " dur=\"indefinite\"" ); + } + + if( rNode.mnU1 ) fprintf(mpFile," u1=\"%#lx\"", rNode.mnU1); + if( rNode.mnU3 ) fprintf(mpFile," u3=\"%#lx\"", rNode.mnU3); + if( rNode.mnU4 ) fprintf(mpFile," u4=\"%#lx\"", rNode.mnU4); +} + +void AnimationImporter::dump( Any& rAny ) +{ + Sequence< Any > aSeq; + sal_Int32 nInt; + double fDouble; + OUString aString; + sal_Bool bBool; + Event aEvent; + Timing aTiming; + + if( rAny >>= aSeq ) + { + const sal_Int32 nSize = aSeq.getLength(); + sal_Int32 nIndex = 0; + while( nIndex < nSize ) + { + dump( aSeq[nIndex++] ); + if(nIndex < nSize) + fprintf( mpFile, "," ); + } + } + else if( rAny >>= aString ) + { + UniString aTmp(aString); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf( mpFile, "%s", aStr.GetBuffer() ); + } + else if( rAny >>= nInt ) + { + fprintf( mpFile, "%ld", nInt ); + } + else if( rAny >>= bBool ) + { + fprintf( mpFile, "%s", bBool ? "true" : "false" ); + } + else if( rAny >>= fDouble ) + { + fprintf( mpFile, "%g", fDouble ); + } + else if( rAny >>= aTiming ) + { + fprintf( mpFile, "%s", aTiming == (Timing_INDEFINITE) ? "indefinite" : "media" ); + } + else if( rAny >>= aEvent ) + { + static const char* triggers[] = + { + "none","onbegin","onend","begin", + "end","onclick","ondoubleclick","onmouseenter", + "onmouseleave","onpptnext","onpptprev","onstopaudio" + }; + + if( aEvent.Trigger != EventTrigger::NONE ) + { + if( aEvent.Source.hasValue() ) + { + dump_target( aEvent.Source ); + dump( "." ); + } + + dump( triggers[ aEvent.Trigger ] ); + } + + if( aEvent.Offset.hasValue() ) + { + double fOffset; + if( aEvent.Offset >>= fOffset ) + fprintf( mpFile, "%g", fOffset ); + else + dump( "indefinite" ); + } + } +} + +void AnimationImporter::dump( const PropertySet& rSet ) +{ + // dump property set + + map< sal_Int32, Any >::const_iterator aIter( rSet.maProperties.begin() ); + const map< sal_Int32, Any >::const_iterator aEnd( rSet.maProperties.end() ); + while( aIter != aEnd ) + { + bool bKnown = false; + + const sal_Int32 nInstance = (*aIter).first; + Any aAny( (*aIter).second ); + + switch ( nInstance ) + { + case DFF_ANIM_COLORSPACE: + { + sal_Int32 nColorSpace; + if( aAny >>= nColorSpace ) + { + fprintf( mpFile, " colorSpace=\"%s\"", (nColorSpace == 0) ? "rgb" : (nColorSpace == 1) ? "hsl" : "unknown" ); + bKnown = true; + } + } + break; + + case DFF_ANIM_DIRECTION: +// case DFF_ANIM_MASTERREL: + { + sal_Bool bDirection; + if( aAny >>= bDirection ) + { + fprintf( mpFile, " direction=\"%s\"", bDirection ? "cclockwise" : "clockwise" ); + bKnown = true; + } + else + { + sal_Int32 nMasterRel; + if( aAny >>= nMasterRel ) + { + fprintf( mpFile, " direction=\"%s\"", nMasterRel == 0 ? "sameClick" : ( nMasterRel == 2 ? "nextClick" : "lastClick" ) ); + bKnown = true; + } + } + } + break; + + case DFF_ANIM_OVERRIDE: // TODO + { + sal_Int32 nOverride; + if( aAny >>= nOverride ) + { + fprintf( mpFile, " override=\"%s\"", (nOverride == 1) ? "childStyle" : (nOverride == 0) ? "normal" : "unknown" ); + bKnown = true; + } + } + break; + + case DFF_ANIM_PATH_EDIT_MODE: + { + sal_Bool bPathEditMode; + if( aAny >>= bPathEditMode ) + { + fprintf( mpFile, " pptPathEditMode=\"%s\"", bPathEditMode ? "relative" : "fixed" ); + bKnown = true; + } + } + break; + + case DFF_ANIM_PRESET_ID : + { + sal_Int32 nPresetId ; + if( aAny >>= nPresetId ) + { + fprintf(mpFile, " presetid=\"%ld\"", nPresetId ); + bKnown = true; + } + } + break; + + case DFF_ANIM_PRESET_SUB_TYPE : + { + sal_Int32 nPointsType ; + if( aAny >>= nPointsType ) + { + fprintf(mpFile, " presetSubType=\"%ld\"", nPointsType ); + bKnown = true; + } + } + break; + + case DFF_ANIM_PRESET_CLASS : + { + sal_Int32 nPresetClass; + if ( aAny >>= nPresetClass ) + { + const char* pMode; + switch( nPresetClass ) + { + case DFF_ANIM_PRESS_CLASS_USER_DEFINED: pMode = "userdefined"; break; + case DFF_ANIM_PRESS_CLASS_ENTRANCE: pMode = "entrance"; break; + case DFF_ANIM_PRESS_CLASS_EXIT: pMode = "exit"; break; + case DFF_ANIM_PRESS_CLASS_EMPHASIS: pMode = "emphasis"; break; + case DFF_ANIM_PRESS_CLASS_MOTIONPATH: pMode = "motionpath"; break; + case DFF_ANIM_PRESS_CLASS_OLE_ACTION: pMode = "oleaction"; break; + case DFF_ANIM_PRESS_CLASS_MEDIACALL: pMode = "mediacall"; break; + default: + { + static char buffer[128]; + sprintf( buffer, "%ld", nPresetClass ); + pMode = buffer; + } + break; + } + + fprintf(mpFile, " class=\"%s\"", pMode); + bKnown = true; + } + } + break; + + case DFF_ANIM_NODE_TYPE : + { + sal_Int32 nNodeType; + if ( aAny >>= nNodeType ) + { + const char* pNode; + switch( nNodeType ) + { + case DFF_ANIM_NODE_TYPE_ON_CLICK: pNode = "onclick"; break; + case DFF_ANIM_NODE_TYPE_WITH_PREVIOUS: pNode = "withprevious"; break; + case DFF_ANIM_NODE_TYPE_AFTER_PREVIOUS: pNode = "afterprevious"; break; + case DFF_ANIM_NODE_TYPE_MAIN_SEQUENCE: pNode = "mainsequence"; break; + case DFF_ANIM_NODE_TYPE_TIMING_ROOT: pNode = "timingroot"; break; + case DFF_ANIM_NODE_TYPE_INTERACTIVE_SEQ:pNode = "interactivesequence"; break; + default : + { + static char buffer[128]; + sprintf( buffer, "%ld", nNodeType ); + pNode = buffer; + } + break; + } + + fprintf(mpFile, " nodeType=\"%s\"", pNode); + bKnown = true; + } + } + break; + + case DFF_ANIM_GROUP_ID: + { + sal_Int32 nGroupId; + if ( aAny >>= nGroupId ) + { + fprintf( mpFile, " groupId=\"%ld\"", nGroupId ); + bKnown = true; + } + } + break; + + case DFF_ANIM_ID: + { + rtl::OUString aString; + if( aAny >>= aString ) + { + UniString aTmp(aString); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf( mpFile, " id=\"%s\"", aStr.GetBuffer() ); + bKnown = true; + } + } + break; + + case DFF_ANIM_EVENT_FILTER: + { + rtl::OUString aString; + if( aAny >>= aString ) + { + UniString aTmp(aString); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf( mpFile, " eventFilter=\"%s\"", aStr.GetBuffer() ); + bKnown = true; + } + } + break; + + case DFF_ANIM_ENDAFTERSLIDE: + { + sal_Int32 nEndAfterSlide; + if( aAny >>= nEndAfterSlide ) + { + fprintf(mpFile, " endAfterSlide=\"%ld\"", nEndAfterSlide ); + bKnown = true; + } + } + + case DFF_ANIM_TIMEFILTER: + { + rtl::OUString aString; + if( aAny >>= aString ) + { + UniString aTmp(aString); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf( mpFile, " timeFilter=\"%s\"", aStr.GetBuffer() ); + bKnown = true; + } + } + break; + + case DFF_ANIM_RUNTIMECONTEXT: + { + rtl::OUString aString; + if( aAny >>= aString ) + { + UniString aTmp(aString); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf( mpFile, " runtimeContext=\"%s\"", aStr.GetBuffer() ); + bKnown = true; + } + } + break; + + case DFF_ANIM_VOLUME: + { + double fVolume; + if( aAny >>= fVolume ) + { + fprintf( mpFile, " volume=\"%g%%\"", (double)(fVolume * 100.0) ); + bKnown = true; + } + } + break; + + case DFF_ANIM_AFTEREFFECT: + { + sal_Bool bAfterEffect; + if( aAny >>= bAfterEffect ) + { + fprintf( mpFile, "afterEffect=\"%s\"", bAfterEffect ? "true" : "false" ); + bKnown = true; + } + } + break; + + } + + + if( !bKnown ) + { + fprintf( mpFile, " unknown_%lu=\"", nInstance ); + dump( aAny ); + fprintf( mpFile, "\"" ); + } + + aIter++; + } +} + +void AnimationImporter::dump_target( Any& rAny ) +{ + Any aSource, aSourceData; + Sequence< Any > aSeq; + if( rAny >>= aSeq ) + { + if( aSeq.getLength() >= 1 ) aSource = aSeq[0]; + if( aSeq.getLength() >= 2 ) aSourceData = aSeq[1]; + } + else + { + aSource = rAny; + } + + Reference< XShape > xShape; + aSource >>= xShape; + if( xShape.is() ) + { + OUString aStr( xShape->getShapeType() ); + dump( aStr ); + + if( aSourceData.hasValue() ) + { + dump( "(" ); + dump( aSourceData ); + dump( ")" ); + } + } +} + +void AnimationImporter::dump( const char * pText ) +{ + fprintf( mpFile, "%s", pText ); +} + +void AnimationImporter::dump( const rtl::OUString& rString ) +{ + UniString aTmp( rString ); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf( mpFile, aStr.GetBuffer() ); +} + +void AnimationImporter::dump( const char * pText, sal_Int32 nInt ) +{ + fprintf( mpFile, pText, nInt ); +} + +void AnimationImporter::dump( const char * pText, double fDouble ) +{ + fprintf( mpFile, pText, fDouble ); +} + +void AnimationImporter::dump( const char * pText, const char * pText2 ) +{ + fprintf( mpFile, pText, pText2 ); +} + +void AnimationImporter::dump( const char * pText, const OUString& rString ) +{ + UniString aTmp( rString ); + ByteString aStr( aTmp, RTL_TEXTENCODING_UTF8 ); + fprintf( mpFile, pText, aStr.GetBuffer() ); +} + +#else + +void AnimationImporter::dump_atom_header( const Atom* , bool , bool ) +{ +} + +void AnimationImporter::dump_atom( const Atom* , bool ) +{ +} + +void AnimationImporter::dump_target( ::com::sun::star::uno::Any& ) +{ +} + +void AnimationImporter::dump( ::com::sun::star::uno::Any& ) +{ +} + +void AnimationImporter::dump( const PropertySet& ) +{ +} + +void AnimationImporter::dump( const AnimationNode& ) +{ +} + +void AnimationImporter::dump( const char * ) +{ +} + +void AnimationImporter::dump( const char * , sal_Int32 ) +{ +} + +void AnimationImporter::dump( const char * , double ) +{ +} + +void AnimationImporter::dump( const char * , const char * ) +{ +} + +void AnimationImporter::dump( const char * , const rtl::OUString& ) +{ +} + +#endif + +} // namespace ppt; + |