/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::oox::core; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::container; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::animations; using namespace ::com::sun::star::presentation; namespace { void lcl_setAncestorSubItem( const Reference& xParent, sal_Int16 nSubItem ) { Reference xNode = xParent; while ( xNode.is() ) { if ( xNode->getType() == AnimationNodeType::ANIMATE ) { Reference xAnimate( xNode, UNO_QUERY ); if ( xAnimate.is() ) xAnimate->setSubItem( nSubItem ); break; } else if ( xNode->getType() == AnimationNodeType::ITERATE ) { Reference xIterateContainer( xNode, UNO_QUERY ); if ( xIterateContainer.is() ) xIterateContainer->setSubItem( nSubItem ); break; } xNode.set( xNode->getParent(), UNO_QUERY ); } } } namespace oox::ppt { OUString TimeNode::getServiceName( sal_Int16 nNodeType ) { OUString sServiceName; switch( nNodeType ) { case AnimationNodeType::PAR: sServiceName = "com.sun.star.animations.ParallelTimeContainer"; break; case AnimationNodeType::SEQ: sServiceName = "com.sun.star.animations.SequenceTimeContainer"; break; case AnimationNodeType::ANIMATE: sServiceName = "com.sun.star.animations.Animate"; break; case AnimationNodeType::ITERATE: sServiceName = "com.sun.star.animations.IterateContainer"; break; case AnimationNodeType::ANIMATECOLOR: sServiceName = "com.sun.star.animations.AnimateColor"; break; case AnimationNodeType::TRANSITIONFILTER: sServiceName = "com.sun.star.animations.TransitionFilter"; break; case AnimationNodeType::ANIMATEMOTION: sServiceName = "com.sun.star.animations.AnimateMotion"; break; case AnimationNodeType::ANIMATETRANSFORM: sServiceName = "com.sun.star.animations.AnimateTransform"; break; case AnimationNodeType::COMMAND: sServiceName = "com.sun.star.animations.Command"; break; case AnimationNodeType::SET: sServiceName = "com.sun.star.animations.AnimateSet"; break; case AnimationNodeType::AUDIO: sServiceName = "com.sun.star.animations.Audio"; break; default: SAL_INFO("oox.ppt","OOX: unhandled type " << nNodeType ); break; } return sServiceName; } TimeNode::TimeNode( sal_Int16 nNodeType ) : mnNodeType( nNodeType ) , mbHasEndSyncValue( false ) { } TimeNode::~TimeNode() { } void fixMainSequenceTiming( const css::uno::Reference< css::animations::XAnimationNode >& xNode ) { try { bool bFirst = true; Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_SET_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( Any( aEvent ) ); if( bFirst ) { bFirst = false; Reference< XEnumerationAccess > xEA2( xClickNode, UNO_QUERY_THROW ); Reference< XEnumeration > xE2( xEA2->createEnumeration(), UNO_SET_THROW ); if( xE2->hasMoreElements() ) { // with node xE2->nextElement() >>= xEA2; if( xEA2.is() ) xE2 = xEA2->createEnumeration(); else xE2.clear(); if( xE2.is() && xE2->hasMoreElements() ) { Reference< XAnimationNode > xEffectNode( xE2->nextElement(), UNO_QUERY_THROW ); const Sequence< NamedValue > aUserData( xEffectNode->getUserData() ); for( const NamedValue& rProp : aUserData ) { if ( rProp.Name == "node-type" ) { sal_Int16 nNodeType = 0; rProp.Value >>= nNodeType; if( nNodeType != css::presentation::EffectNodeType::ON_CLICK ) { // first effect does not start on click, so correct // first click nodes begin to 0s xClickNode->setBegin( Any( 0.0 ) ); break; } } } } } } } } catch( Exception& ) { SAL_INFO("oox.ppt","fixMainSequenceTiming(), exception caught!" ); } } void fixInteractiveSequenceTiming( const css::uno::Reference< css::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_SET_THROW ); while( xE->hasMoreElements() ) { // click node Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); xClickNode->setBegin( aBegin ); } } catch( Exception& ) { SAL_INFO("oox.ppt","fixInteractiveSequenceTiming(), exception caught!" ); } } void TimeNode::addNode( const XmlFilterBase& rFilter, const Reference< XAnimationNode >& rxNode, const SlidePersistPtr & pSlide ) { try { sal_Int16 nNodeType = mnNodeType; if (mnNodeType == AnimationNodeType::PAR && maNodeProperties[NP_ITERATETYPE].hasValue()) nNodeType = AnimationNodeType::ITERATE; OUString sServiceName = getServiceName(nNodeType); Reference< XAnimationNode > xNode = createAndInsert( rFilter, sServiceName, rxNode ); if (!xNode) return; setNode(rFilter, xNode, pSlide, rxNode); } catch( const Exception& ) { TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::addNode()" ); } } void TimeNode::setNode(const XmlFilterBase& rFilter, const Reference< XAnimationNode >& xNode, const SlidePersistPtr & pSlide, const Reference& xParent) { SAL_WARN_IF( !xNode.is(), "oox.ppt", "null node passed" ); try { if( !msId.isEmpty() ) { pSlide->getAnimNodesMap()[ msId ] = xNode; } if( mpTarget ) { sal_Int16 nSubItem(0); maNodeProperties[ NP_TARGET ] = mpTarget->convert( pSlide, nSubItem ); if( mpTarget->mnType == XML_spTgt ) { if ( xNode->getType() == AnimationNodeType::ANIMATE || xNode->getType() == AnimationNodeType::ITERATE ) { maNodeProperties[ NP_SUBITEM ] <<= nSubItem; } else lcl_setAncestorSubItem( xParent, nSubItem ); } } if( !maStCondList.empty() ) { Any aAny = AnimationCondition::convertList( pSlide, maStCondList ); if( aAny.hasValue() ) { xNode->setBegin( aAny ); } } if( !maEndCondList.empty() ) { Any aAny = AnimationCondition::convertList( pSlide, maEndCondList ); if( aAny.hasValue() ) { xNode->setEnd( aAny ); } } if( mbHasEndSyncValue ) { Any aValue = maEndSyncValue.convert( pSlide ); xNode->setEndSync(aValue); } if( !maUserData.empty() ) { Sequence< NamedValue > aUserDataSeq( static_cast< sal_Int32 >( maUserData.size() ) ); NamedValue* pValues = aUserDataSeq.getArray(); for (auto const& elem : maUserData) { pValues->Name = elem.first; pValues->Value = elem.second; ++pValues; } maNodeProperties[ NP_USERDATA ] <<= aUserDataSeq; } Reference< XAnimate > xAnimate( xNode, UNO_QUERY ); Reference< XAnimateColor > xAnimateColor( xNode, UNO_QUERY ); Reference< XAnimateMotion > xAnimateMotion( xNode, UNO_QUERY ); Reference< XAnimateTransform > xAnimateTransform( xNode, UNO_QUERY ); Reference< XCommand > xCommand( xNode, UNO_QUERY ); Reference< XAudio > xAudio( xNode, UNO_QUERY ); Reference< XIterateContainer > xIterateContainer( xNode, UNO_QUERY ); sal_Int16 nInt16 = 0; bool bBool = false; double fDouble = 0; OUString sString; Sequence< NamedValue > aSeq; for( int i = 0; i < NP_SIZE_; i++) { Any & aValue( maNodeProperties[ i ] ); if( aValue.hasValue() ) { switch( i ) { case NP_TO: if( xAnimate.is() ) xAnimate->setTo( aValue ); break; case NP_FROM: if( xAnimate.is() ) xAnimate->setFrom( aValue ); break; case NP_BY: if( xAnimate.is() ) xAnimate->setBy( aValue ); break; case NP_HIDEDURINGSHOW: if (xAudio.is() && (aValue >>= bBool)) { xAudio->setHideDuringShow(bBool); } break; case NP_ISNARRATION: if (xAudio.is() && (aValue >>= bBool)) { xAudio->setNarration(bBool); } break; case NP_TARGET: if (xParent.is() && xParent->getType() == AnimationNodeType::ITERATE) { Reference xParentContainer(xParent, UNO_QUERY); if (xParentContainer.is()) xParentContainer->setTarget(aValue); } else { if (xAnimate.is()) xAnimate->setTarget(aValue); if (xCommand.is()) xCommand->setTarget(aValue); if (xAudio.is()) xAudio->setSource(aValue); } break; case NP_SUBITEM: if( aValue >>= nInt16 ) { if( xAnimate.is() ) { xAnimate->setSubItem( nInt16 ); } else if ( xIterateContainer.is() ) { xIterateContainer->setSubItem( nInt16 ); } } else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } break; case NP_ATTRIBUTENAME: if( xAnimate.is() ) { if( aValue >>= sString ) xAnimate->setAttributeName( sString ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_CALCMODE: if( xAnimate.is() ) { if( aValue >>= nInt16 ) xAnimate->setCalcMode( nInt16 ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_KEYTIMES: if( xAnimate.is() ) { Sequence aKeyTimes; if( aValue >>= aKeyTimes ) xAnimate->setKeyTimes(aKeyTimes); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_VALUES: if( xAnimate.is() ) { Sequence aValues; if( aValue >>= aValues ) xAnimate->setValues(aValues); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_FORMULA: if( xAnimate.is() ) { if( aValue >>= sString ) xAnimate->setFormula(sString); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_COLORINTERPOLATION: if( xAnimateColor.is() ) { if( aValue >>= nInt16 ) xAnimateColor->setColorInterpolation( nInt16 ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_DIRECTION: if( xAnimateColor.is() ) { if( aValue >>= bBool ) xAnimateColor->setDirection( bBool ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_PATH: if( xAnimateMotion.is() ) xAnimateMotion->setPath( aValue ); break; case NP_TRANSFORMTYPE: if( xAnimateTransform.is() ) { if( aValue >>= nInt16 ) xAnimateTransform->setTransformType( nInt16 ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_USERDATA: if( aValue >>= aSeq ) xNode->setUserData( aSeq ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } break; case NP_ACCELERATION: if( aValue >>= fDouble ) xNode->setAcceleration( fDouble ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } break; case NP_DECELERATE: if( aValue >>= fDouble ) xNode->setDecelerate( fDouble ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } break; case NP_AUTOREVERSE: if( aValue >>= bBool ) xNode->setAutoReverse( bBool ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } break; case NP_DURATION: xNode->setDuration( aValue ); break; case NP_FILL: if( aValue >>= nInt16 ) xNode->setFill( nInt16 ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } break; case NP_REPEATCOUNT: xNode->setRepeatCount( aValue ); break; case NP_REPEATDURATION: xNode->setRepeatDuration( aValue ); break; case NP_RESTART: if( aValue >>= nInt16 ) xNode->setRestart( nInt16 ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } break; case NP_COMMAND: if( xCommand.is() ) { if( aValue >>= nInt16 ) xCommand->setCommand( nInt16 ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_PARAMETER: if( xCommand.is() ) xCommand->setParameter( aValue ); break; case NP_ITERATETYPE: if( xIterateContainer.is() ) { if( aValue >>= nInt16 ) xIterateContainer->setIterateType( nInt16 ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; case NP_ITERATEINTERVAL: if( xIterateContainer.is() ) { if( aValue >>= fDouble ) xIterateContainer->setIterateInterval( fDouble ); else { SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); } } break; default: SAL_INFO("oox.ppt","ERR-OOX: unknown prop index " << i ); break; } } } if (xAnimate.is() && xAnimate->getValues().getLength() != xAnimate->getKeyTimes().getLength()) throw css::io::WrongFormatException(); if( mnNodeType == AnimationNodeType::TRANSITIONFILTER ) { Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY ); maTransitionFilter.setTransitionFilterProperties( xFilter ); } std::for_each( maChildren.begin(), maChildren.end(), [&rFilter, &xNode, &pSlide] (TimeNodePtr const & child) { child->addNode(rFilter, xNode, pSlide); } ); switch( mnNodeType ) { case AnimationNodeType::SEQ: { sal_Int16 nEnum = 0; if( maUserData[ u"node-type"_ustr ] >>= nEnum ) { if( nEnum == EffectNodeType::MAIN_SEQUENCE ) { fixMainSequenceTiming( xNode ); } else if( nEnum == EffectNodeType::INTERACTIVE_SEQUENCE ) { fixInteractiveSequenceTiming( xNode ); } } break; } case AnimationNodeType::PAR: // some other cut&paste... from AnimationImporter::importAnimationContainer() break; } } catch( const Exception& ) { TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::setNode()"); } } Reference< XAnimationNode > TimeNode::createAndInsert( const XmlFilterBase& rFilter, const OUString& rServiceName, const Reference< XAnimationNode >& rxNode ) { try { Reference< XAnimationNode > xNode( Reference(rFilter.getComponentContext()->getServiceManager(), UNO_QUERY_THROW)->createInstance( rServiceName ), UNO_QUERY_THROW ); Reference< XTimeContainer > xParentContainer( rxNode, UNO_QUERY_THROW ); xParentContainer->appendChild( xNode ); return xNode; } catch( const Exception& ) { TOOLS_INFO_EXCEPTION("oox.ppt", "OOX: exception raised in TimeNode::createAndInsert() trying to create a service " << rServiceName); } return Reference< XAnimationNode >(); } void TimeNode::setId( sal_Int32 nId ) { msId = OUString::number(nId); } void TimeNode::setTo( const Any & aTo ) { maNodeProperties[ NP_TO ] = aTo; } void TimeNode::setFrom( const Any & aFrom ) { maNodeProperties[ NP_FROM ] = aFrom; } void TimeNode::setBy( const Any & aBy ) { maNodeProperties[ NP_BY ] = aBy; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */