LCOV - code coverage report
Current view: top level - canvas/source/vcl - spritecanvashelper.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 228 0.0 %
Date: 2014-11-03 Functions: 0 31 0.0 %
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/verbosetrace.hxx>
      24             : #include <canvas/canvastools.hxx>
      25             : 
      26             : #include <vcl/canvastools.hxx>
      27             : #include <vcl/outdev.hxx>
      28             : #include <vcl/window.hxx>
      29             : #include <vcl/bitmapex.hxx>
      30             : 
      31             : #include <basegfx/range/b2drectangle.hxx>
      32             : #include <basegfx/tools/canvastools.hxx>
      33             : 
      34             : #include <boost/cast.hpp>
      35             : 
      36             : #include "spritecanvashelper.hxx"
      37             : #include "canvascustomsprite.hxx"
      38             : 
      39             : using namespace ::com::sun::star;
      40             : 
      41             : #define FPS_BOUNDS Rectangle(0,0,130,90)
      42             : #define INFO_COLOR COL_RED
      43             : 
      44             : namespace vclcanvas
      45             : {
      46             :     namespace
      47             :     {
      48             :         /** Sprite redraw at original position
      49             : 
      50             :             Used to repaint the whole canvas (background and all
      51             :             sprites)
      52             :          */
      53           0 :         void spriteRedraw( OutputDevice&                      rOutDev,
      54             :                            const ::canvas::Sprite::Reference& rSprite )
      55             :         {
      56             :             // downcast to derived vclcanvas::Sprite interface, which
      57             :             // provides the actual redraw methods.
      58           0 :             ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw(rOutDev,
      59           0 :                                                                             true);
      60           0 :         }
      61             : 
      62           0 :         double calcNumPixel( const ::canvas::Sprite::Reference& rSprite )
      63             :         {
      64             :             const ::basegfx::B2DSize& rSize(
      65           0 :                 ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->getSizePixel() );
      66             : 
      67           0 :             return rSize.getX() * rSize.getY();
      68             :         }
      69             : 
      70           0 :         void repaintBackground( OutputDevice&               rOutDev,
      71             :                                 OutputDevice&               rBackBuffer,
      72             :                                 const ::basegfx::B2DRange&  rArea )
      73             :         {
      74           0 :             const ::Point& rPos( ::vcl::unotools::pointFromB2DPoint( rArea.getMinimum()) );
      75           0 :             const ::Size& rSize( ::vcl::unotools::sizeFromB2DSize( rArea.getRange()) );
      76             : 
      77           0 :             rOutDev.DrawOutDev( rPos, rSize, rPos, rSize, rBackBuffer );
      78           0 :         }
      79             : 
      80           0 :         void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite,
      81             :                                      OutputDevice&                      rOutDev,
      82             :                                      const ::basegfx::B2IRange&         rArea )
      83             :         {
      84             :             const Rectangle& rRequestedArea(
      85           0 :                 ::vcl::unotools::rectangleFromB2IRectangle( rArea ) );
      86             : 
      87             :             // clip output to actual update region (otherwise a)
      88             :             // wouldn't save much render time, and b) will clutter
      89             :             // scrolled sprite content outside this area)
      90           0 :             rOutDev.EnableMapMode( false );
      91           0 :             rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW );
      92           0 :             rOutDev.SetClipRegion(vcl::Region(rRequestedArea));
      93             : 
      94             :             // repaint affected sprite directly to output device (at
      95             :             // the actual screen output position)
      96             :             ::boost::polymorphic_downcast< Sprite* >(
      97           0 :                 rSprite.get() )->redraw( rOutDev,
      98           0 :                                          false ); // rendering
      99             :                                                   // directly to
     100             :                                                   // frontbuffer
     101           0 :         }
     102             : 
     103             :         /** Repaint sprite at original position
     104             : 
     105             :             Used for opaque updates, which render directly to the
     106             :             front buffer.
     107             :          */
     108           0 :         void spriteRedrawStub( OutputDevice&                      rOutDev,
     109             :                                const ::canvas::Sprite::Reference& rSprite )
     110             :         {
     111           0 :             if( rSprite.is() )
     112             :             {
     113             :                 ::boost::polymorphic_downcast< Sprite* >(
     114           0 :                     rSprite.get() )->redraw( rOutDev,
     115           0 :                                              false );
     116             :             }
     117           0 :         }
     118             : 
     119             :         /** Repaint sprite at given position
     120             : 
     121             :             Used for generic update, which renders into vdev of
     122             :             adapted size.
     123             :          */
     124           0 :         void spriteRedrawStub2( OutputDevice&                       rOutDev,
     125             :                                 const ::basegfx::B2DPoint&          rOutPos,
     126             :                                 const ::canvas::Sprite::Reference&  rSprite )
     127             :         {
     128           0 :             if( rSprite.is() )
     129             :             {
     130             :                 Sprite* pSprite = ::boost::polymorphic_downcast< Sprite* >(
     131           0 :                     rSprite.get() );
     132             : 
     133             :                 // calc relative sprite position in rUpdateArea (which
     134             :                 // need not be the whole screen!)
     135           0 :                 const ::basegfx::B2DPoint& rSpriteScreenPos( pSprite->getPosPixel() );
     136           0 :                 const ::basegfx::B2DPoint& rSpriteRenderPos( rSpriteScreenPos - rOutPos );
     137             : 
     138           0 :                 pSprite->redraw( rOutDev, rSpriteRenderPos, true );
     139             :             }
     140           0 :         }
     141             : 
     142             :         /** Repaint sprite at original position
     143             : 
     144             :             Used for opaque updates from scrollUpdate(), which render
     145             :             directly to the front buffer.
     146             :          */
     147           0 :         void spriteRedrawStub3( OutputDevice&                                       rOutDev,
     148             :                                 const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
     149             :         {
     150           0 :             const ::canvas::Sprite::Reference& rSprite( rComponent.second.getSprite() );
     151             : 
     152           0 :             if( rSprite.is() )
     153             :             {
     154             :                 ::boost::polymorphic_downcast< Sprite* >(
     155           0 :                     rSprite.get() )->redraw( rOutDev,
     156           0 :                                              false );
     157             :             }
     158           0 :         }
     159             : 
     160           0 :         void renderInfoText( OutputDevice&          rOutDev,
     161             :                              const OUString& rStr,
     162             :                              const Point&           rPos )
     163             :         {
     164           0 :             vcl::Font aVCLFont;
     165           0 :             aVCLFont.SetHeight( 20 );
     166           0 :             aVCLFont.SetColor( Color( INFO_COLOR ) );
     167             : 
     168           0 :             rOutDev.SetTextAlign(ALIGN_TOP);
     169           0 :             rOutDev.SetTextColor( Color( INFO_COLOR ) );
     170           0 :             rOutDev.SetFont( aVCLFont );
     171             : 
     172           0 :             rOutDev.DrawText( rPos, rStr );
     173           0 :         }
     174             : 
     175             :     }
     176             : 
     177           0 :     SpriteCanvasHelper::SpriteCanvasHelper() :
     178             :         mpRedrawManager( NULL ),
     179             :         mpOwningSpriteCanvas( NULL ),
     180             :         maVDev(),
     181             :         maLastUpdate(),
     182             :         mbShowFrameInfo( false ),
     183             :         mbShowSpriteBounds( false ),
     184           0 :         mbIsUnsafeScrolling( false )
     185             :     {
     186             : #if OSL_DEBUG_LEVEL > 2
     187             :         // inverse defaults for verbose debug mode
     188             :         mbShowSpriteBounds = mbShowFrameInfo = true;
     189             : #endif
     190           0 :     }
     191             : 
     192           0 :     void SpriteCanvasHelper::init( const OutDevProviderSharedPtr& rOutDev,
     193             :                                    SpriteCanvas&                  rOwningSpriteCanvas,
     194             :                                    ::canvas::SpriteRedrawManager& rManager,
     195             :                                    bool                           bProtect,
     196             :                                    bool                           bHaveAlpha )
     197             :     {
     198           0 :         mpOwningSpriteCanvas = &rOwningSpriteCanvas;
     199           0 :         mpRedrawManager = &rManager;
     200             : 
     201           0 :         CanvasHelper::init(rOwningSpriteCanvas,rOutDev,bProtect,bHaveAlpha);
     202           0 :     }
     203             : 
     204           0 :     void SpriteCanvasHelper::disposing()
     205             :     {
     206           0 :         mpRedrawManager = NULL;
     207           0 :         mpOwningSpriteCanvas = NULL;
     208             : 
     209             :         // forward to base
     210           0 :         CanvasHelper::disposing();
     211           0 :     }
     212             : 
     213           0 :     uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
     214             :         const uno::Reference< rendering::XAnimation >&  )
     215             :     {
     216           0 :         return uno::Reference< rendering::XAnimatedSprite >();
     217             :     }
     218             : 
     219           0 :     uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
     220             :         const uno::Sequence< uno::Reference< rendering::XBitmap > >& ,
     221             :         sal_Int8                                                      )
     222             :     {
     223           0 :         return uno::Reference< rendering::XAnimatedSprite >();
     224             :     }
     225             : 
     226           0 :     uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
     227             :     {
     228           0 :         if( !mpRedrawManager || !mpDevice )
     229           0 :             return uno::Reference< rendering::XCustomSprite >(); // we're disposed
     230             : 
     231             :         return uno::Reference< rendering::XCustomSprite >(
     232             :             new CanvasCustomSprite( spriteSize,
     233             :                                     *mpDevice,
     234             :                                     mpOwningSpriteCanvas,
     235             :                                     mpOwningSpriteCanvas->getFrontBuffer(),
     236           0 :                                     mbShowSpriteBounds ) );
     237             :     }
     238             : 
     239           0 :     uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >&  )
     240             :     {
     241           0 :         return uno::Reference< rendering::XSprite >();
     242             :     }
     243             : 
     244           0 :     bool SpriteCanvasHelper::updateScreen( bool bUpdateAll,
     245             :                                            bool&    io_bSurfaceDirty )
     246             :     {
     247           0 :         if( !mpRedrawManager ||
     248           0 :             !mpOwningSpriteCanvas ||
     249           0 :             !mpOwningSpriteCanvas->getFrontBuffer() ||
     250           0 :             !mpOwningSpriteCanvas->getBackBuffer() )
     251             :         {
     252           0 :             return false; // disposed, or otherwise dysfunctional
     253             :         }
     254             : 
     255             :         // commit to backbuffer
     256           0 :         flush();
     257             : 
     258           0 :         OutputDevice&       rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     259           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     260           0 :         OutputDevice&       rBackOutDev( pBackBuffer->getOutDev() );
     261             : 
     262             :         // actual OutputDevice is a shared resource - restore its
     263             :         // state when done.
     264           0 :         tools::OutDevStateKeeper aStateKeeper( rOutDev );
     265             : 
     266           0 :         const Size  aOutDevSize( rBackOutDev.GetOutputSizePixel() );
     267           0 :         const Point aEmptyPoint(0,0);
     268             : 
     269           0 :         vcl::Window* pTargetWindow = NULL;
     270           0 :         if( rOutDev.GetOutDevType() == OUTDEV_WINDOW )
     271             :         {
     272           0 :             pTargetWindow = &static_cast<vcl::Window&>(rOutDev); // TODO(Q3): Evil downcast.
     273             : 
     274             :             // we're double-buffered, thus no need for paint area-limiting
     275             :             // clips. besides that, will interfere with animations (as for
     276             :             // Window-invalidate repaints, only parts of the window will
     277             :             // be redrawn otherwise)
     278             :             const vcl::Region aFullWindowRegion( Rectangle(aEmptyPoint,
     279           0 :                                                       aOutDevSize) );
     280           0 :             pTargetWindow->ExpandPaintClipRegion(aFullWindowRegion);
     281             :         }
     282             : 
     283             :         // TODO(P1): Might be worthwile to track areas of background
     284             :         // changes, too.
     285           0 :         if( !bUpdateAll && !io_bSurfaceDirty )
     286             :         {
     287           0 :             if( mbShowFrameInfo )
     288             :             {
     289             :                 // also repaint background below frame counter (fake
     290             :                 // that as a sprite vanishing in this area)
     291             :                 mpRedrawManager->updateSprite( ::canvas::Sprite::Reference(),
     292             :                                                ::basegfx::B2DPoint(),
     293             :                                                ::basegfx::B2DRectangle( 0.0, 0.0,
     294           0 :                                                                         FPS_BOUNDS.Right(),
     295           0 :                                                                         FPS_BOUNDS.Bottom() ) );
     296             :             }
     297             : 
     298             :             // background has not changed, so we're free to optimize
     299             :             // repaint to areas where a sprite has changed
     300             : 
     301             :             // process each independent area of overlapping sprites
     302             :             // separately.
     303           0 :             mpRedrawManager->forEachSpriteArea( *this );
     304             :         }
     305             :         else
     306             :         {
     307             :             // background has changed, so we currently have no choice
     308             :             // but repaint everything (or caller requested that)
     309             : 
     310           0 :             maVDev->SetOutputSizePixel( aOutDevSize );
     311           0 :             maVDev->EnableMapMode( false );
     312           0 :             maVDev->DrawOutDev( aEmptyPoint, aOutDevSize,
     313             :                                 aEmptyPoint, aOutDevSize,
     314           0 :                                 rBackOutDev );
     315             : 
     316             :             // repaint all active sprites on top of background into
     317             :             // VDev.
     318             :             mpRedrawManager->forEachSprite(
     319             :                 ::boost::bind(
     320             :                     &spriteRedraw,
     321           0 :                     ::boost::ref( maVDev.get() ),
     322           0 :                     _1 ) );
     323             : 
     324             :             // flush to screen
     325           0 :             rOutDev.EnableMapMode( false );
     326           0 :             rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW );
     327           0 :             rOutDev.SetClipRegion();
     328             :             rOutDev.DrawOutDev( aEmptyPoint, aOutDevSize,
     329             :                                 aEmptyPoint, aOutDevSize,
     330           0 :                                 *maVDev );
     331             :         }
     332             : 
     333             :         // change record vector must be cleared, for the next turn of
     334             :         // rendering and sprite changing
     335           0 :         mpRedrawManager->clearChangeRecords();
     336             : 
     337           0 :         io_bSurfaceDirty = false;
     338             : 
     339           0 :         if( mbShowFrameInfo )
     340             :         {
     341           0 :             renderFrameCounter( rOutDev );
     342           0 :             renderSpriteCount( rOutDev );
     343           0 :             renderMemUsage( rOutDev );
     344             :         }
     345             : 
     346             : #if OSL_DEBUG_LEVEL > 2
     347             :         static ::canvas::tools::ElapsedTime aElapsedTime;
     348             : 
     349             :         // log time immediately after surface flip
     350             :         OSL_TRACE( "SpriteCanvasHelper::updateScreen(): flip done at %f",
     351             :                    aElapsedTime.getElapsedTime() );
     352             : #endif
     353             : 
     354             :         // sync output with screen, to ensure that we don't queue up
     355             :         // render requests (calling code might rely on timing,
     356             :         // i.e. assume that things are visible on screen after
     357             :         // updateScreen() returns).
     358           0 :         if( pTargetWindow )
     359             :         {
     360             :             // commit to screen
     361           0 :             pTargetWindow->Sync();
     362             :         }
     363             : 
     364           0 :         return true;
     365             :     }
     366             : 
     367           0 :     void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
     368             :     {
     369           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     370             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     371             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     372             :                          "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
     373             : 
     374           0 :         OutputDevice&       rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     375           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     376           0 :         OutputDevice&       rBackOutDev( pBackBuffer->getOutDev() );
     377             : 
     378           0 :         repaintBackground( rOutDev, rBackOutDev, rUpdateRect );
     379           0 :     }
     380             : 
     381           0 :     void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange&                       rMoveStart,
     382             :                                            const ::basegfx::B2DRange&                       rMoveEnd,
     383             :                                            const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
     384             :     {
     385           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     386             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     387             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     388             :                          "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
     389             : 
     390           0 :         OutputDevice&       rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     391           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     392           0 :         OutputDevice&       rBackOutDev( pBackBuffer->getOutDev() );
     393             : 
     394           0 :         const Size&                rTargetSizePixel( rOutDev.GetOutputSizePixel() );
     395             :         const ::basegfx::B2IRange  aOutputBounds( 0,0,
     396           0 :                                                   rTargetSizePixel.Width(),
     397           0 :                                                   rTargetSizePixel.Height() );
     398             : 
     399             :         // round rectangles to integer pixel. Note: have to be
     400             :         // extremely careful here, to avoid off-by-one errors for
     401             :         // the destination area: otherwise, the next scroll update
     402             :         // would copy pixel that are not supposed to be part of
     403             :         // the sprite.
     404             :         ::basegfx::B2IRange aSourceRect(
     405           0 :             ::canvas::tools::spritePixelAreaFromB2DRange( rMoveStart ) );
     406             :         const ::basegfx::B2IRange& rDestRect(
     407           0 :             ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
     408           0 :         ::basegfx::B2IPoint aDestPos( rDestRect.getMinimum() );
     409             : 
     410           0 :         ::std::vector< ::basegfx::B2IRange > aUnscrollableAreas;
     411             : 
     412             :         // Since strictly speaking, this scroll algorithm is plain
     413             :         // buggy, the scrolled area might actually lie _below_ another
     414             :         // window - we've made this feature configurable via
     415             :         // mbIsUnsafeScrolling.
     416             : 
     417             :         // clip to output bounds (cannot properly scroll stuff
     418             :         // _outside_ our screen area)
     419           0 :         if( !mbIsUnsafeScrolling ||
     420             :             !::canvas::tools::clipScrollArea( aSourceRect,
     421             :                                               aDestPos,
     422             :                                               aUnscrollableAreas,
     423           0 :                                               aOutputBounds ) )
     424             :         {
     425             :             // fully clipped scroll area: cannot simply scroll
     426             :             // then. Perform normal opaque update (can use that, since
     427             :             // one of the preconditions for scrollable update is
     428             :             // opaque sprite content)
     429             : 
     430             :             // repaint all affected sprites directly to output device
     431             :             ::std::for_each( rUpdateArea.maComponentList.begin(),
     432             :                              rUpdateArea.maComponentList.end(),
     433             :                              ::boost::bind(
     434             :                                  &spriteRedrawStub3,
     435             :                                  ::boost::ref( rOutDev ),
     436           0 :                                  _1 ) );
     437             :         }
     438             :         else
     439             :         {
     440             :             // scroll rOutDev content
     441             :             rOutDev.CopyArea( ::vcl::unotools::pointFromB2IPoint( aDestPos ),
     442           0 :                               ::vcl::unotools::pointFromB2IPoint( aSourceRect.getMinimum() ),
     443             :                               // TODO(Q2): use numeric_cast to check range
     444           0 :                               ::Size( static_cast<sal_Int32>(aSourceRect.getRange().getX()),
     445           0 :                                       static_cast<sal_Int32>(aSourceRect.getRange().getY()) ) );
     446             : 
     447             :             const ::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
     448           0 :                 aFirst( rUpdateArea.maComponentList.begin() );
     449             : 
     450           0 :             ENSURE_OR_THROW( aFirst->second.getSprite().is(),
     451             :                               "VCLCanvas::scrollUpdate(): no sprite" );
     452             : 
     453             :             // repaint uncovered areas from sprite. Need to actually
     454             :             // clip here, since we're only repainting _parts_ of the
     455             :             // sprite
     456           0 :             rOutDev.Push( PushFlags::CLIPREGION );
     457             :             ::std::for_each( aUnscrollableAreas.begin(),
     458             :                              aUnscrollableAreas.end(),
     459             :                              ::boost::bind( &opaqueUpdateSpriteArea,
     460           0 :                                             ::boost::cref(aFirst->second.getSprite()),
     461             :                                             ::boost::ref(rOutDev),
     462           0 :                                             _1 ) );
     463           0 :             rOutDev.Pop();
     464             :         }
     465             : 
     466             :         // repaint uncovered areas from backbuffer - take the
     467             :         // _rounded_ rectangles from above, to have the update
     468             :         // consistent with the scroll above.
     469           0 :         ::std::vector< ::basegfx::B2DRange > aUncoveredAreas;
     470             :         ::basegfx::computeSetDifference( aUncoveredAreas,
     471             :                                          rUpdateArea.maTotalBounds,
     472           0 :                                          ::basegfx::B2DRange( rDestRect ) );
     473             :         ::std::for_each( aUncoveredAreas.begin(),
     474             :                          aUncoveredAreas.end(),
     475             :                          ::boost::bind( &repaintBackground,
     476             :                                         ::boost::ref(rOutDev),
     477             :                                         ::boost::ref(rBackOutDev),
     478           0 :                                         _1 ) );
     479           0 :     }
     480             : 
     481           0 :     void SpriteCanvasHelper::opaqueUpdate( SAL_UNUSED_PARAMETER const ::basegfx::B2DRange&,
     482             :                                            const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
     483             :     {
     484           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     485             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     486             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     487             :                          "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
     488             : 
     489           0 :         OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     490             : 
     491             :         // no need to clip output to actual update region - there will
     492             :         // always be ALL sprites contained in the rectangular update
     493             :         // area containd in rTotalArea (that's the way
     494             :         // B2DConnectedRanges work). If rTotalArea appears to be
     495             :         // smaller than the sprite - then this sprite carries a clip,
     496             :         // and the update will be constrained to that rect.
     497             : 
     498             :         // repaint all affected sprites directly to output device
     499             :         ::std::for_each( rSortedUpdateSprites.begin(),
     500             :                          rSortedUpdateSprites.end(),
     501             :                          ::boost::bind(
     502             :                              &spriteRedrawStub,
     503             :                              ::boost::ref( rOutDev ),
     504           0 :                              _1 ) );
     505           0 :     }
     506             : 
     507           0 :     void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange&                          rRequestedArea,
     508             :                                             const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
     509             :     {
     510           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     511             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     512             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     513             :                          "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
     514             : 
     515           0 :         OutputDevice&       rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     516           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     517           0 :         OutputDevice&       rBackOutDev( pBackBuffer->getOutDev() );
     518             : 
     519             :         // limit size of update VDev to target outdev's size
     520           0 :         const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
     521             : 
     522             :         // round output position towards zero. Don't want to truncate
     523             :         // a fraction of a sprite pixel...  Clip position at origin,
     524             :         // otherwise, truncation of size below might leave visible
     525             :         // areas uncovered by VDev.
     526             :         const ::Point aOutputPosition(
     527             :             ::std::max( sal_Int32( 0 ),
     528           0 :                         static_cast< sal_Int32 >(rRequestedArea.getMinX()) ),
     529             :             ::std::max( sal_Int32( 0 ),
     530           0 :                         static_cast< sal_Int32 >(rRequestedArea.getMinY()) ) );
     531             :         // round output size towards +infty. Don't want to truncate a
     532             :         // fraction of a sprite pixel... Limit coverage of VDev to
     533             :         // output device's area (i.e. not only to total size, but to
     534             :         // cover _only_ the visible parts).
     535             :         const ::Size aOutputSize(
     536             :             ::std::max( sal_Int32( 0 ),
     537           0 :                         ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Width() - aOutputPosition.X()),
     538           0 :                                     ::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X() ))),
     539             :             ::std::max( sal_Int32( 0 ),
     540           0 :                         ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Height() - aOutputPosition.Y()),
     541           0 :                                     ::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y() ))));
     542             : 
     543             :         // early exit for empty output area.
     544           0 :         if( aOutputSize.Width() == 0 &&
     545           0 :             aOutputSize.Height() == 0 )
     546             :         {
     547           0 :             return;
     548             :         }
     549             : 
     550           0 :         const Point aEmptyPoint(0,0);
     551           0 :         const Size  aCurrOutputSize( maVDev->GetOutputSizePixel() );
     552             : 
     553             :         // adapt maVDev's size to the area that actually needs the
     554             :         // repaint.
     555           0 :         if( aCurrOutputSize.Width() < aOutputSize.Width() ||
     556           0 :             aCurrOutputSize.Height() < aOutputSize.Height() )
     557             :         {
     558             :             // TODO(P1): Come up with a clever tactic to reduce maVDev
     559             :             // from time to time. Reduction with threshold (say, if
     560             :             // maVDev is more than twice too large) is not wise, as
     561             :             // this might then toggle within the same updateScreen(),
     562             :             // but for different disjunct sprite areas.
     563           0 :             maVDev->SetOutputSizePixel( aOutputSize );
     564             :         }
     565             : 
     566             :         // paint background
     567           0 :         maVDev->EnableMapMode( false );
     568           0 :         maVDev->SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW );
     569           0 :         maVDev->SetClipRegion();
     570           0 :         maVDev->DrawOutDev( aEmptyPoint, aOutputSize,
     571             :                             aOutputPosition, aOutputSize,
     572           0 :                             rBackOutDev );
     573             : 
     574             :         // repaint all affected sprites on top of background into
     575             :         // VDev.
     576           0 :         ::basegfx::B2DPoint outPos( ::vcl::unotools::b2DPointFromPoint(aOutputPosition) );
     577             :         ::std::for_each( rSortedUpdateSprites.begin(),
     578             :                          rSortedUpdateSprites.end(),
     579             :                          ::boost::bind( &spriteRedrawStub2,
     580           0 :                                         ::boost::ref( maVDev.get() ),
     581             :                                         ::boost::cref( outPos ),
     582           0 :                                         _1 ) );
     583             : 
     584             :         // flush to screen
     585           0 :         rOutDev.EnableMapMode( false );
     586           0 :         rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW );
     587             :         rOutDev.DrawOutDev( aOutputPosition, aOutputSize,
     588             :                             aEmptyPoint, aOutputSize,
     589           0 :                             *maVDev );
     590             :     }
     591             : 
     592           0 :     void SpriteCanvasHelper::renderFrameCounter( OutputDevice& rOutDev )
     593             :     {
     594           0 :         const double denominator( maLastUpdate.getElapsedTime() );
     595           0 :         maLastUpdate.reset();
     596             : 
     597             :         OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
     598             :                                                             rtl_math_StringFormat_F,
     599           0 :                                                             2,'.',NULL,' ') );
     600             : 
     601             :         // pad with leading space
     602           0 :         while( text.getLength() < 6 )
     603           0 :             text = " " + text;
     604             : 
     605           0 :         text += " fps";
     606             : 
     607             :         renderInfoText( rOutDev,
     608             :                         text,
     609           0 :                         Point(0, 0) );
     610           0 :     }
     611             : 
     612             :     namespace
     613             :     {
     614             :         template< typename T > struct Adder
     615             :         {
     616             :             typedef void result_type;
     617             : 
     618           0 :             Adder( T& rAdderTarget,
     619             :                    T  nIncrement ) :
     620             :                 mpTarget( &rAdderTarget ),
     621           0 :                 mnIncrement( nIncrement )
     622             :             {
     623           0 :             }
     624             : 
     625             :             void operator()() { *mpTarget += mnIncrement; }
     626           0 :             void operator()( const ::canvas::Sprite::Reference& ) { *mpTarget += mnIncrement; }
     627           0 :             void operator()( T nIncrement ) { *mpTarget += nIncrement; }
     628             : 
     629             :             T* mpTarget;
     630             :             T  mnIncrement;
     631             :         };
     632             : 
     633           0 :         template< typename T> Adder<T> makeAdder( T& rAdderTarget,
     634             :                                                   T  nIncrement )
     635             :         {
     636           0 :             return Adder<T>(rAdderTarget, nIncrement);
     637             :         }
     638             :     }
     639             : 
     640           0 :     void SpriteCanvasHelper::renderSpriteCount( OutputDevice& rOutDev )
     641             :     {
     642           0 :         if( mpRedrawManager )
     643             :         {
     644           0 :             sal_Int32 nCount(0);
     645             : 
     646           0 :             mpRedrawManager->forEachSprite( makeAdder(nCount,sal_Int32(1)) );
     647             :             OUString text(
     648             :                 OUString::number(
     649             :                     // disambiguate overload...
     650           0 :                     nCount ) );
     651             : 
     652             :             // pad with leading space
     653           0 :             while( text.getLength() < 3 )
     654           0 :                 text = " " + text;
     655             : 
     656           0 :             text = "Sprites: " + text;
     657             : 
     658             :             renderInfoText( rOutDev,
     659             :                             text,
     660           0 :                             Point(0, 30) );
     661             :         }
     662           0 :     }
     663             : 
     664           0 :     void SpriteCanvasHelper::renderMemUsage( OutputDevice& rOutDev )
     665             :     {
     666           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     667             : 
     668           0 :         if( mpRedrawManager &&
     669           0 :             pBackBuffer )
     670             :         {
     671           0 :             double nPixel(0.0);
     672             : 
     673             :             // accumulate pixel count for each sprite into fCount
     674             :             mpRedrawManager->forEachSprite( ::boost::bind(
     675             :                                                 makeAdder(nPixel,1.0),
     676             :                                                 ::boost::bind(
     677             :                                                     &calcNumPixel,
     678           0 :                                                     _1 ) ) );
     679             : 
     680             :             static const int NUM_VIRDEV(2);
     681             :             static const int BYTES_PER_PIXEL(3);
     682             : 
     683           0 :             const Size& rVDevSize( maVDev->GetOutputSizePixel() );
     684           0 :             const Size& rBackBufferSize( pBackBuffer->getOutDev().GetOutputSizePixel() );
     685             : 
     686           0 :             const double nMemUsage( nPixel * NUM_VIRDEV * BYTES_PER_PIXEL +
     687           0 :                                     rVDevSize.Width()*rVDevSize.Height() * BYTES_PER_PIXEL +
     688           0 :                                     rBackBufferSize.Width()*rBackBufferSize.Height() * BYTES_PER_PIXEL );
     689             : 
     690             :             OUString text( ::rtl::math::doubleToUString( nMemUsage / 1048576.0,
     691             :                                                                 rtl_math_StringFormat_F,
     692           0 :                                                                 2,'.',NULL,' ') );
     693             : 
     694             :             // pad with leading space
     695           0 :             while( text.getLength() < 4 )
     696           0 :                 text = " " + text;
     697             : 
     698           0 :             text = "Mem: " + text + "MB";
     699             : 
     700             :             renderInfoText( rOutDev,
     701             :                             text,
     702           0 :                             Point(0, 60) );
     703           0 :         }
     704           0 :     }
     705           0 : }
     706             : 
     707             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10