diff options
Diffstat (limited to 'slideshow/source/engine/animationnodes/animationbasenode.cxx')
-rw-r--r-- | slideshow/source/engine/animationnodes/animationbasenode.cxx | 492 |
1 files changed, 0 insertions, 492 deletions
diff --git a/slideshow/source/engine/animationnodes/animationbasenode.cxx b/slideshow/source/engine/animationnodes/animationbasenode.cxx deleted file mode 100644 index 10700502d..000000000 --- a/slideshow/source/engine/animationnodes/animationbasenode.cxx +++ /dev/null @@ -1,492 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * 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_slideshow.hxx" - -// must be first -#include <canvas/debug.hxx> -#include <canvas/verbosetrace.hxx> -#include <cppuhelper/exc_hlp.hxx> -#include <comphelper/anytostring.hxx> -#include <com/sun/star/presentation/ParagraphTarget.hpp> -#include <com/sun/star/animations/Timing.hpp> -#include <com/sun/star/animations/AnimationAdditiveMode.hpp> -#include <com/sun/star/presentation/ShapeAnimationSubType.hpp> - -#include "nodetools.hxx" -#include "doctreenode.hxx" -#include "animationbasenode.hxx" -#include "delayevent.hxx" -#include "framerate.hxx" - -#include <boost/bind.hpp> -#include <boost/optional.hpp> -#include <algorithm> - -using namespace com::sun::star; - -namespace slideshow { -namespace internal { - -AnimationBaseNode::AnimationBaseNode( - const uno::Reference< animations::XAnimationNode >& xNode, - const BaseContainerNodeSharedPtr& rParent, - const NodeContext& rContext ) - : BaseNode( xNode, rParent, rContext ), - mxAnimateNode( xNode, uno::UNO_QUERY_THROW ), - maAttributeLayerHolder(), - maSlideSize( rContext.maSlideSize ), - mpActivity(), - mpShape(), - mpShapeSubset(), - mpSubsetManager(rContext.maContext.mpSubsettableShapeManager), - mbIsIndependentSubset( rContext.mbIsIndependentSubset ) -{ - // extract native node targets - // =========================== - - // plain shape target - uno::Reference< drawing::XShape > xShape( mxAnimateNode->getTarget(), - uno::UNO_QUERY ); - - // distinguish 5 cases: - // - // - plain shape target - // (NodeContext.mpMasterShapeSubset full set) - // - // - parent-generated subset (generate an - // independent subset) - // - // - parent-generated subset from iteration - // (generate a dependent subset) - // - // - XShape target at the XAnimatioNode (generate - // a plain shape target) - // - // - ParagraphTarget target at the XAnimationNode - // (generate an independent shape subset) - if( rContext.mpMasterShapeSubset ) - { - if( rContext.mpMasterShapeSubset->isFullSet() ) - { - // case 1: plain shape target from parent - mpShape = rContext.mpMasterShapeSubset->getSubsetShape(); - } - else - { - // cases 2 & 3: subset shape - mpShapeSubset = rContext.mpMasterShapeSubset; - } - } - else - { - // no parent-provided shape, try to extract - // from XAnimationNode - cases 4 and 5 - - if( xShape.is() ) - { - mpShape = lookupAttributableShape( getContext().mpSubsettableShapeManager, - xShape ); - } - else - { - // no shape provided. Maybe a ParagraphTarget? - presentation::ParagraphTarget aTarget; - - if( !(mxAnimateNode->getTarget() >>= aTarget) ) - ENSURE_OR_THROW( - false, "could not extract any target information" ); - - xShape = aTarget.Shape; - - ENSURE_OR_THROW( xShape.is(), "invalid shape in ParagraphTarget" ); - - mpShape = lookupAttributableShape( getContext().mpSubsettableShapeManager, - xShape ); - - // NOTE: For shapes with ParagraphTarget, we ignore - // the SubItem property. We implicitely assume that it - // is set to ONLY_TEXT. - OSL_ENSURE( - mxAnimateNode->getSubItem() == - presentation::ShapeAnimationSubType::ONLY_TEXT || - mxAnimateNode->getSubItem() == - presentation::ShapeAnimationSubType::AS_WHOLE, - "ParagraphTarget given, but subitem not AS_TEXT or AS_WHOLE? " - "Make up your mind, I'll ignore the subitem." ); - - // okay, found a ParagraphTarget with a valid XShape. Does the shape - // provide the given paragraph? - const DocTreeNode& rTreeNode( - mpShape->getTreeNodeSupplier().getTreeNode( - aTarget.Paragraph, - DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) ); - - // CAUTION: the creation of the subset shape - // _must_ stay in the node constructor, since - // Slide::prefetchShow() initializes shape - // attributes right after animation import (or - // the Slide class must be changed). - mpShapeSubset.reset( - new ShapeSubset( mpShape, - rTreeNode, - mpSubsetManager )); - - // Override NodeContext, and flag this node as - // a special independent subset one. This is - // important when applying initial attributes: - // independent shape subsets must be setup - // when the slide starts, since they, as their - // name suggest, can have state independent to - // the master shape. The following example - // might illustrate that: a master shape has - // no effect, one of the text paragraphs - // within it has an appear effect. Now, the - // respective paragraph must be invisible when - // the slide is initially shown, and become - // visible only when the effect starts. - mbIsIndependentSubset = true; - - // already enable subset right here, the - // setup of initial shape attributes of - // course needs the subset shape - // generated, to apply e.g. visibility - // changes. - mpShapeSubset->enableSubsetShape(); - } - } -} - -void AnimationBaseNode::dispose() -{ - if (mpActivity) { - mpActivity->dispose(); - mpActivity.reset(); - } - - maAttributeLayerHolder.reset(); - mxAnimateNode.clear(); - mpShape.reset(); - mpShapeSubset.reset(); - - BaseNode::dispose(); -} - -bool AnimationBaseNode::init_st() -{ - // if we've still got an old activity lying around, dispose it: - if (mpActivity) { - mpActivity->dispose(); - mpActivity.reset(); - } - - // note: actually disposing the activity too early might cause problems, - // because on dequeued() it calls endAnimation(pAnim->end()), thus ending - // animation _after_ last screen update. - // review that end() is properly called (which calls endAnimation(), too). - - try { - // TODO(F2): For restart functionality, we must regenerate activities, - // since they are not able to reset their state (or implement _that_) - mpActivity = createActivity(); - } - catch (uno::Exception const&) { - OSL_FAIL( rtl::OUStringToOString( - comphelper::anyToString(cppu::getCaughtException()), - RTL_TEXTENCODING_UTF8 ) ); - // catch and ignore. We later handle empty activities, but for - // other nodes to function properly, the core functionality of - // this node must remain up and running. - } - return true; -} - -bool AnimationBaseNode::resolve_st() -{ - // enable shape subset for automatically generated - // subsets. Independent subsets are already setup - // during construction time. Doing it only here - // saves us a lot of sprites and shapes lying - // around. This is especially important for - // character-wise iterations, since the shape - // content (e.g. thousands of characters) would - // otherwise be painted character-by-character. - if (isDependentSubsettedShape() && mpShapeSubset) { - mpShapeSubset->enableSubsetShape(); - } - return true; -} - -void AnimationBaseNode::activate_st() -{ - // create new attribute layer - maAttributeLayerHolder.createAttributeLayer( getShape() ); - - ENSURE_OR_THROW( maAttributeLayerHolder.get(), - "Could not generate shape attribute layer" ); - - // TODO(Q2): This affects the way mpActivity - // works, but is performed here because of - // locality (we're fiddling with the additive mode - // here, anyway, and it's the only place where we - // do). OTOH, maybe the complete additive mode - // setup should be moved to the activities. - - // for simple by-animations, the SMIL spec - // requires us to emulate "0,by-value" value list - // behaviour, with additive mode forced to "sum", - // no matter what the input is - // (http://www.w3.org/TR/smil20/animation.html#adef-by). - if( mxAnimateNode->getBy().hasValue() && - !mxAnimateNode->getTo().hasValue() && - !mxAnimateNode->getFrom().hasValue() ) - { - // force attribute mode to REPLACE (note the - // subtle discrepancy to the paragraph above, - // where SMIL requires SUM. This is internally - // handled by the FromToByActivity, and is - // because otherwise DOM values would not be - // handled correctly: the activity cannot - // determine whether an - // Activity::getUnderlyingValue() yields the - // DOM value, or already a summed-up conglomerate) - // - // Note that this poses problems with our - // hybrid activity duration (time or min number of frames), - // since if activities - // exceed their duration, wrong 'by' start - // values might arise ('Laser effect') - maAttributeLayerHolder.get()->setAdditiveMode( - animations::AnimationAdditiveMode::REPLACE ); - } - else - { - // apply additive mode to newly created Attribute layer - maAttributeLayerHolder.get()->setAdditiveMode( - mxAnimateNode->getAdditive() ); - } - - // fake normal animation behaviour, even if we - // show nothing. This is the appropriate way to - // handle errors on Activity generation, because - // maybe all other effects on the slide are - // correctly initialized (but won't run, if we - // signal an error here) - if (mpActivity) { - // supply Activity (and the underlying Animation) with - // it's AttributeLayer, to perform the animation on - mpActivity->setTargets( getShape(), maAttributeLayerHolder.get() ); - - // add to activities queue - getContext().mrActivitiesQueue.addActivity( mpActivity ); - } - else { - // Actually, DO generate the event for empty activity, - // to keep the chain of animations running - BaseNode::scheduleDeactivationEvent(); - } -} - -void AnimationBaseNode::deactivate_st( NodeState eDestState ) -{ - if (eDestState == FROZEN) { - if (mpActivity) - mpActivity->end(); - } - - if (isDependentSubsettedShape()) { - // for dependent subsets, remove subset shape - // from layer, re-integrate subsetted part - // back into original shape. For independent - // subsets, we cannot make any assumptions - // about subset attribute state relative to - // master shape, thus, have to keep it. This - // will effectively re-integrate the subsetted - // part into the original shape (whose - // animation will hopefully have ended, too) - - // this statement will save a whole lot of - // sprites for iterated text effects, since - // those sprites will only exist during the - // actual lifetime of the effects - if (mpShapeSubset) { - mpShapeSubset->disableSubsetShape(); - } - } - - if (eDestState == ENDED) { - - // no shape anymore, no layer needed: - maAttributeLayerHolder.reset(); - - if (! isDependentSubsettedShape()) { - - // for all other shapes, removing the - // attribute layer quite possibly changes - // shape display. Thus, force update - AttributableShapeSharedPtr const pShape( getShape() ); - - // don't anybody dare to check against - // pShape->isVisible() here, removing the - // attribute layer might actually make the - // shape invisible! - getContext().mpSubsettableShapeManager->notifyShapeUpdate( pShape ); - } - - if (mpActivity) { - // kill activity, if still running - mpActivity->dispose(); - mpActivity.reset(); - } - } -} - -bool AnimationBaseNode::hasPendingAnimation() const -{ - // TODO(F1): This might not always be true. Are there 'inactive' - // animation nodes? - return true; -} - -#if defined(VERBOSE) && defined(DBG_UTIL) -void AnimationBaseNode::showState() const -{ - BaseNode::showState(); - - VERBOSE_TRACE( "AnimationBaseNode info: independent subset=%s", - mbIsIndependentSubset ? "y" : "n" ); -} -#endif - -ActivitiesFactory::CommonParameters -AnimationBaseNode::fillCommonParameters() const -{ - double nDuration = 0.0; - - // TODO(F3): Duration/End handling is barely there - if( !(mxAnimateNode->getDuration() >>= nDuration) ) { - mxAnimateNode->getEnd() >>= nDuration; // Wah. - } - - // minimal duration we fallback to (avoid 0 here!) - nDuration = ::std::max( 0.001, nDuration ); - - const bool bAutoReverse( mxAnimateNode->getAutoReverse() ); - - boost::optional<double> aRepeats; - double nRepeats = 0; - if( (mxAnimateNode->getRepeatCount() >>= nRepeats) ) { - aRepeats.reset( nRepeats ); - } - else { - if( (mxAnimateNode->getRepeatDuration() >>= nRepeats) ) { - // when repeatDuration is given, - // autoreverse does _not_ modify the - // active duration. Thus, calc repeat - // count with already adapted simple - // duration (twice the specified duration) - - // convert duration back to repeat counts - if( bAutoReverse ) - aRepeats.reset( nRepeats / (2.0 * nDuration) ); - else - aRepeats.reset( nRepeats / nDuration ); - } - else { - // no double value for both values - Timing::INDEFINITE? - animations::Timing eTiming; - - if( !(mxAnimateNode->getRepeatDuration() >>= eTiming) || - eTiming != animations::Timing_INDEFINITE ) - { - if( !(mxAnimateNode->getRepeatCount() >>= eTiming) || - eTiming != animations::Timing_INDEFINITE ) - { - // no indefinite timing, no other values given - - // use simple run, i.e. repeat of 1.0 - aRepeats.reset( 1.0 ); - } - } - } - } - - // calc accel/decel: - double nAcceleration = 0.0; - double nDeceleration = 0.0; - BaseNodeSharedPtr const pSelf( getSelf() ); - for ( boost::shared_ptr<BaseNode> pNode( pSelf ); - pNode; pNode = pNode->getParentNode() ) - { - uno::Reference<animations::XAnimationNode> const xAnimationNode( - pNode->getXAnimationNode() ); - nAcceleration = std::max( nAcceleration, - xAnimationNode->getAcceleration() ); - nDeceleration = std::max( nDeceleration, - xAnimationNode->getDecelerate() ); - } - - EventSharedPtr pEndEvent; - if (pSelf) { - pEndEvent = makeEvent( - boost::bind( &AnimationNode::deactivate, pSelf ), - "AnimationBaseNode::deactivate"); - } - - // Calculate the minimum frame count that depends on the duration and - // the minimum frame count. - const sal_Int32 nMinFrameCount (basegfx::clamp<sal_Int32>( - basegfx::fround(nDuration * FrameRate::MinimumFramesPerSecond), 1, 10)); - - return ActivitiesFactory::CommonParameters( - pEndEvent, - getContext().mrEventQueue, - getContext().mrActivitiesQueue, - nDuration, - nMinFrameCount, - bAutoReverse, - aRepeats, - nAcceleration, - nDeceleration, - getShape(), - getSlideSize()); -} - -AttributableShapeSharedPtr AnimationBaseNode::getShape() const -{ - // any subsetting at all? - if (mpShapeSubset) - return mpShapeSubset->getSubsetShape(); - else - return mpShape; // nope, plain shape always -} - -} // namespace internal -} // namespace slideshow - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |