| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_slideshow.hxx" |
| |
| #include <osl/diagnose.hxx> |
| #include <canvas/debug.hxx> |
| #include <tools/diagnose_ex.h> |
| #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> |
| #include <iostream> |
| |
| using namespace ::com::sun::star; |
| |
| // ----------------------------------------------------------------------------- |
| |
| namespace slideshow |
| { |
| namespace internal |
| { |
| namespace |
| { |
| |
| class SlideImpl : public Slide, |
| public CursorManager, |
| public ViewEventHandler, |
| public ::osl::DebugBase<SlideImpl> |
| { |
| public: |
| SlideImpl( const uno::Reference<drawing::XDrawPage>& xDrawPage, |
| const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages, |
| 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, |
| const PolyPolygonVector& rPolyPolygonVector, |
| RGBColor const& rUserPaintColor, |
| double dUserPaintStrokeWidth, |
| 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; |
| virtual PolyPolygonVector getPolygons(); |
| virtual void drawPolygons() const; |
| virtual bool isPaintOverlayActive() const; |
| virtual void enablePaintOverlay(); |
| virtual void disablePaintOverlay(); |
| virtual void update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth ); |
| |
| |
| // 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(); |
| |
| void activatePaintOverlay(); |
| void deactivatePaintOverlay(); |
| |
| /** 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; |
| |
| /// 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(); |
| |
| /// Add Polygons to the member maPolygons |
| void addPolygons(PolyPolygonVector aPolygons); |
| |
| // 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< drawing::XDrawPagesSupplier > mxDrawPagesSupplier; |
| 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; |
| PolyPolygonVector maPolygons; |
| |
| RGBColor maUserPaintColor; |
| double mdUserPaintStrokeWidth; |
| 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; |
| |
| ///When true, enablePaintOverlay was called and mbUserPaintOverlay = true |
| bool mbPaintOverlayActive; |
| }; |
| |
| |
| ////////////////////////////////////////////////////////////////////////////////// |
| |
| |
| 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<drawing::XDrawPagesSupplier>& xDrawPages, |
| 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, |
| const PolyPolygonVector& rPolyPolygonVector, |
| RGBColor const& aUserPaintColor, |
| double dUserPaintStrokeWidth, |
| bool bUserPaintEnabled, |
| bool bIntrinsicAnimationsAllowed, |
| bool bDisableAnimationZOrder ) : |
| mxDrawPage( xDrawPage ), |
| mxDrawPagesSupplier( xDrawPages ), |
| 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() ), |
| maPolygons(rPolyPolygonVector), |
| maUserPaintColor(aUserPaintColor), |
| mdUserPaintStrokeWidth(dUserPaintStrokeWidth), |
| 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 ), |
| mbPaintOverlayActive( 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); |
| } |
| |
| void SlideImpl::update_settings( bool bUserPaintEnabled, RGBColor const& aUserPaintColor, double dUserPaintStrokeWidth ) |
| { |
| maUserPaintColor = aUserPaintColor; |
| mdUserPaintStrokeWidth = dUserPaintStrokeWidth; |
| mbUserPaintOverlayEnabled = bUserPaintEnabled; |
| } |
| |
| 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(); |
| mxDrawPagesSupplier.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 |
| activatePaintOverlay(); |
| |
| // --------------------------------------------------------------- |
| |
| // 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. |
| deactivatePaintOverlay(); |
| |
| // --------------------------------------------------------------- |
| |
| // 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; |
| } |
| |
| PolyPolygonVector SlideImpl::getPolygons() |
| { |
| if(mbPaintOverlayActive) |
| maPolygons = mpPaintOverlay->getPolygons(); |
| return maPolygons; |
| } |
| |
| 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_OR_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_OR_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_OR_THROW( rView && rView->getCanvas(), |
| "SlideImpl::createCurrentSlideBitmap(): Invalid view" ); |
| ENSURE_OR_THROW( mpLayerManager, |
| "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" ); |
| ENSURE_OR_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_OR_THROW( pBitmap, |
| "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" ); |
| |
| ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() ); |
| |
| ENSURE_OR_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_OR_RETURN_FALSE( mxDrawPage.is(), |
| "SlideImpl::implPrefetchShow(): Invalid draw page" ); |
| ENSURE_OR_RETURN_FALSE( 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 || !mbPaintOverlayActive ) |
| { |
| mbUserPaintOverlayEnabled = true; |
| activatePaintOverlay(); |
| } |
| } |
| |
| void SlideImpl::disablePaintOverlay() |
| { |
| } |
| |
| void SlideImpl::activatePaintOverlay() |
| { |
| if( mbUserPaintOverlayEnabled || !maPolygons.empty() ) |
| { |
| mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor, |
| mdUserPaintStrokeWidth, |
| maContext, |
| maPolygons, |
| mbUserPaintOverlayEnabled ); |
| mbPaintOverlayActive = true; |
| } |
| } |
| |
| void SlideImpl::drawPolygons() const |
| { |
| if( mpPaintOverlay ) |
| mpPaintOverlay->drawPolygons(); |
| } |
| |
| void SlideImpl::addPolygons(PolyPolygonVector aPolygons) |
| { |
| if(!aPolygons.empty()) |
| { |
| for( PolyPolygonVector::iterator aIter=aPolygons.begin(), |
| aEnd=aPolygons.end(); |
| aIter!=aEnd; |
| ++aIter ) |
| { |
| maPolygons.push_back(*aIter); |
| } |
| } |
| } |
| |
| bool SlideImpl::isPaintOverlayActive() const |
| { |
| return mbPaintOverlayActive; |
| } |
| |
| void SlideImpl::deactivatePaintOverlay() |
| { |
| if(mbPaintOverlayActive) |
| maPolygons = mpPaintOverlay->getPolygons(); |
| |
| mpPaintOverlay.reset(); |
| mbPaintOverlayActive = false; |
| } |
| |
| ::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_OR_RETURN_FALSE( 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_OR_RETURN_FALSE( 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_OR_RETURN_FALSE( mxDrawPage.is(), |
| "SlideImpl::loadShapes(): Invalid draw page" ); |
| ENSURE_OR_RETURN_FALSE( 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, |
| mxDrawPagesSupplier, |
| 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 ); |
| } |
| addPolygons(aMPShapesFunctor.getPolygons()); |
| |
| 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, |
| mxDrawPagesSupplier, |
| maContext, |
| nCurrCount, |
| false ); |
| |
| while( !aShapesFunctor.isImportDone() ) |
| { |
| ShapeSharedPtr const& rShape( |
| aShapesFunctor.importShape() ); |
| if( rShape ) |
| mpLayerManager->addShape( rShape ); |
| } |
| addPolygons(aShapesFunctor.getPolygons()); |
| } |
| 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<drawing::XDrawPagesSupplier>& xDrawPages, |
| 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, |
| const PolyPolygonVector& rPolyPolygonVector, |
| RGBColor const& rUserPaintColor, |
| double dUserPaintStrokeWidth, |
| bool bUserPaintEnabled, |
| bool bIntrinsicAnimationsAllowed, |
| bool bDisableAnimationZOrder ) |
| { |
| boost::shared_ptr<SlideImpl> pRet( new SlideImpl( xDrawPage, xDrawPages, xRootNode, rEventQueue, |
| rEventMultiplexer, rScreenUpdater, |
| rActivitiesQueue, rUserEventQueue, |
| rCursorManager, rViewContainer, |
| xComponentContext, rShapeListenerMap, |
| rShapeCursorMap, rPolyPolygonVector, rUserPaintColor, |
| dUserPaintStrokeWidth, bUserPaintEnabled, |
| bIntrinsicAnimationsAllowed, |
| bDisableAnimationZOrder )); |
| |
| rEventMultiplexer.addViewHandler( pRet ); |
| |
| return pRet; |
| } |
| |
| } // namespace internal |
| } // namespace slideshow |