LCOV - code coverage report
Current view: top level - slideshow/source/engine/transitions - slidechangebase.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 188 0.5 %
Date: 2014-11-03 Functions: 2 23 8.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <canvas/debug.hxx>
      22             : #include <tools/diagnose_ex.h>
      23             : #include <canvas/canvastools.hxx>
      24             : #include <basegfx/numeric/ftools.hxx>
      25             : #include <basegfx/polygon/b2dpolygontools.hxx>
      26             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      27             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      28             : #include <cppcanvas/basegfxfactory.hxx>
      29             : 
      30             : #include "slidechangebase.hxx"
      31             : #include "tools.hxx"
      32             : 
      33             : #include <boost/bind.hpp>
      34             : #include <algorithm>
      35             : 
      36             : using namespace com::sun::star;
      37             : 
      38             : namespace slideshow {
      39             : namespace internal {
      40             : 
      41           0 : SlideChangeBase::SlideChangeBase( boost::optional<SlideSharedPtr> const & leavingSlide,
      42             :                                   const SlideSharedPtr&                   pEnteringSlide,
      43             :                                   const SoundPlayerSharedPtr&             pSoundPlayer,
      44             :                                   const UnoViewContainer&                 rViewContainer,
      45             :                                   ScreenUpdater&                          rScreenUpdater,
      46             :                                   EventMultiplexer&                       rEventMultiplexer,
      47             :                                   bool                                    bCreateLeavingSprites,
      48             :                                   bool                                    bCreateEnteringSprites ) :
      49             :       mpSoundPlayer( pSoundPlayer ),
      50             :       mrEventMultiplexer(rEventMultiplexer),
      51             :       mrScreenUpdater(rScreenUpdater),
      52             :       maLeavingSlide( leavingSlide ),
      53             :       mpEnteringSlide( pEnteringSlide ),
      54             :       maViewData(),
      55             :       mrViewContainer(rViewContainer),
      56             :       mbCreateLeavingSprites(bCreateLeavingSprites),
      57             :       mbCreateEnteringSprites(bCreateEnteringSprites),
      58             :       mbSpritesVisible(false),
      59             :       mbFinished(false),
      60           0 :       mbPrefetched(false)
      61             : {
      62           0 :     ENSURE_OR_THROW(
      63             :         pEnteringSlide,
      64             :         "SlideChangeBase::SlideChangeBase(): Invalid entering slide!" );
      65           0 : }
      66             : 
      67           0 : SlideBitmapSharedPtr SlideChangeBase::getLeavingBitmap( const ViewEntry& rViewEntry ) const
      68             : {
      69           0 :     if( !rViewEntry.mpLeavingBitmap )
      70           0 :         rViewEntry.mpLeavingBitmap = createBitmap(rViewEntry.mpView,
      71           0 :                                                   maLeavingSlide);
      72             : 
      73           0 :     return rViewEntry.mpLeavingBitmap;
      74             : }
      75             : 
      76           0 : SlideBitmapSharedPtr SlideChangeBase::getEnteringBitmap( const ViewEntry& rViewEntry ) const
      77             : {
      78           0 :     if( !rViewEntry.mpEnteringBitmap )
      79           0 :         rViewEntry.mpEnteringBitmap = createBitmap( rViewEntry.mpView,
      80           0 :                                                     boost::optional<SlideSharedPtr>(mpEnteringSlide) );
      81             : 
      82           0 :     return rViewEntry.mpEnteringBitmap;
      83             : }
      84             : 
      85           0 : SlideBitmapSharedPtr SlideChangeBase::createBitmap( const UnoViewSharedPtr&                rView,
      86             :                                                     const boost::optional<SlideSharedPtr>& rSlide ) const
      87             : {
      88           0 :     SlideBitmapSharedPtr pRet;
      89           0 :     if( !rSlide )
      90           0 :         return pRet;
      91             : 
      92           0 :     SlideSharedPtr const & pSlide = *rSlide;
      93           0 :     if( !pSlide )
      94             :     {
      95             :         // TODO(P3): No need to generate a bitmap here. This only made
      96             :         // the code more uniform. Faster would be to simply clear the
      97             :         // sprite to black.
      98             : 
      99             :         // create empty, black-filled bitmap
     100             :         const basegfx::B2ISize slideSizePixel(
     101           0 :             getSlideSizePixel( basegfx::B2DSize( mpEnteringSlide->getSlideSize() ),
     102           0 :                                rView ));
     103             : 
     104           0 :         cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
     105             : 
     106             :         // create a bitmap of appropriate size
     107             :         cppcanvas::BitmapSharedPtr pBitmap(
     108           0 :             cppcanvas::BaseGfxFactory::getInstance().createBitmap(
     109             :                 pCanvas,
     110           0 :                 slideSizePixel ) );
     111             : 
     112           0 :         ENSURE_OR_THROW(
     113             :             pBitmap,
     114             :             "SlideChangeBase::createBitmap(): Cannot create page bitmap" );
     115             : 
     116             :         cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas(
     117           0 :             pBitmap->getBitmapCanvas() );
     118             : 
     119           0 :         ENSURE_OR_THROW( pBitmapCanvas,
     120             :                           "SlideChangeBase::createBitmap(): "
     121             :                           "Cannot create page bitmap canvas" );
     122             : 
     123             :         // set transformation to identitiy (->device pixel)
     124           0 :         pBitmapCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
     125             : 
     126             :         // clear bitmap to black
     127             :         fillRect( pBitmapCanvas,
     128             :                   ::basegfx::B2DRectangle( 0.0, 0.0,
     129           0 :                                            slideSizePixel.getX(),
     130           0 :                                            slideSizePixel.getY() ),
     131           0 :                   0x000000FFU );
     132             : 
     133           0 :         pRet.reset( new SlideBitmap( pBitmap ));
     134             :     }
     135             :     else
     136             :     {
     137           0 :         pRet = pSlide->getCurrentSlideBitmap( rView );
     138             :     }
     139             : 
     140           0 :     return pRet;
     141             : }
     142             : 
     143           0 : ::basegfx::B2ISize SlideChangeBase::getEnteringSlideSizePixel( const UnoViewSharedPtr& pView ) const
     144             : {
     145           0 :     return getSlideSizePixel( basegfx::B2DSize( mpEnteringSlide->getSlideSize() ),
     146           0 :                               pView );
     147             : }
     148             : 
     149           0 : void SlideChangeBase::renderBitmap(
     150             :     SlideBitmapSharedPtr const & pSlideBitmap,
     151             :     cppcanvas::CanvasSharedPtr const & pCanvas )
     152             : {
     153           0 :     if( pSlideBitmap && pCanvas )
     154             :     {
     155             :         // need to render without any transformation (we
     156             :         // assume device units):
     157             :         const basegfx::B2DHomMatrix viewTransform(
     158           0 :             pCanvas->getTransformation() );
     159             :         const basegfx::B2DPoint pageOrigin(
     160           0 :             viewTransform * basegfx::B2DPoint() );
     161             :         const cppcanvas::CanvasSharedPtr pDevicePixelCanvas(
     162           0 :             pCanvas->clone() );
     163             : 
     164             :         // render at output position, don't modify bitmap object (no move!):
     165             :         const basegfx::B2DHomMatrix transform(basegfx::tools::createTranslateB2DHomMatrix(
     166           0 :             pageOrigin.getX(), pageOrigin.getY()));
     167             : 
     168           0 :         pDevicePixelCanvas->setTransformation( transform );
     169           0 :         pSlideBitmap->draw( pDevicePixelCanvas );
     170             :     }
     171           0 : }
     172             : 
     173           0 : void SlideChangeBase::prefetch( const AnimatableShapeSharedPtr&,
     174             :                                 const ShapeAttributeLayerSharedPtr& )
     175             : {
     176             :     // we're a one-shot activity, and already finished
     177           0 :     if( mbFinished || mbPrefetched )
     178           0 :         return;
     179             : 
     180             :     // register ourselves for view change events
     181           0 :     mrEventMultiplexer.addViewHandler( shared_from_this() );
     182             : 
     183             :     // init views and create slide bitmaps
     184             :     std::for_each( mrViewContainer.begin(),
     185             :                    mrViewContainer.end(),
     186             :                    boost::bind( &SlideChangeBase::viewAdded,
     187             :                                 this,
     188           0 :                                 _1 ));
     189             : 
     190           0 :     mbPrefetched = true;
     191             : }
     192             : 
     193           0 : void SlideChangeBase::start( const AnimatableShapeSharedPtr&     rShape,
     194             :                              const ShapeAttributeLayerSharedPtr& rLayer )
     195             : {
     196             :     // we're a one-shot activity, and already finished
     197           0 :     if( mbFinished )
     198           0 :         return;
     199             : 
     200           0 :     prefetch(rShape,rLayer); // no-op, if already done
     201             : 
     202             :     // get the subclasses a chance to do any specific initialization before run
     203           0 :     for ( ViewsVecT::const_iterator aCurr( beginViews() ), aEnd( endViews() ); aCurr != aEnd; ++aCurr )
     204           0 :         prepareForRun( *aCurr, aCurr->mpView->getCanvas() );
     205             : 
     206             :     // start accompanying sound effect, if any
     207           0 :     if( mpSoundPlayer )
     208             :     {
     209           0 :         mpSoundPlayer->startPlayback();
     210             :         // xxx todo: for now, presentation.cxx takes care about the slide
     211             :         // #i50492#  transition sound object, so just release it here
     212           0 :         mpSoundPlayer.reset();
     213             :     }
     214             : }
     215             : 
     216           0 : void SlideChangeBase::end()
     217             : {
     218             :     // we're a one-shot activity, and already finished
     219           0 :     if( mbFinished )
     220           0 :         return;
     221             : 
     222             :     try
     223             :     {
     224             :         // draw fully entered bitmap:
     225           0 :         ViewsVecT::const_iterator aCurr( beginViews() );
     226           0 :         const ViewsVecT::const_iterator aEnd( endViews() );
     227           0 :         while( aCurr != aEnd )
     228             :         {
     229             :             // fully clear view content to background color
     230           0 :             aCurr->mpView->clearAll();
     231             : 
     232           0 :             const SlideBitmapSharedPtr pSlideBitmap( getEnteringBitmap( *aCurr ));
     233           0 :             pSlideBitmap->clip( basegfx::B2DPolyPolygon() /* no clipping */ );
     234           0 :             aCurr->mpView->clearAll();
     235             :             renderBitmap( pSlideBitmap,
     236           0 :                           aCurr->mpView->getCanvas() );
     237             : 
     238           0 :             ++aCurr;
     239           0 :         }
     240             :     }
     241           0 :     catch( uno::Exception& )
     242             :     {
     243             :         // make sure releasing below happens
     244             :     }
     245             : 
     246             :     // swap changes to screen
     247           0 :     mrScreenUpdater.notifyUpdate();
     248             : 
     249             :     // make object dysfunctional
     250           0 :     mbFinished = true;
     251           0 :     ViewsVecT().swap(maViewData);
     252           0 :     maLeavingSlide.reset();
     253           0 :     mpEnteringSlide.reset();
     254             : 
     255             :     // sprites have been binned above
     256           0 :     mbSpritesVisible = false;
     257             : 
     258             :     // remove also from event multiplexer, we're dead anyway
     259           0 :     mrEventMultiplexer.removeViewHandler( shared_from_this() );
     260             : }
     261             : 
     262           0 : bool SlideChangeBase::operator()( double nValue )
     263             : {
     264           0 :     if( mbFinished )
     265           0 :         return false;
     266             : 
     267           0 :     const std::size_t nEntries( maViewData.size() );
     268           0 :     bool bSpritesVisible( mbSpritesVisible );
     269             : 
     270           0 :     for( ::std::size_t i=0; i<nEntries; ++i )
     271             :     {
     272             :         // calc sprite offsets. The enter/leaving bitmaps are only
     273             :         // as large as the actual slides. For scaled-down
     274             :         // presentations, we have to move the left, top edge of
     275             :         // those bitmaps to the actual position, governed by the
     276             :         // given view transform. The aSpritePosPixel local
     277             :         // variable is already in device coordinate space
     278             :         // (i.e. pixel).
     279             : 
     280           0 :         ViewEntry& rViewEntry( maViewData[i] );
     281           0 :         const ::cppcanvas::CanvasSharedPtr& rCanvas( rViewEntry.mpView->getCanvas() );
     282           0 :         ::cppcanvas::CustomSpriteSharedPtr& rInSprite( rViewEntry.mpInSprite );
     283           0 :         ::cppcanvas::CustomSpriteSharedPtr& rOutSprite( rViewEntry.mpOutSprite );
     284             : 
     285             :         // TODO(F2): Properly respect clip here.
     286             : 
     287             :         // Might have to be transformed, too.
     288             :         const ::basegfx::B2DHomMatrix aViewTransform(
     289           0 :             rViewEntry.mpView->getTransformation() );
     290             :         const ::basegfx::B2DPoint aSpritePosPixel(
     291           0 :             aViewTransform * ::basegfx::B2DPoint() );
     292             : 
     293             :         // move sprite to final output position, in
     294             :         // device coordinates
     295           0 :         if( rOutSprite )
     296           0 :             rOutSprite->movePixel( aSpritePosPixel );
     297           0 :         if( rInSprite )
     298           0 :             rInSprite->movePixel( aSpritePosPixel );
     299             : 
     300           0 :         if( !mbSpritesVisible )
     301             :         {
     302           0 :             if( rOutSprite )
     303             :             {
     304             :                 // only render once: clipping is done
     305             :                 // exclusively with the sprite
     306             :                 const ::cppcanvas::CanvasSharedPtr pOutContentCanvas(
     307           0 :                     rOutSprite->getContentCanvas() );
     308           0 :                 if( pOutContentCanvas)
     309             :                 {
     310             :                     // TODO(Q2): Use basegfx bitmaps here
     311             : 
     312             :                     // TODO(F1): SlideBitmap is not fully portable
     313             :                     // between different canvases!
     314             : 
     315             :                     // render the content
     316             :                     OSL_ASSERT( getLeavingBitmap( rViewEntry ) );
     317           0 :                     if( getLeavingBitmap( rViewEntry ) )
     318           0 :                         getLeavingBitmap( rViewEntry )->draw( pOutContentCanvas );
     319           0 :                 }
     320             :             }
     321             : 
     322           0 :             if( rInSprite )
     323             :             {
     324             :                 // only render once: clipping is done
     325             :                 // exclusively with the sprite
     326             :                 const ::cppcanvas::CanvasSharedPtr pInContentCanvas(
     327           0 :                     rInSprite->getContentCanvas() );
     328           0 :                 if( pInContentCanvas )
     329             :                 {
     330             :                     // TODO(Q2): Use basegfx bitmaps here
     331             : 
     332             :                     // TODO(F1): SlideBitmap is not fully portable
     333             :                     // between different canvases!
     334             : 
     335             :                     // render the content
     336           0 :                     getEnteringBitmap( rViewEntry )->draw( pInContentCanvas );
     337           0 :                 }
     338             :             }
     339             :         }
     340             : 
     341           0 :         if( rOutSprite )
     342           0 :             performOut( rOutSprite, rViewEntry, rCanvas, nValue );
     343           0 :         if( rInSprite )
     344           0 :             performIn( rInSprite, rViewEntry, rCanvas, nValue );
     345             : 
     346             :         // finishing deeds for first run.
     347           0 :         if( !mbSpritesVisible)
     348             :         {
     349             :             // enable sprites:
     350           0 :             if( rOutSprite )
     351           0 :                 rOutSprite->show();
     352           0 :             if( rInSprite )
     353           0 :                 rInSprite->show();
     354           0 :             bSpritesVisible = true;
     355             :         }
     356           0 :     } // for_each( sprite )
     357             : 
     358           0 :     mbSpritesVisible = bSpritesVisible;
     359           0 :     mrScreenUpdater.notifyUpdate();
     360             : 
     361           0 :     return true;
     362             : }
     363             : 
     364           0 : void SlideChangeBase::prepareForRun(
     365             :     const ViewEntry& /* rViewEntry */,
     366             :     const boost::shared_ptr<cppcanvas::Canvas>& /* rDestinationCanvas */ )
     367             : {
     368           0 : }
     369             : 
     370           0 : void SlideChangeBase::performIn(
     371             :     const cppcanvas::CustomSpriteSharedPtr&   /*rSprite*/,
     372             :     const ViewEntry&                          /*rViewEntry*/,
     373             :     const cppcanvas::CanvasSharedPtr&         /*rDestinationCanvas*/,
     374             :     double                                    /*t*/ )
     375             : {
     376           0 : }
     377             : 
     378           0 : void SlideChangeBase::performOut(
     379             :     const cppcanvas::CustomSpriteSharedPtr&  /*rSprite*/,
     380             :     const ViewEntry&                         /*rViewEntry*/,
     381             :     const cppcanvas::CanvasSharedPtr&        /*rDestinationCanvas*/,
     382             :     double                                   /*t*/ )
     383             : {
     384           0 : }
     385             : 
     386           0 : double SlideChangeBase::getUnderlyingValue() const
     387             : {
     388           0 :     return 0.0;     // though this should be used in concert with
     389             :                     // ActivitiesFactory::createSimpleActivity, better
     390             :                     // explicitly name our start value.
     391             :                     // Permissible range for operator() above is [0,1]
     392             : }
     393             : 
     394           0 : void SlideChangeBase::viewAdded( const UnoViewSharedPtr& rView )
     395             : {
     396             :     // we're a one-shot activity, and already finished
     397           0 :     if( mbFinished )
     398           0 :         return;
     399             : 
     400           0 :     maViewData.push_back( ViewEntry(rView) );
     401             : 
     402           0 :     ViewEntry& rEntry( maViewData.back() );
     403           0 :     getEnteringBitmap( rEntry );
     404           0 :     getLeavingBitmap( rEntry );
     405           0 :     addSprites( rEntry );
     406             : }
     407             : 
     408           0 : void SlideChangeBase::viewRemoved( const UnoViewSharedPtr& rView )
     409             : {
     410             :     // we're a one-shot activity, and already finished
     411           0 :     if( mbFinished )
     412           0 :         return;
     413             : 
     414             :     // erase corresponding entry from maViewData
     415             :     maViewData.erase(
     416             :         std::remove_if(
     417             :             maViewData.begin(),
     418             :             maViewData.end(),
     419             :             boost::bind(
     420             :                 std::equal_to<UnoViewSharedPtr>(),
     421             :                 rView,
     422             :                 // select view:
     423           0 :                 boost::bind( &ViewEntry::getView, _1 ))),
     424           0 :         maViewData.end() );
     425             : }
     426             : 
     427           0 : void SlideChangeBase::viewChanged( const UnoViewSharedPtr& rView )
     428             : {
     429             :     // we're a one-shot activity, and already finished
     430           0 :     if( mbFinished )
     431           0 :         return;
     432             : 
     433             :     // find entry corresponding to modified view
     434             :     ViewsVecT::iterator aModifiedEntry(
     435             :         std::find_if(
     436             :             maViewData.begin(),
     437             :             maViewData.end(),
     438             :             boost::bind(
     439             :                 std::equal_to<UnoViewSharedPtr>(),
     440             :                 rView,
     441             :                 // select view:
     442           0 :                 boost::bind( &ViewEntry::getView, _1 ) )));
     443             : 
     444             :     OSL_ASSERT( aModifiedEntry != maViewData.end() );
     445           0 :     if( aModifiedEntry == maViewData.end() )
     446           0 :         return;
     447             : 
     448             :     // clear stale info (both bitmaps and sprites prolly need a
     449             :     // resize)
     450           0 :     clearViewEntry( *aModifiedEntry );
     451           0 :     addSprites( *aModifiedEntry );
     452             : }
     453             : 
     454           0 : void SlideChangeBase::viewsChanged()
     455             : {
     456             :     // we're a one-shot activity, and already finished
     457           0 :     if( mbFinished )
     458           0 :         return;
     459             : 
     460           0 :     ViewsVecT::iterator       aIter( maViewData.begin() );
     461           0 :     ViewsVecT::iterator const aEnd ( maViewData.end() );
     462           0 :     while( aIter != aEnd )
     463             :     {
     464             :         // clear stale info (both bitmaps and sprites prolly need a
     465             :         // resize)
     466           0 :         clearViewEntry( *aIter );
     467           0 :         addSprites( *aIter );
     468             : 
     469           0 :         ++aIter;
     470             :     }
     471             : }
     472             : 
     473           0 : cppcanvas::CustomSpriteSharedPtr SlideChangeBase::createSprite(
     474             :     UnoViewSharedPtr const & pView,
     475             :     basegfx::B2DSize const & rSpriteSize,
     476             :     double                   nPrio ) const
     477             : {
     478             :     // TODO(P2): change to bitmapsprite once that's working
     479             :     const cppcanvas::CustomSpriteSharedPtr pSprite(
     480           0 :         pView->createSprite( rSpriteSize,
     481           0 :                              nPrio ));
     482             : 
     483             :     // alpha default is 0.0, which seems to be
     484             :     // a bad idea when viewing content...
     485           0 :     pSprite->setAlpha( 1.0 );
     486           0 :     if (mbSpritesVisible)
     487           0 :         pSprite->show();
     488             : 
     489           0 :     return pSprite;
     490             : }
     491             : 
     492           0 : void SlideChangeBase::addSprites( ViewEntry& rEntry )
     493             : {
     494           0 :     if( mbCreateLeavingSprites && maLeavingSlide )
     495             :     {
     496             :         // create leaving sprite:
     497             :         const basegfx::B2ISize leavingSlideSizePixel(
     498           0 :             getLeavingBitmap( rEntry )->getSize() );
     499             : 
     500           0 :         rEntry.mpOutSprite = createSprite( rEntry.mpView,
     501             :                                            basegfx::B2DSize( leavingSlideSizePixel ),
     502           0 :                                            100 );
     503             :     }
     504             : 
     505           0 :     if( mbCreateEnteringSprites )
     506             :     {
     507             :         // create entering sprite:
     508             :         const basegfx::B2ISize enteringSlideSizePixel(
     509           0 :             getSlideSizePixel( basegfx::B2DSize( mpEnteringSlide->getSlideSize() ),
     510           0 :                                rEntry.mpView ));
     511             : 
     512           0 :         rEntry.mpInSprite = createSprite( rEntry.mpView,
     513             :                                           basegfx::B2DSize( enteringSlideSizePixel ),
     514           0 :                                           101 );
     515             :     }
     516           0 : }
     517             : 
     518           0 : void SlideChangeBase::clearViewEntry( ViewEntry& rEntry )
     519             : {
     520             :     // clear stale info (both bitmaps and sprites prolly need a
     521             :     // resize)
     522           0 :     rEntry.mpEnteringBitmap.reset();
     523           0 :     rEntry.mpLeavingBitmap.reset();
     524           0 :     rEntry.mpInSprite.reset();
     525           0 :     rEntry.mpOutSprite.reset();
     526           0 : }
     527             : 
     528             : } // namespace internal
     529           6 : } // namespace presentation
     530             : 
     531             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10