summaryrefslogtreecommitdiff
path: root/slideshow/source/engine/slide
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2007-07-17 13:57:53 +0000
committerOliver Bolte <obo@openoffice.org>2007-07-17 13:57:53 +0000
commit4f62fb23245bb1666988bdc08b361124dd788c43 (patch)
treef4747704e874c01e6899f01e32d0a9cdcdaddde7 /slideshow/source/engine/slide
parent67b029256ddf4842daa8ea6781f47b703cdaa756 (diff)
INTEGRATION: CWS presfixes12 (1.1.2); FILE ADDED
2007/05/14 00:55:29 thb 1.1.2.14: #i77154# Moved intrinsic animation notification from global EventMultiplexer to ShapeManager (which is local to each slide). This is a temporary workaround, the proper fix would demote the EventMultiplexer to each Slide 2007/05/10 20:32:40 thb 1.1.2.13: #i37778# Reworked LayerManager::updateShapeLayers - now much better aligned with general shape update, and avoids superfluous rendering; made unit tests work again; passing down slide background repaint status to LayerManager; relaxed preconditions for Shape::getUpdateArea() - no longer requires views to work; now catching singular view matrix and using sensible default at API border 2007/05/02 21:37:23 thb 1.1.2.12: #i37778# Changed calls to cppcanvas::Canvas::getTransformation() to ViewLayer::getTransformation() where appropriate (because that's more direct); added initial Slide rendering back in (this time optional) 2007/04/30 07:26:33 thb 1.1.2.11: #i37778# Rendering slide bitmap at the end of a slide transition, instead of during Slide::show(), to avoid temporary display of previous slide after transition sprite vanished. 2007/03/11 00:17:59 thb 1.1.2.10: #i37778# Necessary adaptions for cppcanvas clip behaviour (extra setClip() methods to clear clip, instead of empty polygon, which denotes everything clipped on canvas); removed cyclic references for intrinsically animated shapes (GIF and drawing layer scroll text); fixed a few coding style inconsistencies 2007/03/06 21:54:18 thb 1.1.2.9: #i37778# Added bool property to disable z order correct animations 2007/02/25 01:10:27 thb 1.1.2.8: #i37778# Cleared up error handling a lot: no longer quenching RuntimeExceptions; reporting assertions in the debug case; ViewLayer now reports resized sprite (which needs re-render from all shapes); fixed missing subset area reduction for glyph-level animations; added return of resize state from Layer::commitLayerBounds(); adapted unit tests to corrected behaviour 2007/02/20 22:41:15 thb 1.1.2.7: #i37778# Emulating old sprite behaviour to clear content on getContentCanvas() in AnimatedSprite; corrected handling of full and partial view clears; corrected layer update when shapes are added or removed 2007/02/12 02:14:52 thb 1.1.2.6: #i37778# Added workaround to have ViewLayer always return valid canvas (even if no size has been set); fixed silly reference-instead-of-byvalue bug in SlideAnimations for slide size; fixed member initialization order problem in SlideImpl (also affecting slide size); adapted shape import for new LayerManager (which no longer gracefully ignores addition of NULL shapes); extended unit tests to catch fixed bugs 2007/02/06 17:18:13 thb 1.1.2.5: #i37778# Moved clear() method from View to ViewLayer (also sprites need to be cleared); fixed a few more cases of local code style violations; removed redundant inline keywords; finished Layer/LayerManager rework (Layer now represents ViewLayers, shapes and rendering are fully under LayerManager control); made shape comparator reusable 2007/01/31 14:30:33 thb 1.1.2.4: #i37778# removed View::isContentDestroyed() and mbContentValid distinction on View::clear() - clear() now always clears view the hard way; added explicit screen update to CombTransition, which bypasses SlideChangeBase functionality 2007/01/30 16:43:50 thb 1.1.2.3: #i37778# Made view update/repaint/resize work again; swapped BackgroundShape parameters for correct mtf import 2007/01/29 16:29:30 thb 1.1.2.2: #i37778# Build fixes for msvc; added shapes lib to util link line 2007/01/29 14:02:15 thb 1.1.2.1: Issue number: #i37778# Larger slideshow refactoring. Wrote design and coding style manifest, and adapted the code to actually conform to this. In detail: - cleaned up ownership/disposable/weak_ptr story. removed hacks and explicit Disposable implementations, where workaround were available - removed object mutices, where superfluous - reworked EventMultiplexer (using templatized listener class now), added more events. EventMultiplexer now serves as a true blackboard - reworked directory structure: disjunct parts are now physically separated into directories, instantiation happens via factories & abstract interfaces - added CursorManager, to make setting mouse cursor less hackish - reworked DrawShape, to implement SeparateListener pattern - reworked IntrinsicAnimationActivity, to avoid cyclic references - modified hyperlink & shape cursor handling to communicate via EventMultiplexer - renamed & cleaned up files (presentation.cxx now named slideshowimpl.cxx, etc.) - added first version of the z-order fix to layer/layermanager - cleaned up include guards and include syntax
Diffstat (limited to 'slideshow/source/engine/slide')
-rw-r--r--slideshow/source/engine/slide/slideimpl.cxx1215
1 files changed, 1215 insertions, 0 deletions
diff --git a/slideshow/source/engine/slide/slideimpl.cxx b/slideshow/source/engine/slide/slideimpl.cxx
new file mode 100644
index 000000000000..9aee72aaa5c8
--- /dev/null
+++ b/slideshow/source/engine/slide/slideimpl.cxx
@@ -0,0 +1,1215 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: slideimpl.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: obo $ $Date: 2007-07-17 14:57:53 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <osl/diagnose.hxx>
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/drawing/XMasterPageTarget.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#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>
+
+#include "slide.hxx"
+#include "slideshowcontext.hxx"
+#include "slideanimations.hxx"
+#include "doctreenode.hxx"
+#include "screenupdater.hxx"
+#include "cursormanager.hxx"
+#include "shapeimporter.hxx"
+#include "slideshowexceptions.hxx"
+#include "eventqueue.hxx"
+#include "activitiesqueue.hxx"
+#include "layermanager.hxx"
+#include "shapemanagerimpl.hxx"
+#include "usereventqueue.hxx"
+#include "userpaintoverlay.hxx"
+#include "event.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+#include <iterator>
+#include <algorithm>
+#include <functional>
+
+
+using namespace ::com::sun::star;
+
+// -----------------------------------------------------------------------------
+
+namespace slideshow
+{
+namespace internal
+{
+namespace
+{
+
+class SlideImpl : public Slide,
+ public CursorManager,
+ public ViewEventHandler,
+ protected ::osl::DebugBase<SlideImpl>
+{
+public:
+ SlideImpl( const uno::Reference<drawing::XDrawPage>& xDrawPage,
+ const uno::Reference<animations::XAnimationNode>& xRootNode,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const uno::Reference<uno::XComponentContext>& xContext,
+ const ShapeEventListenerMap& rShapeListenerMap,
+ const ShapeCursorMap& rShapeCursorMap,
+ RGBColor const& rUserPaintColor,
+ bool bUserPaintEnabled,
+ bool bIntrinsicAnimationsAllowed,
+ bool bDisableAnimationZOrder );
+
+ ~SlideImpl();
+
+
+ // Disposable interface
+ // -------------------------------------------------------------------
+
+ virtual void dispose();
+
+
+ // Slide interface
+ // -------------------------------------------------------------------
+
+ virtual bool prefetch();
+ virtual bool show( bool );
+ virtual void hide();
+
+ virtual basegfx::B2ISize getSlideSize() const;
+ virtual uno::Reference<drawing::XDrawPage > getXDrawPage() const;
+ virtual uno::Reference<animations::XAnimationNode> getXAnimationNode() const;
+
+ // TODO(F2): Rework SlideBitmap to no longer be based on XBitmap,
+ // but on canvas-independent basegfx bitmaps
+ virtual SlideBitmapSharedPtr getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const;
+
+
+private:
+ // ViewEventHandler
+ virtual void viewAdded( const UnoViewSharedPtr& rView );
+ virtual void viewRemoved( const UnoViewSharedPtr& rView );
+ virtual void viewChanged( const UnoViewSharedPtr& rView );
+ virtual void viewsChanged();
+
+ // CursorManager
+ virtual bool requestCursor( sal_Int16 nCursorShape );
+ virtual void resetCursor();
+
+ /** Query whether the slide has animations at all
+
+ If the slide doesn't have animations, show() displays
+ only static content. If an event is registered with
+ registerSlideEndEvent(), this event will be
+ immediately activated at the end of the show() method.
+
+ @return true, if this slide has animations, false
+ otherwise
+ */
+ bool isAnimated();
+
+ /** Query whether this slide is currently showing.
+
+ @return true, if this slide is currently showing.
+ */
+ bool isShowing() const;
+
+ void enablePaintOverlay();
+ void disablePaintOverlay();
+
+ /// Set all Shapes to their initial attributes for slideshow
+ bool applyInitialShapeAttributes( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >& xRootAnimationNode );
+
+ /// Renders current slide content to bitmap
+ SlideBitmapSharedPtr createCurrentSlideBitmap(
+ const UnoViewSharedPtr& rView,
+ ::basegfx::B2ISize const & rSlideSize ) const;
+
+ /// Prefetch all shapes (not the animations)
+ bool loadShapes();
+
+ /// Retrieve slide size from XDrawPage
+ basegfx::B2ISize getSlideSizeImpl() const;
+
+ /// Prefetch show, but don't call applyInitialShapeAttributes()
+ bool implPrefetchShow();
+
+ /// Query the rectangle covered by the slide
+ ::basegfx::B2DRectangle getSlideRect() const;
+
+ /// Start GIF and other intrinsic shape animations
+ void endIntrinsicAnimations();
+
+ /// End GIF and other intrinsic shape animations
+ void startIntrinsicAnimations();
+
+
+ // Types
+ // =====
+
+ enum SlideAnimationState
+ {
+ CONSTRUCTING_STATE=0,
+ INITIAL_STATE=1,
+ SHOWING_STATE=2,
+ FINAL_STATE=3,
+ SlideAnimationState_NUM_ENTRIES=4
+ };
+
+ typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps;
+ /** Vector of slide bitmaps.
+
+ Since the bitmap content is sensitive to animation
+ effects, we have an inner vector containing a distinct
+ bitmap for each of the SlideAnimationStates.
+ */
+ typedef ::std::vector< std::pair< UnoViewSharedPtr,
+ VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
+
+
+ // Member variables
+ // ================
+
+ /// The page model object
+ uno::Reference< drawing::XDrawPage > mxDrawPage;
+ uno::Reference< animations::XAnimationNode > mxRootNode;
+
+ LayerManagerSharedPtr mpLayerManager;
+ boost::shared_ptr<ShapeManagerImpl> mpShapeManager;
+ boost::shared_ptr<SubsettableShapeManager> mpSubsettableShapeManager;
+
+ /// Contains common objects needed throughout the slideshow
+ SlideShowContext maContext;
+
+ /// parent cursor manager
+ CursorManager& mrCursorManager;
+
+ /// Handles the animation and event generation for us
+ SlideAnimations maAnimations;
+
+ RGBColor maUserPaintColor;
+ UserPaintOverlaySharedPtr mpPaintOverlay;
+
+ /// Bitmaps with slide content at various states
+ mutable VectorOfVectorOfSlideBitmaps maSlideBitmaps;
+
+ SlideAnimationState meAnimationState;
+
+ const basegfx::B2ISize maSlideSize;
+
+ sal_Int16 mnCurrentCursor;
+
+ /// True, when intrinsic shape animations are allowed
+ bool mbIntrinsicAnimationsAllowed;
+
+ /// True, when user paint overlay is enabled
+ bool mbUserPaintOverlayEnabled;
+
+ /// True, if initial load of all page shapes succeeded
+ bool mbShapesLoaded;
+
+ /// True, if initial load of all animation info succeeded
+ bool mbShowLoaded;
+
+ /** True, if this slide is not static.
+
+ If this slide has animated content, this variable will
+ be true, and false otherwise.
+ */
+ bool mbHaveAnimations;
+
+ /** True, if this slide has a main animation sequence.
+
+ If this slide has animation content, which in turn has
+ a main animation sequence (which must be fully run
+ before EventMultiplexer::notifySlideAnimationsEnd() is
+ called), this member is true.
+ */
+ bool mbMainSequenceFound;
+
+ /// When true, show() was called. Slide hidden oherwise.
+ bool mbActive;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////////
+
+
+class SlideRenderer
+{
+public:
+ explicit SlideRenderer( SlideImpl& rSlide ) :
+ mrSlide( rSlide )
+ {
+ }
+
+ void operator()( const UnoViewSharedPtr& rView )
+ {
+ // fully clear view content to background color
+ rView->clearAll();
+
+ SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( rView ) );
+ ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
+
+ const ::basegfx::B2DHomMatrix aViewTransform( rView->getTransformation() );
+ const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
+
+ // setup a canvas with device coordinate space, the slide
+ // bitmap already has the correct dimension.
+ ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
+ pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // render at given output position
+ pBitmap->move( aOutPosPixel );
+
+ // clear clip (might have been changed, e.g. from comb
+ // transition)
+ pBitmap->clip( ::basegfx::B2DPolyPolygon() );
+ pBitmap->draw( pDevicePixelCanvas );
+ }
+
+private:
+ SlideImpl& mrSlide;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////////
+
+
+SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const uno::Reference< animations::XAnimationNode >& xRootNode,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const uno::Reference< uno::XComponentContext >& xComponentContext,
+ const ShapeEventListenerMap& rShapeListenerMap,
+ const ShapeCursorMap& rShapeCursorMap,
+ RGBColor const& aUserPaintColor,
+ bool bUserPaintEnabled,
+ bool bIntrinsicAnimationsAllowed,
+ bool bDisableAnimationZOrder ) :
+ mxDrawPage( xDrawPage ),
+ mxRootNode( xRootNode ),
+ mpLayerManager( new LayerManager(
+ rViewContainer,
+ getSlideRect(),
+ bDisableAnimationZOrder) ),
+ mpShapeManager( new ShapeManagerImpl(
+ rEventMultiplexer,
+ mpLayerManager,
+ rCursorManager,
+ rShapeListenerMap,
+ rShapeCursorMap)),
+ mpSubsettableShapeManager( mpShapeManager ),
+ maContext( mpSubsettableShapeManager,
+ rEventQueue,
+ rEventMultiplexer,
+ rScreenUpdater,
+ rActivitiesQueue,
+ rUserEventQueue,
+ *this,
+ rViewContainer,
+ xComponentContext ),
+ mrCursorManager( rCursorManager ),
+ maAnimations( maContext,
+ getSlideSizeImpl() ),
+ maUserPaintColor(aUserPaintColor),
+ mpPaintOverlay(),
+ maSlideBitmaps(),
+ meAnimationState( CONSTRUCTING_STATE ),
+ maSlideSize(getSlideSizeImpl()),
+ mnCurrentCursor( awt::SystemPointer::ARROW ),
+ mbIntrinsicAnimationsAllowed( bIntrinsicAnimationsAllowed ),
+ mbUserPaintOverlayEnabled(bUserPaintEnabled),
+ mbShapesLoaded( false ),
+ mbShowLoaded( false ),
+ mbHaveAnimations( false ),
+ mbMainSequenceFound( false ),
+ mbActive( false )
+{
+ // clone already existing views for slide bitmaps
+ std::for_each( rViewContainer.begin(),
+ rViewContainer.end(),
+ boost::bind( &SlideImpl::viewAdded,
+ this,
+ _1 ));
+
+ // register screen update (LayerManager needs to signal pending
+ // updates)
+ maContext.mrScreenUpdater.addViewUpdate(mpShapeManager);
+}
+
+SlideImpl::~SlideImpl()
+{
+ if( mpShapeManager )
+ {
+ maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
+ mpShapeManager->dispose();
+
+ // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
+ // first, because SlideShowContext has SubsettableShapeManager
+ // as reference member.
+ mpLayerManager.reset();
+ }
+}
+
+void SlideImpl::dispose()
+{
+ maSlideBitmaps.clear();
+ mpPaintOverlay.reset();
+ maAnimations.dispose();
+ maContext.dispose();
+
+ if( mpShapeManager )
+ {
+ maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
+ mpShapeManager->dispose();
+ }
+
+ // TODO(Q3): Make sure LayerManager (and thus Shapes) dies first,
+ // because SlideShowContext has SubsettableShapeManager as
+ // reference member.
+ mpLayerManager.reset();
+ mpSubsettableShapeManager.reset();
+ mpShapeManager.reset();
+ mxRootNode.clear();
+ mxDrawPage.clear();
+}
+
+bool SlideImpl::prefetch()
+{
+ if( !mxRootNode.is() )
+ return false;
+
+ return applyInitialShapeAttributes(mxRootNode);
+}
+
+bool SlideImpl::show( bool bSlideBackgoundPainted )
+{
+ // ---------------------------------------------------------------
+
+ if( mbActive )
+ return true; // already active
+
+ if( !mpShapeManager || !mpLayerManager )
+ return false; // disposed
+
+ // ---------------------------------------------------------------
+
+ // set initial shape attributes (e.g. hide shapes that have
+ // 'appear' effect set)
+ if( !applyInitialShapeAttributes(mxRootNode) )
+ return false;
+
+ // ---------------------------------------------------------------
+
+ // activate and take over view - clears view, if necessary
+ mbActive = true;
+ requestCursor( mnCurrentCursor );
+
+ // enable shape management & event broadcasting for shapes of this
+ // slide. Also enables LayerManager to record updates. Currently,
+ // never let LayerManager render initial slide content, use
+ // buffered slide bitmaps instead.
+ mpShapeManager->activate( true );
+
+ // ---------------------------------------------------------------
+
+ // render slide to screen, if requested
+ if( !bSlideBackgoundPainted )
+ {
+ std::for_each(maContext.mrViewContainer.begin(),
+ maContext.mrViewContainer.end(),
+ boost::mem_fn(&View::clearAll));
+
+ std::for_each( maContext.mrViewContainer.begin(),
+ maContext.mrViewContainer.end(),
+ SlideRenderer(*this) );
+ maContext.mrScreenUpdater.notifyUpdate();
+ }
+
+ // ---------------------------------------------------------------
+
+ // fire up animations
+ const bool bIsAnimated( isAnimated() );
+ if( bIsAnimated )
+ maAnimations.start(); // feeds initial events into queue
+
+ // NOTE: this looks slightly weird, but is indeed correct:
+ // as isAnimated() might return false, _although_ there is
+ // a main sequence (because the animation nodes don't
+ // contain any executable effects), we gotta check both
+ // conditions here.
+ if( !bIsAnimated || !mbMainSequenceFound )
+ {
+ // manually trigger a slide animation end event (we don't have
+ // animations at all, or we don't have a main animation
+ // sequence, but if we had, it'd end now). Note that having
+ // animations alone does not matter here, as only main
+ // sequence animations prevents showing the next slide on
+ // nextEvent().
+ maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
+ }
+
+ // enable shape-intrinsic animations (drawing layer animations or
+ // GIF animations)
+ if( mbIntrinsicAnimationsAllowed )
+ startIntrinsicAnimations();
+
+ // ---------------------------------------------------------------
+
+ // enable paint overlay, if maUserPaintColor is valid
+ enablePaintOverlay();
+
+ // ---------------------------------------------------------------
+
+ // from now on, animations might be showing
+ meAnimationState = SHOWING_STATE;
+
+ return true;
+}
+
+void SlideImpl::hide()
+{
+ if( !mbActive || !mpShapeManager )
+ return; // already hidden/disposed
+
+ // ---------------------------------------------------------------
+
+ // from now on, all animations are stopped
+ meAnimationState = FINAL_STATE;
+
+ // ---------------------------------------------------------------
+
+ // disable user paint overlay under all circumstances,
+ // this slide now ceases to be active.
+ disablePaintOverlay();
+
+ // ---------------------------------------------------------------
+
+ // switch off all shape-intrinsic animations.
+ endIntrinsicAnimations();
+
+ // force-end all SMIL animations, too
+ maAnimations.end();
+
+ // ---------------------------------------------------------------
+
+ // disable shape management & event broadcasting for shapes of this
+ // slide. Also disables LayerManager.
+ mpShapeManager->deactivate();
+
+ // vanish from view
+ resetCursor();
+ mbActive = false;
+
+ // ---------------------------------------------------------------
+}
+
+basegfx::B2ISize SlideImpl::getSlideSize() const
+{
+ return maSlideSize;
+}
+
+uno::Reference<drawing::XDrawPage > SlideImpl::getXDrawPage() const
+{
+ return mxDrawPage;
+}
+
+uno::Reference<animations::XAnimationNode> SlideImpl::getXAnimationNode() const
+{
+ return mxRootNode;
+}
+
+
+SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
+{
+ // search corresponding entry in maSlideBitmaps (which
+ // contains the views as the key)
+ VectorOfVectorOfSlideBitmaps::iterator aIter;
+ const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
+ if( (aIter=std::find_if( maSlideBitmaps.begin(),
+ aEnd,
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind(
+ std::select1st<VectorOfVectorOfSlideBitmaps::value_type>(),
+ _1 )))) == aEnd )
+ {
+ // corresponding view not found - maybe view was not
+ // added to Slide?
+ ENSURE_AND_THROW( false,
+ "SlideImpl::getInitialSlideBitmap(): view does not "
+ "match any of the added ones" );
+ }
+
+ // ensure that the show is loaded
+ if( !mbShowLoaded )
+ {
+ // only prefetch and init shapes when not done already
+ // (otherwise, at least applyInitialShapeAttributes() will be
+ // called twice for initial slide rendering). Furthermore,
+ // applyInitialShapeAttributes() _always_ performs
+ // initializations, which would be highly unwanted during a
+ // running show. OTOH, a slide whose mbShowLoaded is false is
+ // guaranteed not be running a show.
+
+ // set initial shape attributes (e.g. hide 'appear' effect
+ // shapes)
+ if( !const_cast<SlideImpl*>(this)->applyInitialShapeAttributes( mxRootNode ) )
+ ENSURE_AND_THROW(false,
+ "SlideImpl::getCurrentSlideBitmap(): Cannot "
+ "apply initial attributes");
+ }
+
+ SlideBitmapSharedPtr& rBitmap( aIter->second.at( meAnimationState ));
+ const ::basegfx::B2ISize& rSlideSize(
+ getSlideSizePixel( getSlideSize(),
+ rView ));
+
+ // is the bitmap valid (actually existent, and of correct
+ // size)?
+ if( !rBitmap || rBitmap->getSize() != rSlideSize )
+ {
+ // no bitmap there yet, or wrong size - create one
+ rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
+ }
+
+ return rBitmap;
+}
+
+
+// private methods
+//--------------------------------------------------------------------------------------------------------------
+
+
+void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
+{
+ maSlideBitmaps.push_back(
+ std::make_pair( rView,
+ VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) ));
+
+ if( mpLayerManager )
+ mpLayerManager->viewAdded( rView );
+}
+
+void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
+{
+ if( mpLayerManager )
+ mpLayerManager->viewRemoved( rView );
+
+ const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
+ maSlideBitmaps.erase(
+ std::remove_if( maSlideBitmaps.begin(),
+ aEnd,
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind(
+ std::select1st<VectorOfVectorOfSlideBitmaps::value_type>(),
+ _1 ))),
+ aEnd );
+}
+
+void SlideImpl::viewChanged( const UnoViewSharedPtr& rView )
+{
+ // nothing to do for the Slide - getCurrentSlideBitmap() lazily
+ // handles bitmap resizes
+ if( mbActive && mpLayerManager )
+ mpLayerManager->viewChanged(rView);
+}
+
+void SlideImpl::viewsChanged()
+{
+ // nothing to do for the Slide - getCurrentSlideBitmap() lazily
+ // handles bitmap resizes
+ if( mbActive && mpLayerManager )
+ mpLayerManager->viewsChanged();
+}
+
+bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
+{
+ mnCurrentCursor = nCursorShape;
+ return mrCursorManager.requestCursor(mnCurrentCursor);
+}
+
+void SlideImpl::resetCursor()
+{
+ mnCurrentCursor = awt::SystemPointer::ARROW;
+ mrCursorManager.resetCursor();
+}
+
+bool SlideImpl::isShowing() const
+{
+ return meAnimationState == SHOWING_STATE;
+}
+
+bool SlideImpl::isAnimated()
+{
+ // prefetch, but don't apply initial shape attributes
+ if( !implPrefetchShow() )
+ return false;
+
+ return mbHaveAnimations && maAnimations.isAnimated();
+}
+
+SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( const UnoViewSharedPtr& rView,
+ const ::basegfx::B2ISize& rBmpSize ) const
+{
+ ENSURE_AND_THROW( rView && rView->getCanvas(),
+ "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
+ ENSURE_AND_THROW( mpLayerManager,
+ "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" );
+ ENSURE_AND_THROW( mbShowLoaded,
+ "SlideImpl::createCurrentSlideBitmap(): No show loaded" );
+
+ ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
+
+ // create a bitmap of appropriate size
+ ::cppcanvas::BitmapSharedPtr pBitmap(
+ ::cppcanvas::BaseGfxFactory::getInstance().createBitmap(
+ pCanvas,
+ rBmpSize ) );
+
+ ENSURE_AND_THROW( pBitmap,
+ "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" );
+
+ ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
+
+ ENSURE_AND_THROW( pBitmapCanvas,
+ "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap canvas" );
+
+ // apply linear part of destination canvas transformation (linear means in this context:
+ // transformation without any translational components)
+ ::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
+ aLinearTransform.set( 0, 2, 0.0 );
+ aLinearTransform.set( 1, 2, 0.0 );
+ pBitmapCanvas->setTransformation( aLinearTransform );
+
+ // output all shapes to bitmap
+ initSlideBackground( pBitmapCanvas, rBmpSize );
+ mpLayerManager->renderTo( pBitmapCanvas );
+
+ return SlideBitmapSharedPtr( new SlideBitmap( pBitmap ) );
+}
+
+namespace
+{
+ class MainSequenceSearcher
+ {
+ public:
+ MainSequenceSearcher()
+ {
+ maSearchKey.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
+ maSearchKey.Value <<= presentation::EffectNodeType::MAIN_SEQUENCE;
+ }
+
+ void operator()( const uno::Reference< animations::XAnimationNode >& xChildNode )
+ {
+ uno::Sequence< beans::NamedValue > aUserData( xChildNode->getUserData() );
+
+ if( findNamedValue( aUserData, maSearchKey ) )
+ {
+ maMainSequence = xChildNode;
+ }
+ }
+
+ uno::Reference< animations::XAnimationNode > getMainSequence() const
+ {
+ return maMainSequence;
+ }
+
+ private:
+ beans::NamedValue maSearchKey;
+ uno::Reference< animations::XAnimationNode > maMainSequence;
+ };
+}
+
+bool SlideImpl::implPrefetchShow()
+{
+ if( mbShowLoaded )
+ return true;
+
+ ENSURE_AND_RETURN( mxDrawPage.is(),
+ "SlideImpl::implPrefetchShow(): Invalid draw page" );
+ ENSURE_AND_RETURN( mpLayerManager,
+ "SlideImpl::implPrefetchShow(): Invalid layer manager" );
+
+ // fetch desired page content
+ // ==========================
+
+ if( !loadShapes() )
+ return false;
+
+ // New animations framework: import the shape effect info
+ // ======================================================
+
+ try
+ {
+ if( mxRootNode.is() )
+ {
+ if( !maAnimations.importAnimations( mxRootNode ) )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::implPrefetchShow(): have animation nodes, "
+ "but import animations failed." );
+
+ // could not import animation framework,
+ // _although_ some animation nodes are there -
+ // this is an error (not finding animations at
+ // all is okay - might be a static slide)
+ return false;
+ }
+
+ // now check whether we've got a main sequence (if
+ // not, we must manually call
+ // EventMultiplexer::notifySlideAnimationsEnd()
+ // above, as e.g. interactive sequences alone
+ // don't block nextEvent() from issuing the next
+ // slide)
+ MainSequenceSearcher aSearcher;
+ if( ::anim::for_each_childNode( mxRootNode, aSearcher ) )
+ mbMainSequenceFound = aSearcher.getMainSequence().is();
+
+ // import successfully done
+ mbHaveAnimations = true;
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE(
+ false,
+ rtl::OUStringToOString(
+ comphelper::anyToString(cppu::getCaughtException()),
+ RTL_TEXTENCODING_UTF8 ) );
+ // TODO(E2): Error handling. For now, bail out
+ }
+
+ mbShowLoaded = true;
+
+ return true;
+}
+
+void SlideImpl::enablePaintOverlay()
+{
+ if( mbUserPaintOverlayEnabled )
+ mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor,
+ 2.0,
+ maContext );
+}
+
+void SlideImpl::disablePaintOverlay()
+{
+ mpPaintOverlay.reset();
+}
+
+::basegfx::B2DRectangle SlideImpl::getSlideRect() const
+{
+ const basegfx::B2ISize slideSize( getSlideSizeImpl() );
+ return ::basegfx::B2DRectangle(0.0,0.0,
+ slideSize.getX(),
+ slideSize.getY());
+}
+
+void SlideImpl::endIntrinsicAnimations()
+{
+ mpSubsettableShapeManager->notifyIntrinsicAnimationsDisabled();
+}
+
+void SlideImpl::startIntrinsicAnimations()
+{
+ mpSubsettableShapeManager->notifyIntrinsicAnimationsEnabled();
+}
+
+bool SlideImpl::applyInitialShapeAttributes(
+ const uno::Reference< animations::XAnimationNode >& xRootAnimationNode )
+{
+ if( !implPrefetchShow() )
+ return false;
+
+ if( !xRootAnimationNode.is() )
+ {
+ meAnimationState = INITIAL_STATE;
+
+ return true; // no animations - no attributes to apply -
+ // succeeded
+ }
+
+ uno::Reference< animations::XTargetPropertiesCreator > xPropsCreator;
+
+ try
+ {
+ ENSURE_AND_RETURN( maContext.mxComponentContext.is(),
+ "SlideImpl::applyInitialShapeAttributes(): Invalid component context" );
+
+ uno::Reference<lang::XMultiComponentFactory> xFac(
+ maContext.mxComponentContext->getServiceManager() );
+
+ xPropsCreator.set(
+ xFac->createInstanceWithContext(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.animations.TargetPropertiesCreator") ),
+ maContext.mxComponentContext ),
+ uno::UNO_QUERY_THROW );
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE(
+ false,
+ rtl::OUStringToOString(
+ comphelper::anyToString(cppu::getCaughtException()),
+ RTL_TEXTENCODING_UTF8 ) );
+
+ // could not determine initial shape attributes - this
+ // is an error, as some effects might then be plainly
+ // invisible
+ ENSURE_AND_RETURN( false,
+ "SlideImpl::applyInitialShapeAttributes(): "
+ "couldn't create TargetPropertiesCreator." );
+ }
+
+ uno::Sequence< animations::TargetProperties > aProps(
+ xPropsCreator->createInitialTargetProperties( xRootAnimationNode ) );
+
+ // apply extracted values to our shapes
+ const ::std::size_t nSize( aProps.getLength() );
+ for( ::std::size_t i=0; i<nSize; ++i )
+ {
+ sal_Int16 nParaIndex( -1 );
+ uno::Reference< drawing::XShape > xShape( aProps[i].Target,
+ uno::UNO_QUERY );
+
+ if( !xShape.is() )
+ {
+ // not a shape target. Maybe a ParagraphTarget?
+ presentation::ParagraphTarget aParaTarget;
+
+ if( (aProps[i].Target >>= aParaTarget) )
+ {
+ // yep, ParagraphTarget found - extract shape
+ // and index
+ xShape = aParaTarget.Shape;
+ nParaIndex = aParaTarget.Paragraph;
+ }
+ }
+
+ if( xShape.is() )
+ {
+ ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
+
+ if( !pShape )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
+ continue;
+ }
+
+ AttributableShapeSharedPtr pAttrShape(
+ ::boost::dynamic_pointer_cast< AttributableShape >( pShape ) );
+
+ if( !pAttrShape )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): shape found does not "
+ "implement AttributableShape interface" );
+ continue;
+ }
+
+ if( nParaIndex != -1 )
+ {
+ // our target is a paragraph subset, thus look
+ // this up first.
+ const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
+
+ pAttrShape = pAttrShape->getSubset(
+ rNodeSupplier.getTreeNode(
+ nParaIndex,
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) );
+
+ if( !pAttrShape )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): shape found does not "
+ "provide a subset for requested paragraph index" );
+ continue;
+ }
+ }
+
+ const uno::Sequence< beans::NamedValue >& rShapeProps( aProps[i].Properties );
+ const ::std::size_t nShapePropSize( rShapeProps.getLength() );
+ for( ::std::size_t j=0; j<nShapePropSize; ++j )
+ {
+ bool bVisible=false;
+ if( rShapeProps[j].Name.equalsIgnoreAsciiCaseAscii("visibility") &&
+ extractValue( bVisible,
+ rShapeProps[j].Value,
+ pShape,
+ getSlideSize() ))
+ {
+ pAttrShape->setVisibility( bVisible );
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): Unexpected "
+ "(and unimplemented) property encountered" );
+ }
+ }
+ }
+ }
+
+ meAnimationState = INITIAL_STATE;
+
+ return true;
+}
+
+bool SlideImpl::loadShapes()
+{
+ if( mbShapesLoaded )
+ return true;
+
+ ENSURE_AND_RETURN( mxDrawPage.is(),
+ "SlideImpl::loadShapes(): Invalid draw page" );
+ ENSURE_AND_RETURN( mpLayerManager,
+ "SlideImpl::loadShapes(): Invalid layer manager" );
+
+ // fetch desired page content
+ // ==========================
+
+ // also take master page content
+ uno::Reference< drawing::XDrawPage > xMasterPage;
+ uno::Reference< drawing::XShapes > xMasterPageShapes;
+ sal_Int32 nCurrCount(0);
+
+ uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( mxDrawPage,
+ uno::UNO_QUERY );
+ if( xMasterPageTarget.is() )
+ {
+ xMasterPage = xMasterPageTarget->getMasterPage();
+ xMasterPageShapes.set( xMasterPage,
+ uno::UNO_QUERY );
+
+ if( xMasterPage.is() && xMasterPageShapes.is() )
+ {
+ // TODO(P2): maybe cache master pages here (or treat the
+ // masterpage as a single metafile. At least currently,
+ // masterpages do not contain animation effects)
+ try
+ {
+ // load the masterpage shapes
+ // -------------------------------------------------------------------------
+ ShapeImporter aMPShapesFunctor( xMasterPage,
+ mxDrawPage,
+ maContext,
+ 0, /* shape num starts at 0 */
+ true );
+
+ mpLayerManager->addShape(
+ aMPShapesFunctor.importBackgroundShape() );
+
+ while( !aMPShapesFunctor.isImportDone() )
+ {
+ ShapeSharedPtr const& rShape(
+ aMPShapesFunctor.importShape() );
+ if( rShape )
+ mpLayerManager->addShape( rShape );
+ }
+
+ nCurrCount = xMasterPageShapes->getCount() + 1;
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( ShapeLoadFailedException& )
+ {
+ // TODO(E2): Error handling. For now, bail out
+ OSL_ENSURE( false,
+ "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
+ return false;
+
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return false;
+ }
+ }
+ }
+
+ try
+ {
+ // load the normal page shapes
+ // -------------------------------------------------------------------------
+
+ ShapeImporter aShapesFunctor( mxDrawPage,
+ mxDrawPage,
+ maContext,
+ nCurrCount,
+ false );
+
+ while( !aShapesFunctor.isImportDone() )
+ {
+ ShapeSharedPtr const& rShape(
+ aShapesFunctor.importShape() );
+ if( rShape )
+ mpLayerManager->addShape( rShape );
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( ShapeLoadFailedException& )
+ {
+ // TODO(E2): Error handling. For now, bail out
+ OSL_ENSURE( false,
+ "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
+ return false;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return false;
+ }
+
+ mbShapesLoaded = true;
+
+ return true;
+}
+
+basegfx::B2ISize SlideImpl::getSlideSizeImpl() const
+{
+ uno::Reference< beans::XPropertySet > xPropSet(
+ mxDrawPage, uno::UNO_QUERY_THROW );
+
+ sal_Int32 nDocWidth = 0;
+ sal_Int32 nDocHeight = 0;
+ xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= nDocWidth;
+ xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= nDocHeight;
+
+ return basegfx::B2ISize( nDocWidth, nDocHeight );
+}
+
+} // namespace
+
+
+SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const uno::Reference< animations::XAnimationNode >& xRootNode,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const uno::Reference< uno::XComponentContext >& xComponentContext,
+ const ShapeEventListenerMap& rShapeListenerMap,
+ const ShapeCursorMap& rShapeCursorMap,
+ RGBColor const& rUserPaintColor,
+ bool bUserPaintEnabled,
+ bool bIntrinsicAnimationsAllowed,
+ bool bDisableAnimationZOrder )
+{
+ boost::shared_ptr<SlideImpl> pRet( new SlideImpl( xDrawPage, xRootNode, rEventQueue,
+ rEventMultiplexer, rScreenUpdater,
+ rActivitiesQueue, rUserEventQueue,
+ rCursorManager, rViewContainer,
+ xComponentContext, rShapeListenerMap,
+ rShapeCursorMap, rUserPaintColor,
+ bUserPaintEnabled,
+ bIntrinsicAnimationsAllowed,
+ bDisableAnimationZOrder ));
+
+ rEventMultiplexer.addViewHandler( pRet );
+
+ return pRet;
+}
+
+} // namespace internal
+} // namespace slideshow