diff options
Diffstat (limited to '')
-rw-r--r-- | slideshow/source/engine/transitions/slidetransitionfactory.cxx | 1110 |
1 files changed, 1110 insertions, 0 deletions
diff --git a/slideshow/source/engine/transitions/slidetransitionfactory.cxx b/slideshow/source/engine/transitions/slidetransitionfactory.cxx new file mode 100644 index 000000000..3ec2c8089 --- /dev/null +++ b/slideshow/source/engine/transitions/slidetransitionfactory.cxx @@ -0,0 +1,1110 @@ +/* -*- 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 <tools/diagnose_ex.h> +#include <sal/log.hxx> + +#include <basegfx/matrix/b2dhommatrix.hxx> + +#include <cppcanvas/customsprite.hxx> + +#include <com/sun/star/animations/TransitionType.hpp> +#include <com/sun/star/animations/TransitionSubType.hpp> + +#include "slidechangebase.hxx" +#include <transitionfactory.hxx> +#include "transitionfactorytab.hxx" +#include "parametricpolypolygonfactory.hxx" +#include "clippingfunctor.hxx" +#include "combtransition.hxx" +#include <tools.hxx> +#include <memory> + + +/*************************************************** + *** *** + *** Slide Transition Effects *** + *** *** + ***************************************************/ + +using namespace com::sun::star; + +namespace slideshow::internal { + +namespace { + +// helper methods +// ============================================= + +void fillPage( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + const ::basegfx::B2DSize& rPageSizePixel, + const RGBColor& rFillColor ) +{ + // need to render without any transformation (we + // assume rPageSizePixel to represent device units) + const ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( + rDestinationCanvas->clone() ); + pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() ); + + // TODO(F2): Properly respect clip here. + // Might have to be transformed, too. + const ::basegfx::B2DHomMatrix aViewTransform( + rDestinationCanvas->getTransformation() ); + const ::basegfx::B2DPoint aOutputPosPixel( + aViewTransform * ::basegfx::B2DPoint() ); + + fillRect( pDevicePixelCanvas, + ::basegfx::B2DRectangle( + aOutputPosPixel.getX(), + aOutputPosPixel.getY(), + aOutputPosPixel.getX() + rPageSizePixel.getX(), + aOutputPosPixel.getY() + rPageSizePixel.getY() ), + rFillColor.getIntegerColor() ); +} + +class PluginSlideChange: public SlideChangeBase +{ + struct TransitionViewPair { + uno::Reference<presentation::XTransition> mxTransition; + UnoViewSharedPtr mpView; + + TransitionViewPair( uno::Reference<presentation::XTransition> const & xTransition, const UnoViewSharedPtr& rView ) + : mxTransition(xTransition), mpView(rView) + { + } + + ~TransitionViewPair() + { + mxTransition.clear(); + mpView.reset(); + } + + void update( double t ) + { + mxTransition->update( t ); + } + }; + +public: + /** Create a new SlideChanger, for the given leaving and + entering slide bitmaps, which uses super secret OpenGL + stuff. + */ + PluginSlideChange( sal_Int16 nTransitionType, + sal_Int16 nTransitionSubType, + const RGBColor& rTransitionFadeColor, + std::optional<SlideSharedPtr> const& leavingSlide_, + const SlideSharedPtr& pEnteringSlide, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + const uno::Reference< + presentation::XTransitionFactory>& xFactory, + const SoundPlayerSharedPtr& pSoundPlayer, + EventMultiplexer& rEventMultiplexer) : + SlideChangeBase( leavingSlide_, + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer ), + maTransitions(), + mbSuccess( false ), + mnTransitionType( nTransitionType ), + mnTransitionSubType( nTransitionSubType ), + mnTransitionFadeColor( rTransitionFadeColor ), + mxFactory( xFactory ) + { + // create one transition per view + for( const auto& rView : rViewContainer ) + { + if( !addTransition( rView ) ) + return; + + ENSURE_OR_THROW(maTransitions.back() && maTransitions.back()->mxTransition.is(), + "Failed to create plugin transition"); + } + mbSuccess = true; + } + + virtual ~PluginSlideChange() override + { + mxFactory.clear(); + } + + bool addTransition( const UnoViewSharedPtr& rView ) + { + uno::Reference<presentation::XTransition> rTransition = mxFactory->createTransition( + mnTransitionType, + mnTransitionSubType, + RGBAColor2UnoColor( mnTransitionFadeColor.getIntegerColor()), + rView->getUnoView(), + getLeavingBitmap(ViewEntry(rView))->getXBitmap(), + getEnteringBitmap(ViewEntry(rView))->getXBitmap() ); + + if( rTransition.is() ) + maTransitions.emplace_back( new TransitionViewPair( rTransition, rView ) ); + else + return false; + + return true; + } + + virtual bool operator()( double t ) override + { + for( const auto& pTransition : maTransitions ) + pTransition->update( t ); + return true; + } + + bool Success() + { + return mbSuccess; + } + + // ViewEventHandler + virtual void viewAdded( const UnoViewSharedPtr& rView ) override + { + SAL_INFO("slideshow", "PluginSlideChange viewAdded"); + SlideChangeBase::viewAdded( rView ); + + for( const auto& pCurrView : maTransitions ) + { + if( pCurrView->mpView == rView ) + return; + } + + SAL_INFO("slideshow", "need to be added" ); + addTransition( rView ); + } + + virtual void viewRemoved( const UnoViewSharedPtr& rView ) override + { + SAL_INFO("slideshow", "PluginSlideChange viewRemoved"); + SlideChangeBase::viewRemoved( rView ); + + auto aIter = std::find_if(maTransitions.begin(), maTransitions.end(), + [&rView](const std::unique_ptr<TransitionViewPair>& rxTransition) { return rxTransition->mpView == rView; }); + if (aIter != maTransitions.end()) + { + SAL_INFO("slideshow", "view removed" ); + maTransitions.erase( aIter ); + } + } + + virtual void viewChanged( const UnoViewSharedPtr& rView ) override + { + SAL_INFO("slideshow", "PluginSlideChange viewChanged"); + SlideChangeBase::viewChanged( rView ); + + for( const auto& pCurrView : maTransitions ) + { + if( pCurrView->mpView == rView ) + { + SAL_INFO("slideshow", "view changed" ); + pCurrView->mxTransition->viewChanged( rView->getUnoView(), + getLeavingBitmap(ViewEntry(rView))->getXBitmap(), + getEnteringBitmap(ViewEntry(rView))->getXBitmap() ); + } + else + SAL_INFO("slideshow", "view did not change" ); + } + } + + virtual void viewsChanged() override + { + SAL_INFO("slideshow", "PluginSlideChange viewsChanged"); + SlideChangeBase::viewsChanged(); + + for( const auto& pCurrView : maTransitions ) + { + SAL_INFO("slideshow", "view changed" ); + UnoViewSharedPtr pView = pCurrView->mpView; + pCurrView->mxTransition->viewChanged( pView->getUnoView(), + getLeavingBitmap(ViewEntry(pView))->getXBitmap(), + getEnteringBitmap(ViewEntry(pView))->getXBitmap() ); + } + } + +private: + // One transition object per view + std::vector< std::unique_ptr<TransitionViewPair> > maTransitions; + + // bool + bool mbSuccess; + + sal_Int16 mnTransitionType; + sal_Int16 mnTransitionSubType; + RGBColor mnTransitionFadeColor; + + uno::Reference<presentation::XTransitionFactory> mxFactory; +}; + +class ClippedSlideChange : public SlideChangeBase +{ +public: + /** Create a new SlideChanger, for the given leaving and + entering slide bitmaps, which applies the given clip + polygon. + */ + ClippedSlideChange( + const SlideSharedPtr& pEnteringSlide, + const ParametricPolyPolygonSharedPtr& rPolygon, + const TransitionInfo& rTransitionInfo, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + EventMultiplexer& rEventMultiplexer, + bool bDirectionForward, + const SoundPlayerSharedPtr& pSoundPlayer ) : + SlideChangeBase( + // leaving bitmap is empty, we're leveraging the fact that the + // old slide is still displayed in the background: + std::optional<SlideSharedPtr>(), + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer ), + maClippingFunctor( rPolygon, + rTransitionInfo, + bDirectionForward, + true ) + {} + + virtual void performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; + + virtual void performOut( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; + +private: + ClippingFunctor maClippingFunctor; +}; + +void ClippedSlideChange::performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/, + double t ) +{ + // #i46602# Better work in device coordinate space here, + // otherwise, we too easily suffer from roundoffs. Apart from + // that, getEnteringSizePixel() _guarantees_ to cover the whole + // slide bitmap. There's a catch, though: this removes any effect + // of the view transformation (e.g. rotation) from the transition. + rSprite->setClipPixel( + maClippingFunctor( t, + ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) ) ); +} + +void ClippedSlideChange::performOut( + const ::cppcanvas::CustomSpriteSharedPtr& /*rSprite*/, + const ViewEntry& /*rViewEntry*/, + const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/, + double /*t*/ ) +{ + // not needed here +} + + +class FadingSlideChange : public SlideChangeBase +{ +public: + /** Create a new SlideChanger, for the given leaving and + entering slides, which applies a fade effect. + */ + FadingSlideChange( + std::optional<SlideSharedPtr> const & leavingSlide, + const SlideSharedPtr& pEnteringSlide, + std::optional<RGBColor> const& rFadeColor, + const SoundPlayerSharedPtr& pSoundPlayer, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + EventMultiplexer& rEventMultiplexer ) + : SlideChangeBase( leavingSlide, + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer ), + maFadeColor( rFadeColor ) + {} + + virtual void prepareForRun( + const ViewEntry& rViewEntry, + const cppcanvas::CanvasSharedPtr& rDestinationCanvas ) override; + + virtual void performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; + + virtual void performOut( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; + +private: + const std::optional< RGBColor > maFadeColor; +}; + +void FadingSlideChange::prepareForRun( + const ViewEntry& rViewEntry, + const cppcanvas::CanvasSharedPtr& rDestinationCanvas ) +{ + if ( maFadeColor ) + { + // clear page to given fade color. 'Leaving' slide is + // painted atop of that, but slowly fading out. + fillPage( rDestinationCanvas, + ::basegfx::B2DSize( getEnteringSlideSizePixel( rViewEntry.mpView ) ), + *maFadeColor ); + } +} + +void FadingSlideChange::performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& /*rViewEntry*/, + const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/, + double t ) +{ + ENSURE_OR_THROW( + rSprite, + "FadingSlideChange::performIn(): Invalid sprite" ); + + if( maFadeColor ) + // After half of the active time, fade in new slide + rSprite->setAlpha( t > 0.5 ? 2.0*(t-0.5) : 0.0 ); + else + // Fade in new slide over full active time + rSprite->setAlpha( t ); +} + +void FadingSlideChange::performOut( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& /* rViewEntry */, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) +{ + ENSURE_OR_THROW( + rSprite, + "FadingSlideChange::performOut(): Invalid sprite" ); + ENSURE_OR_THROW( + rDestinationCanvas, + "FadingSlideChange::performOut(): Invalid dest canvas" ); + + // only needed for color fades + if( maFadeColor ) + { + // Until half of the active time, fade out old + // slide. After half of the active time, old slide + // will be invisible. + rSprite->setAlpha( t > 0.5 ? 0.0 : 2.0*(0.5-t) ); + } +} + +class CutSlideChange : public SlideChangeBase +{ +public: + /** Create a new SlideChanger, for the given leaving and + entering slides, which applies a cut effect. + */ + CutSlideChange( + std::optional<SlideSharedPtr> const & leavingSlide, + const SlideSharedPtr& pEnteringSlide, + const RGBColor& rFadeColor, + const SoundPlayerSharedPtr& pSoundPlayer, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + EventMultiplexer& rEventMultiplexer ) + : SlideChangeBase( leavingSlide, + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer ), + maFadeColor( rFadeColor ) + {} + + virtual void prepareForRun( + const ViewEntry& rViewEntry, + const cppcanvas::CanvasSharedPtr& rDestinationCanvas ) override; + + virtual void performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; + + virtual void performOut( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; + +private: + RGBColor maFadeColor; +}; + +void CutSlideChange::prepareForRun( + const ViewEntry& rViewEntry, + const cppcanvas::CanvasSharedPtr& rDestinationCanvas ) +{ + // clear page to given fade color. 'Leaving' slide is + // painted atop of that + fillPage( rDestinationCanvas, + ::basegfx::B2DSize( getEnteringSlideSizePixel( rViewEntry.mpView ) ), + maFadeColor ); +} + +void CutSlideChange::performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& /*rViewEntry*/, + const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/, + double t ) +{ + ENSURE_OR_THROW( + rSprite, + "CutSlideChange::performIn(): Invalid sprite" ); + + // After 2/3rd of the active time, display new slide + rSprite->setAlpha( t > 2/3.0 ? 1.0 : 0.0 ); +} + +void CutSlideChange::performOut( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& /* rViewEntry */, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) +{ + ENSURE_OR_THROW( + rSprite, + "CutSlideChange::performOut(): Invalid sprite" ); + ENSURE_OR_THROW( + rDestinationCanvas, + "CutSlideChange::performOut(): Invalid dest canvas" ); + + // Until 1/3rd of the active time, display old slide. + rSprite->setAlpha( t > 1/3.0 ? 0.0 : 1.0 ); +} + +class MovingSlideChange : public SlideChangeBase +{ + /// Direction vector for leaving slide, + const ::basegfx::B2DVector maLeavingDirection; + + /// Direction vector for entering slide, + const ::basegfx::B2DVector maEnteringDirection; + +public: + /** Create a new SlideChanger, for the given entering slide + bitmaps, which performs a moving slide change effect + + @param rLeavingDirection + Direction vector. The move is performed along this + direction vector, starting at a position where the leaving + slide is fully visible, and ending at a position where the + leaving slide is just not visible. The vector must have + unit length. + + @param rEnteringDirection + Direction vector. The move is performed along this + direction vector, starting at a position where the + entering slide is just not visible, and ending at the + final slide position. The vector must have unit length. + */ + MovingSlideChange( + const std::optional<SlideSharedPtr>& leavingSlide, + const SlideSharedPtr& pEnteringSlide, + const SoundPlayerSharedPtr& pSoundPlayer, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + EventMultiplexer& rEventMultiplexer, + const ::basegfx::B2DVector& rLeavingDirection, + const ::basegfx::B2DVector& rEnteringDirection ) + : SlideChangeBase( + leavingSlide, pEnteringSlide, pSoundPlayer, + rViewContainer, rScreenUpdater, rEventMultiplexer, + // Optimization: when leaving bitmap is given, + // but it does not move, don't create sprites for it, + // we simply paint it once at startup: + !rLeavingDirection.equalZero() /* bCreateLeavingSprites */, + !rEnteringDirection.equalZero() /* bCreateEnteringSprites */ ), + // TODO(F1): calc correct length of direction + // vector. Directions not strictly horizontal or vertical + // must travel a longer distance. + maLeavingDirection( rLeavingDirection ), + // TODO(F1): calc correct length of direction + // vector. Directions not strictly horizontal or vertical + // must travel a longer distance. + maEnteringDirection( rEnteringDirection ) + {} + + virtual void prepareForRun( + const ViewEntry& rViewEntry, + const cppcanvas::CanvasSharedPtr& rDestinationCanvas ) override; + + virtual void performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; + + virtual void performOut( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) override; +}; + +void MovingSlideChange::prepareForRun( + const ViewEntry& rViewEntry, + const cppcanvas::CanvasSharedPtr& rDestinationCanvas ) +{ + if ( maLeavingDirection.equalZero() ) + renderBitmap( getLeavingBitmap( rViewEntry ), rDestinationCanvas ); + else if ( maEnteringDirection.equalZero() ) + renderBitmap( getEnteringBitmap( rViewEntry ), rDestinationCanvas ); +} + +void MovingSlideChange::performIn( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) +{ + // intro sprite moves: + + ENSURE_OR_THROW( + rSprite, + "MovingSlideChange::performIn(): Invalid sprite" ); + ENSURE_OR_THROW( + rDestinationCanvas, + "MovingSlideChange::performIn(): Invalid dest canvas" ); + + // TODO(F1): This does not account for non-translational + // transformations! If the canvas is rotated, we still + // move the sprite unrotated (which might or might not + // produce the intended effect). + const basegfx::B2DHomMatrix aViewTransform( + rDestinationCanvas->getTransformation() ); + const basegfx::B2DPoint aPageOrigin( + aViewTransform * basegfx::B2DPoint() ); + + // move sprite + rSprite->movePixel( + aPageOrigin + + ((t - 1.0) * + ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) * + maEnteringDirection) ); +} + +void MovingSlideChange::performOut( + const ::cppcanvas::CustomSpriteSharedPtr& rSprite, + const ViewEntry& rViewEntry, + const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas, + double t ) +{ + // outro sprite moves: + + ENSURE_OR_THROW( + rSprite, + "MovingSlideChange::performOut(): Invalid sprite" ); + ENSURE_OR_THROW( + rDestinationCanvas, + "MovingSlideChange::performOut(): Invalid dest canvas" ); + + // TODO(F1): This does not account for non-translational + // transformations! If the canvas is rotated, we still + // move the sprite unrotated (which might or might not + // produce the intended effect). + const basegfx::B2DHomMatrix aViewTransform( + rDestinationCanvas->getTransformation() ); + const basegfx::B2DPoint aPageOrigin( + aViewTransform * basegfx::B2DPoint() ); + + // move sprite + rSprite->movePixel( + aPageOrigin + (t * + ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) * + maLeavingDirection) ); +} + + +NumberAnimationSharedPtr createPushWipeTransition( + std::optional<SlideSharedPtr> const & leavingSlide_, + const SlideSharedPtr& pEnteringSlide, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + EventMultiplexer& rEventMultiplexer, + sal_Int16 /*nTransitionType*/, + sal_Int16 nTransitionSubType, + bool /*bTransitionDirection*/, + const SoundPlayerSharedPtr& pSoundPlayer ) +{ + std::optional<SlideSharedPtr> leavingSlide; // no bitmap + if (leavingSlide_ && *leavingSlide_ != nullptr) + { + // opt: only page, if we've an + // actual slide to move out here. We + // _don't_ need a fake black background + // bitmap, neither for push nor for comb + // wipes. + leavingSlide = leavingSlide_; + } + + // setup direction vector + bool bComb( false ); + ::basegfx::B2DVector aDirection; + switch( nTransitionSubType ) + { + default: + OSL_FAIL( + "createPushWipeTransition(): Unexpected transition " + "subtype for animations::TransitionType::PUSHWIPE " + "transitions" ); + return NumberAnimationSharedPtr(); + + case animations::TransitionSubType::FROMTOP: + aDirection = ::basegfx::B2DVector( 0.0, 1.0 ); + break; + + case animations::TransitionSubType::FROMBOTTOM: + aDirection = ::basegfx::B2DVector( 0.0, -1.0 ); + break; + + case animations::TransitionSubType::FROMLEFT: + aDirection = ::basegfx::B2DVector( 1.0, 0.0 ); + break; + + case animations::TransitionSubType::FROMRIGHT: + aDirection = ::basegfx::B2DVector( -1.0, 0.0 ); + break; + + case animations::TransitionSubType::FROMBOTTOMRIGHT: + aDirection = ::basegfx::B2DVector( -1.0, -1.0 ); + break; + + case animations::TransitionSubType::FROMBOTTOMLEFT: + aDirection = ::basegfx::B2DVector( 1.0, -1.0 ); + break; + + case animations::TransitionSubType::FROMTOPRIGHT: + aDirection = ::basegfx::B2DVector( -1.0, 1.0 ); + break; + + case animations::TransitionSubType::FROMTOPLEFT: + aDirection = ::basegfx::B2DVector( 1.0, 1.0 ); + break; + + case animations::TransitionSubType::COMBHORIZONTAL: + aDirection = ::basegfx::B2DVector( 1.0, 0.0 ); + bComb = true; + break; + + case animations::TransitionSubType::COMBVERTICAL: + aDirection = ::basegfx::B2DVector( 0.0, 1.0 ); + bComb = true; + break; + } + + if( bComb ) + { + return std::make_shared<CombTransition>( leavingSlide, + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + aDirection, + 24 /* comb with 12 stripes */ ); + } + else + { + return std::make_shared<MovingSlideChange>( leavingSlide, + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + aDirection, + aDirection ); + } +} + +NumberAnimationSharedPtr createSlideWipeTransition( + std::optional<SlideSharedPtr> const & leavingSlide, + const SlideSharedPtr& pEnteringSlide, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + EventMultiplexer& rEventMultiplexer, + sal_Int16 /*nTransitionType*/, + sal_Int16 nTransitionSubType, + bool bTransitionDirection, + const SoundPlayerSharedPtr& pSoundPlayer ) +{ + // setup 'in' direction vector + ::basegfx::B2DVector aInDirection; + switch( nTransitionSubType ) + { + default: + OSL_FAIL( + "createSlideWipeTransition(): Unexpected transition " + "subtype for animations::TransitionType::SLIDEWIPE " + "transitions" ); + return NumberAnimationSharedPtr(); + + case animations::TransitionSubType::FROMTOP: + aInDirection = ::basegfx::B2DVector( 0.0, 1.0 ); + break; + + case animations::TransitionSubType::FROMRIGHT: + aInDirection = ::basegfx::B2DVector( -1.0, 0.0 ); + break; + + case animations::TransitionSubType::FROMLEFT: + aInDirection = ::basegfx::B2DVector( 1.0, 0.0 ); + break; + + case animations::TransitionSubType::FROMBOTTOM: + aInDirection = ::basegfx::B2DVector( 0.0, -1.0 ); + break; + + case animations::TransitionSubType::FROMBOTTOMRIGHT: + aInDirection = ::basegfx::B2DVector( -1.0, -1.0 ); + break; + + case animations::TransitionSubType::FROMBOTTOMLEFT: + aInDirection = ::basegfx::B2DVector( 1.0, -1.0 ); + break; + + case animations::TransitionSubType::FROMTOPRIGHT: + aInDirection = ::basegfx::B2DVector( -1.0, 1.0 ); + break; + + case animations::TransitionSubType::FROMTOPLEFT: + aInDirection = ::basegfx::B2DVector( 1.0, 1.0 ); + break; + } + + if( bTransitionDirection ) + { + // normal, 'forward' slide wipe effect. Since the old + // content is still on screen (and does not move), we omit + // the 'leaving' slide. + + + return std::make_shared<MovingSlideChange>( + std::optional<SlideSharedPtr>() /* no slide */, + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + basegfx::B2DVector(), + aInDirection ); + } + else + { + // 'reversed' slide wipe effect. Reverse for slide wipes + // means, that the new slide is in the back, statically, + // and the old one is moving off in the foreground. + + + return std::make_shared<MovingSlideChange>( leavingSlide, + pEnteringSlide, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + aInDirection, + basegfx::B2DVector() ); + } +} + +NumberAnimationSharedPtr createPluginTransition( + sal_Int16 nTransitionType, + sal_Int16 nTransitionSubType, + const RGBColor& rTransitionFadeColor, + std::optional<SlideSharedPtr> const& pLeavingSlide, + const SlideSharedPtr& pEnteringSlide, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + const uno::Reference< + presentation::XTransitionFactory>& xFactory, + const SoundPlayerSharedPtr& pSoundPlayer, + EventMultiplexer& rEventMultiplexer) +{ + auto pTransition = + std::make_shared<PluginSlideChange>( + nTransitionType, + nTransitionSubType, + rTransitionFadeColor, + pLeavingSlide, + pEnteringSlide, + rViewContainer, + rScreenUpdater, + xFactory, + pSoundPlayer, + rEventMultiplexer ); + + if( !pTransition->Success() ) + return nullptr; + return pTransition; +} + +} // anon namespace + + +NumberAnimationSharedPtr TransitionFactory::createSlideTransition( + const SlideSharedPtr& pLeavingSlide, + const SlideSharedPtr& pEnteringSlide, + const UnoViewContainer& rViewContainer, + ScreenUpdater& rScreenUpdater, + EventMultiplexer& rEventMultiplexer, + const uno::Reference<presentation::XTransitionFactory>& xOptionalFactory, + sal_Int16 nTransitionType, + sal_Int16 nTransitionSubType, + bool bTransitionDirection, + const RGBColor& rTransitionFadeColor, + const SoundPlayerSharedPtr& pSoundPlayer ) +{ + // xxx todo: change to TransitionType::NONE, TransitionSubType::NONE: + if (nTransitionType == 0 && nTransitionSubType == 0) { + // just play sound, no slide transition: + if (pSoundPlayer) { + pSoundPlayer->startPlayback(); + // xxx todo: for now, presentation.cxx takes care about the slide + // #i50492# transition sound object, so just release it here + } + return NumberAnimationSharedPtr(); + } + + ENSURE_OR_THROW( + pEnteringSlide, + "TransitionFactory::createSlideTransition(): Invalid entering slide" ); + + if( xOptionalFactory.is() && + xOptionalFactory->hasTransition(nTransitionType, nTransitionSubType) ) + { + // #i82460# - optional plugin factory claims this transition. delegate. + NumberAnimationSharedPtr pTransition( + createPluginTransition( + nTransitionType, + nTransitionSubType, + rTransitionFadeColor, + std::make_optional(pLeavingSlide), + pEnteringSlide, + rViewContainer, + rScreenUpdater, + xOptionalFactory, + pSoundPlayer, + rEventMultiplexer )); + + if( pTransition ) + return pTransition; + } + + const TransitionInfo* pTransitionInfo( + getTransitionInfo( nTransitionType, nTransitionSubType ) ); + + if( pTransitionInfo != nullptr ) + { + switch( pTransitionInfo->meTransitionClass ) + { + default: + case TransitionInfo::TRANSITION_INVALID: + SAL_WARN("slideshow", + "TransitionFactory::createSlideTransition(): " + "Invalid type/subtype combination encountered." + << nTransitionType << " " << nTransitionSubType ); + return NumberAnimationSharedPtr(); + + + case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON: + { + // generate parametric poly-polygon + ParametricPolyPolygonSharedPtr pPoly( + ParametricPolyPolygonFactory::createClipPolyPolygon( + nTransitionType, nTransitionSubType ) ); + + // create a clip transition from that + return std::make_shared<ClippedSlideChange>( pEnteringSlide, + pPoly, + *pTransitionInfo, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + bTransitionDirection, + pSoundPlayer ); + } + + case TransitionInfo::TRANSITION_SPECIAL: + { + switch( nTransitionType ) + { + default: + OSL_FAIL( + "TransitionFactory::createSlideTransition(): " + "Unexpected transition type for " + "TRANSITION_SPECIAL transitions" ); + return NumberAnimationSharedPtr(); + + case animations::TransitionType::RANDOM: + { + // select randomly one of the effects from the + // TransitionFactoryTable + + const TransitionInfo* pRandomTransitionInfo( + getRandomTransitionInfo() ); + + ENSURE_OR_THROW( + pRandomTransitionInfo != nullptr, + "TransitionFactory::createSlideTransition(): " + "Got invalid random transition info" ); + + ENSURE_OR_THROW( + pRandomTransitionInfo->mnTransitionType != + animations::TransitionType::RANDOM, + "TransitionFactory::createSlideTransition(): " + "Got random again for random input!" ); + + // and recurse + return createSlideTransition( + pLeavingSlide, + pEnteringSlide, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + xOptionalFactory, + pRandomTransitionInfo->mnTransitionType, + pRandomTransitionInfo->mnTransitionSubType, + bTransitionDirection, + rTransitionFadeColor, + pSoundPlayer ); + } + + case animations::TransitionType::PUSHWIPE: + { + return createPushWipeTransition( + std::make_optional(pLeavingSlide), + pEnteringSlide, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + nTransitionType, + nTransitionSubType, + bTransitionDirection, + pSoundPlayer ); + } + + case animations::TransitionType::SLIDEWIPE: + { + return createSlideWipeTransition( + std::make_optional(pLeavingSlide), + pEnteringSlide, + rViewContainer, + rScreenUpdater, + rEventMultiplexer, + nTransitionType, + nTransitionSubType, + bTransitionDirection, + pSoundPlayer ); + } + + case animations::TransitionType::BARWIPE: + case animations::TransitionType::FADE: + { + // black page: + std::optional<SlideSharedPtr> leavingSlide; + std::optional<RGBColor> aFadeColor; + + switch( nTransitionSubType ) + { + case animations::TransitionSubType::CROSSFADE: + // crossfade needs no further setup, + // just blend new slide over current + // slide. + break; + + // TODO(F1): Implement toColor/fromColor fades + case animations::TransitionSubType::FADETOCOLOR: + case animations::TransitionSubType::FADEFROMCOLOR: + case animations::TransitionSubType::FADEOVERCOLOR: + if (pLeavingSlide) { + // only generate, if fade + // effect really needs it. + leavingSlide = pLeavingSlide; + } + aFadeColor = rTransitionFadeColor; + break; + + default: + ENSURE_OR_THROW( false, + "SlideTransitionFactory::createSlideTransition(): Unknown FADE subtype" ); + } + + if( nTransitionType == animations::TransitionType::FADE ) + return std::make_shared<FadingSlideChange>( + leavingSlide, + pEnteringSlide, + aFadeColor, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer ); + else + return std::make_shared<CutSlideChange>( + leavingSlide, + pEnteringSlide, + rTransitionFadeColor, + pSoundPlayer, + rViewContainer, + rScreenUpdater, + rEventMultiplexer ); + } + } + } + break; + } + } + + // No animation generated, maybe no table entry for given + // transition? + SAL_WARN("slideshow", + "TransitionFactory::createSlideTransition(): " + "Unknown type/subtype combination encountered " + << nTransitionType << " " << nTransitionSubType ); + OSL_FAIL( + "TransitionFactory::createSlideTransition(): " + "Unknown type/subtype combination encountered" ); + + return NumberAnimationSharedPtr(); +} + +} // namespace presentation + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |