diff options
Diffstat (limited to 'slideshow/source/engine/slide')
-rw-r--r-- | slideshow/source/engine/slide/slideimpl.cxx | 44 | ||||
-rw-r--r-- | slideshow/source/engine/slide/targetpropertiescreator.cxx | 365 | ||||
-rw-r--r-- | slideshow/source/engine/slide/targetpropertiescreator.hxx | 47 |
3 files changed, 415 insertions, 41 deletions
diff --git a/slideshow/source/engine/slide/slideimpl.cxx b/slideshow/source/engine/slide/slideimpl.cxx index 1ba3723d2459..08ccce20a810 100644 --- a/slideshow/source/engine/slide/slideimpl.cxx +++ b/slideshow/source/engine/slide/slideimpl.cxx @@ -39,11 +39,8 @@ #include <com/sun/star/presentation/ParagraphTarget.hpp> #include <com/sun/star/presentation/EffectNodeType.hpp> #include <com/sun/star/animations/XAnimationNodeSupplier.hpp> -#include <com/sun/star/animations/XTargetPropertiesCreator.hpp> #include <com/sun/star/drawing/TextAnimationKind.hpp> -#include <animations/animationnodehelper.hxx> - #include <cppuhelper/exc_hlp.hxx> #include <comphelper/anytostring.hxx> @@ -62,6 +59,7 @@ #include "usereventqueue.hxx" #include "userpaintoverlay.hxx" #include "event.hxx" +#include "targetpropertiescreator.hxx" #include "tools.hxx" #include <o3tl/compat_functional.hxx> @@ -849,7 +847,7 @@ bool SlideImpl::implPrefetchShow() // don't block nextEvent() from issuing the next // slide) MainSequenceSearcher aSearcher; - if( ::anim::for_each_childNode( mxRootNode, aSearcher ) ) + if( for_each_childNode( mxRootNode, aSearcher ) ) mbMainSequenceFound = aSearcher.getMainSequence().is(); // import successfully done @@ -966,44 +964,8 @@ bool SlideImpl::applyInitialShapeAttributes( // succeeded } - uno::Reference< animations::XTargetPropertiesCreator > xPropsCreator; - - try - { - ENSURE_OR_RETURN_FALSE( maContext.mxComponentContext.is(), - "SlideImpl::applyInitialShapeAttributes(): Invalid component context" ); - - uno::Reference<lang::XMultiComponentFactory> xFac( - maContext.mxComponentContext->getServiceManager() ); - - xPropsCreator.set( - xFac->createInstanceWithContext( - OUString( - "com.sun.star.animations.TargetPropertiesCreator"), - maContext.mxComponentContext ), - uno::UNO_QUERY_THROW ); - } - catch( uno::RuntimeException& ) - { - throw; - } - catch( uno::Exception& ) - { - OSL_FAIL( - OUStringToOString( - comphelper::anyToString(cppu::getCaughtException()), - RTL_TEXTENCODING_UTF8).getStr() ); - - // could not determine initial shape attributes - this - // is an error, as some effects might then be plainly - // invisible - ENSURE_OR_RETURN_FALSE( false, - "SlideImpl::applyInitialShapeAttributes(): " - "couldn't create TargetPropertiesCreator." ); - } - uno::Sequence< animations::TargetProperties > aProps( - xPropsCreator->createInitialTargetProperties( xRootAnimationNode ) ); + TargetPropertiesCreator::createInitialTargetProperties( xRootAnimationNode ) ); // apply extracted values to our shapes const ::std::size_t nSize( aProps.getLength() ); diff --git a/slideshow/source/engine/slide/targetpropertiescreator.cxx b/slideshow/source/engine/slide/targetpropertiescreator.cxx new file mode 100644 index 000000000000..5902c2980a27 --- /dev/null +++ b/slideshow/source/engine/slide/targetpropertiescreator.cxx @@ -0,0 +1,365 @@ +/* -*- 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 <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/animations/XIterateContainer.hpp> +#include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <com/sun/star/animations/XAnimate.hpp> + +#include <boost/unordered_map.hpp> +#include <vector> + +#include "targetpropertiescreator.hxx" +#include "tools.hxx" + +namespace slideshow +{ +namespace internal +{ + namespace + { + // Vector containing all properties for a given shape + typedef ::std::vector< beans::NamedValue > VectorOfNamedValues; + + /** The hash map key + + This key contains both XShape reference and a paragraph + index, as we somehow have to handle shape and paragraph + targets with the same data structure. + */ + struct ShapeHashKey + { + /// Shape target + uno::Reference< drawing::XShape > mxRef; + + /** Paragraph index. + + If this is a pure shape target, mnParagraphIndex is + set to -1. + */ + sal_Int16 mnParagraphIndex; + + /// Comparison needed for boost::unordered_map + bool operator==( const ShapeHashKey& rRHS ) const + { + return mxRef == rRHS.mxRef && mnParagraphIndex == rRHS.mnParagraphIndex; + } + }; + + // A hash functor for ShapeHashKey objects + struct ShapeKeyHasher + { + ::std::size_t operator()( const ShapeHashKey& rKey ) const + { + // TODO(P2): Maybe a better hash function would be to + // spread mnParagraphIndex to 32 bit: a0b0c0d0e0... Hakmem + // should have a formula. + + // Yes it has: + // x = (x & 0x0000FF00) << 8) | (x >> 8) & 0x0000FF00 | x & 0xFF0000FF; + // x = (x & 0x00F000F0) << 4) | (x >> 4) & 0x00F000F0 | x & 0xF00FF00F; + // x = (x & 0x0C0C0C0C) << 2) | (x >> 2) & 0x0C0C0C0C | x & 0xC3C3C3C3; + // x = (x & 0x22222222) << 1) | (x >> 1) & 0x22222222 | x & 0x99999999; + + // Costs about 17 cycles on a RISC machine with infinite + // instruction level parallelism (~42 basic + // instructions). Thus I truly doubt this pays off... + return reinterpret_cast< ::std::size_t >(rKey.mxRef.get()) ^ (rKey.mnParagraphIndex << 16L); + } + }; + + // A hash map which maps a XShape to the corresponding vector of initial properties + typedef ::boost::unordered_map< ShapeHashKey, VectorOfNamedValues, ShapeKeyHasher > XShapeHash; + + + class NodeFunctor + { + public: + explicit NodeFunctor( XShapeHash& rShapeHash ) : + mrShapeHash( rShapeHash ), + mxTargetShape(), + mnParagraphIndex( -1 ) + { + } + + NodeFunctor( XShapeHash& rShapeHash, + const uno::Reference< drawing::XShape >& rTargetShape, + sal_Int16 nParagraphIndex ) : + mrShapeHash( rShapeHash ), + mxTargetShape( rTargetShape ), + mnParagraphIndex( nParagraphIndex ) + { + } + + void operator()( const uno::Reference< animations::XAnimationNode >& xNode ) const + { + if( !xNode.is() ) + { + OSL_FAIL( "AnimCore: NodeFunctor::operator(): invalid XAnimationNode" ); + return; + } + + uno::Reference< drawing::XShape > xTargetShape( mxTargetShape ); + sal_Int16 nParagraphIndex( mnParagraphIndex ); + + switch( xNode->getType() ) + { + case animations::AnimationNodeType::ITERATE: + { + // extract target shape from iterate node + // (will override the target for all children) + + uno::Reference< animations::XIterateContainer > xIterNode( xNode, + uno::UNO_QUERY ); + + // TODO(E1): I'm not too sure what to expect here... + if( !xIterNode->getTarget().hasValue() ) + { + OSL_FAIL( "animcore: NodeFunctor::operator(): no target on ITERATE node" ); + return; + } + + xTargetShape.set( xIterNode->getTarget(), + uno::UNO_QUERY ); + + if( !xTargetShape.is() ) + { + ::com::sun::star::presentation::ParagraphTarget aTarget; + + // no shape provided. Maybe a ParagraphTarget? + if( !(xIterNode->getTarget() >>= aTarget) ) + { + OSL_FAIL( "animcore: NodeFunctor::operator(): could not extract any " + "target information" ); + return; + } + + xTargetShape = aTarget.Shape; + nParagraphIndex = aTarget.Paragraph; + + if( !xTargetShape.is() ) + { + OSL_FAIL( "animcore: NodeFunctor::operator(): invalid shape in ParagraphTarget" ); + return; + } + } + } + // FALLTHROUGH intended + case animations::AnimationNodeType::PAR: + // FALLTHROUGH intended + case animations::AnimationNodeType::SEQ: + { + NodeFunctor aFunctor( mrShapeHash, + xTargetShape, + nParagraphIndex ); + if( !for_each_childNode( xNode, aFunctor ) ) + { + OSL_FAIL( "AnimCore: NodeFunctor::operator(): child node iteration failed, " + "or extraneous container nodes encountered" ); + } + } + break; + + case animations::AnimationNodeType::CUSTOM: + // FALLTHROUGH intended + case animations::AnimationNodeType::ANIMATE: + // FALLTHROUGH intended + case animations::AnimationNodeType::ANIMATEMOTION: + // FALLTHROUGH intended + case animations::AnimationNodeType::ANIMATECOLOR: + // FALLTHROUGH intended + case animations::AnimationNodeType::ANIMATETRANSFORM: + // FALLTHROUGH intended + case animations::AnimationNodeType::TRANSITIONFILTER: + // FALLTHROUGH intended + case animations::AnimationNodeType::AUDIO: + // FALLTHROUGH intended + /*default: + // ignore this node, no valuable content for now. + break;*/ + + case animations::AnimationNodeType::SET: + { + // evaluate set node content + uno::Reference< animations::XAnimate > xAnimateNode( xNode, + uno::UNO_QUERY ); + + if( !xAnimateNode.is() ) + break; // invalid node + + // determine target shape (if any) + ShapeHashKey aTarget; + if( xTargetShape.is() ) + { + // override target shape with parent-supplied + aTarget.mxRef = xTargetShape; + aTarget.mnParagraphIndex = nParagraphIndex; + } + else + { + // no parent-supplied target, retrieve + // node target + if( (xAnimateNode->getTarget() >>= aTarget.mxRef) ) + { + // pure shape target - set paragraph + // index to magic + aTarget.mnParagraphIndex = -1; + } + else + { + // not a pure shape target - maybe a + // ParagraphTarget? + presentation::ParagraphTarget aUnoTarget; + + if( !(xAnimateNode->getTarget() >>= aUnoTarget) ) + { + OSL_FAIL( "AnimCore: NodeFunctor::operator(): unknown target type encountered" ); + break; + } + + aTarget.mxRef = aUnoTarget.Shape; + aTarget.mnParagraphIndex = aUnoTarget.Paragraph; + } + } + + if( !aTarget.mxRef.is() ) + { + OSL_FAIL( "AnimCore: NodeFunctor::operator(): Found target, but XShape is NULL" ); + break; // invalid target XShape + } + + // check whether we already have an entry for + // this target (we only take the first set + // effect for every shape) + XShapeHash::const_iterator aIter; + if( (aIter=mrShapeHash.find( aTarget )) != mrShapeHash.end() ) + break; // already an entry in existence for given XShape + + // if this is an appear effect, hide shape + // initially. This is currently the only place + // where a shape effect influences shape + // attributes outside it's effective duration. + sal_Bool bVisible( sal_False ); + if( xAnimateNode->getAttributeName().equalsIgnoreAsciiCase("visibility") ) + { + + uno::Any aAny( xAnimateNode->getTo() ); + + // try to extract bool value + if( !(aAny >>= bVisible) ) + { + // try to extract string + OUString aString; + if( (aAny >>= aString) ) + { + // we also take the strings "true" and "false", + // as well as "on" and "off" here + if( aString.equalsIgnoreAsciiCase("true") || + aString.equalsIgnoreAsciiCase("on") ) + { + bVisible = sal_True; + } + if( aString.equalsIgnoreAsciiCase("false") || + aString.equalsIgnoreAsciiCase("off") ) + { + bVisible = sal_False; + } + } + } + } + // target is set the 'visible' value, + // so we should record the opposite value + mrShapeHash.insert( + XShapeHash::value_type( + aTarget, + VectorOfNamedValues( + 1, + beans::NamedValue( + //xAnimateNode->getAttributeName(), + OUString("visibility"), + uno::makeAny( !bVisible ) ) ) ) ); + break; + } + } + } + + private: + XShapeHash& mrShapeHash; + uno::Reference< drawing::XShape > mxTargetShape; + sal_Int16 mnParagraphIndex; + }; + } + + uno::Sequence< animations::TargetProperties > SAL_CALL TargetPropertiesCreator::createInitialTargetProperties + ( + const uno::Reference< animations::XAnimationNode >& xRootNode + ) //throw (uno::RuntimeException, std::exception) + { + // scan all nodes for visibility changes, and record first + // 'visibility=true' for each shape + XShapeHash aShapeHash( 101 ); + + NodeFunctor aFunctor( aShapeHash ); + + // TODO(F1): Maybe limit functor application to main sequence + // alone (CL said something that shape visibility is only + // affected by effects in the main sequence for PPT). + + // OTOH, client code can pass us only the main sequence (which + // it actually does right now, for the slideshow implementation). + aFunctor( xRootNode ); + + // output to result sequence + uno::Sequence< animations::TargetProperties > aRes( aShapeHash.size() ); + + ::std::size_t nCurrIndex(0); + XShapeHash::const_iterator aCurr( aShapeHash.begin() ); + const XShapeHash::const_iterator aEnd ( aShapeHash.end() ); + while( aCurr != aEnd ) + { + animations::TargetProperties& rCurrProps( aRes[ nCurrIndex++ ] ); + + if( aCurr->first.mnParagraphIndex == -1 ) + { + rCurrProps.Target = uno::makeAny( aCurr->first.mxRef ); + } + else + { + rCurrProps.Target = uno::makeAny( + presentation::ParagraphTarget( + aCurr->first.mxRef, + aCurr->first.mnParagraphIndex ) ); + } + + rCurrProps.Properties = ::comphelper::containerToSequence( aCurr->second ); + + ++aCurr; + } + + return aRes; + } + +} // namespace internal +} // namespace slideshow + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/slide/targetpropertiescreator.hxx b/slideshow/source/engine/slide/targetpropertiescreator.hxx new file mode 100644 index 000000000000..6c6bef6fad4c --- /dev/null +++ b/slideshow/source/engine/slide/targetpropertiescreator.hxx @@ -0,0 +1,47 @@ +/* -*- 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 <com/sun/star/animations/TargetProperties.hpp> + +#include <comphelper/broadcasthelper.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> +#include <comphelper/sequence.hxx> + +using namespace ::com::sun::star; + +namespace slideshow +{ + namespace internal + { + class TargetPropertiesCreator : public ::comphelper::OBaseMutex + { + public: + static uno::Sequence< animations::TargetProperties > SAL_CALL createInitialTargetProperties( const uno::Reference< animations::XAnimationNode >& rootNode ); + + private: + // default: disabled copy/assignment + TargetPropertiesCreator(const TargetPropertiesCreator&); + TargetPropertiesCreator& operator=( const TargetPropertiesCreator& ); + }; + + } // namespace internal +} // namespace slideshow + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |