LCOV - code coverage report
Current view: top level - libreoffice/canvas/source/vcl - spritecanvashelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 222 0.0 %
Date: 2012-12-27 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             : 
      40             : using namespace ::com::sun::star;
      41             : 
      42             : #define FPS_BOUNDS Rectangle(0,0,130,90)
      43             : #define INFO_COLOR COL_RED
      44             : 
      45             : namespace vclcanvas
      46             : {
      47             :     namespace
      48             :     {
      49             :         /** Sprite redraw at original position
      50             : 
      51             :             Used to repaint the whole canvas (background and all
      52             :             sprites)
      53             :          */
      54           0 :         void spriteRedraw( OutputDevice&                      rOutDev,
      55             :                            const ::canvas::Sprite::Reference& rSprite )
      56             :         {
      57             :             // downcast to derived vclcanvas::Sprite interface, which
      58             :             // provides the actual redraw methods.
      59           0 :             ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw(rOutDev,
      60           0 :                                                                             true);
      61           0 :         }
      62             : 
      63           0 :         double calcNumPixel( const ::canvas::Sprite::Reference& rSprite )
      64             :         {
      65             :             const ::basegfx::B2DSize& rSize(
      66           0 :                 ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->getSizePixel() );
      67             : 
      68           0 :             return rSize.getX() * rSize.getY();
      69             :         }
      70             : 
      71           0 :         void repaintBackground( OutputDevice&               rOutDev,
      72             :                                 OutputDevice&               rBackBuffer,
      73             :                                 const ::basegfx::B2DRange&  rArea )
      74             :         {
      75           0 :             const ::Point& rPos( ::vcl::unotools::pointFromB2DPoint( rArea.getMinimum()) );
      76           0 :             const ::Size& rSize( ::vcl::unotools::sizeFromB2DSize( rArea.getRange()) );
      77             : 
      78           0 :             rOutDev.DrawOutDev( rPos, rSize, rPos, rSize, rBackBuffer );
      79           0 :         }
      80             : 
      81           0 :         void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite,
      82             :                                      OutputDevice&                      rOutDev,
      83             :                                      const ::basegfx::B2IRange&         rArea )
      84             :         {
      85             :             const Rectangle& rRequestedArea(
      86           0 :                 ::vcl::unotools::rectangleFromB2IRectangle( rArea ) );
      87             : 
      88             :             // clip output to actual update region (otherwise a)
      89             :             // wouldn't save much render time, and b) will clutter
      90             :             // scrolled sprite content outside this area)
      91           0 :             rOutDev.EnableMapMode( sal_False );
      92           0 :             rOutDev.SetClipRegion( 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 ::rtl::OUString& rStr,
     162             :                              const Point&           rPos )
     163             :         {
     164           0 :             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 :     sal_Bool SpriteCanvasHelper::updateScreen( sal_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 sal_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 :         Window* pTargetWindow = NULL;
     270           0 :         if( rOutDev.GetOutDevType() == OUTDEV_WINDOW )
     271             :         {
     272           0 :             pTargetWindow = &static_cast<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 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( sal_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( sal_False );
     326           0 :             rOutDev.SetClipRegion();
     327             :             rOutDev.DrawOutDev( aEmptyPoint, aOutDevSize,
     328             :                                 aEmptyPoint, aOutDevSize,
     329           0 :                                 *maVDev );
     330             :         }
     331             : 
     332             :         // change record vector must be cleared, for the next turn of
     333             :         // rendering and sprite changing
     334           0 :         mpRedrawManager->clearChangeRecords();
     335             : 
     336           0 :         io_bSurfaceDirty = false;
     337             : 
     338           0 :         if( mbShowFrameInfo )
     339             :         {
     340           0 :             renderFrameCounter( rOutDev );
     341           0 :             renderSpriteCount( rOutDev );
     342           0 :             renderMemUsage( rOutDev );
     343             :         }
     344             : 
     345             : #if OSL_DEBUG_LEVEL > 2
     346             :         static ::canvas::tools::ElapsedTime aElapsedTime;
     347             : 
     348             :         // log time immediately after surface flip
     349             :         OSL_TRACE( "SpriteCanvasHelper::updateScreen(): flip done at %f",
     350             :                    aElapsedTime.getElapsedTime() );
     351             : #endif
     352             : 
     353             :         // sync output with screen, to ensure that we don't queue up
     354             :         // render requests (calling code might rely on timing,
     355             :         // i.e. assume that things are visible on screen after
     356             :         // updateScreen() returns).
     357           0 :         if( pTargetWindow )
     358             :         {
     359             :             // commit to screen
     360           0 :             pTargetWindow->Sync();
     361             :         }
     362             : 
     363           0 :         return sal_True;
     364             :     }
     365             : 
     366           0 :     void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
     367             :     {
     368           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     369             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     370             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     371             :                          "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
     372             : 
     373           0 :         OutputDevice&       rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     374           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     375           0 :         OutputDevice&       rBackOutDev( pBackBuffer->getOutDev() );
     376             : 
     377           0 :         repaintBackground( rOutDev, rBackOutDev, rUpdateRect );
     378           0 :     }
     379             : 
     380           0 :     void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange&                       rMoveStart,
     381             :                                            const ::basegfx::B2DRange&                       rMoveEnd,
     382             :                                            const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
     383             :     {
     384           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     385             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     386             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     387             :                          "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
     388             : 
     389           0 :         OutputDevice&       rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     390           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     391           0 :         OutputDevice&       rBackOutDev( pBackBuffer->getOutDev() );
     392             : 
     393           0 :         const Size&                rTargetSizePixel( rOutDev.GetOutputSizePixel() );
     394             :         const ::basegfx::B2IRange  aOutputBounds( 0,0,
     395             :                                                   rTargetSizePixel.Width(),
     396           0 :                                                   rTargetSizePixel.Height() );
     397             : 
     398             :         // round rectangles to integer pixel. Note: have to be
     399             :         // extremely careful here, to avoid off-by-one errors for
     400             :         // the destination area: otherwise, the next scroll update
     401             :         // would copy pixel that are not supposed to be part of
     402             :         // the sprite.
     403             :         ::basegfx::B2IRange aSourceRect(
     404           0 :             ::canvas::tools::spritePixelAreaFromB2DRange( rMoveStart ) );
     405             :         const ::basegfx::B2IRange& rDestRect(
     406           0 :             ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
     407           0 :         ::basegfx::B2IPoint aDestPos( rDestRect.getMinimum() );
     408             : 
     409           0 :         ::std::vector< ::basegfx::B2IRange > aUnscrollableAreas;
     410             : 
     411             :         // Since strictly speaking, this scroll algorithm is plain
     412             :         // buggy, the scrolled area might actually lie _below_ another
     413             :         // window - we've made this feature configurable via
     414             :         // mbIsUnsafeScrolling.
     415             : 
     416             :         // clip to output bounds (cannot properly scroll stuff
     417             :         // _outside_ our screen area)
     418           0 :         if( !mbIsUnsafeScrolling ||
     419             :             !::canvas::tools::clipScrollArea( aSourceRect,
     420             :                                               aDestPos,
     421             :                                               aUnscrollableAreas,
     422           0 :                                               aOutputBounds ) )
     423             :         {
     424             :             // fully clipped scroll area: cannot simply scroll
     425             :             // then. Perform normal opaque update (can use that, since
     426             :             // one of the preconditions for scrollable update is
     427             :             // opaque sprite content)
     428             : 
     429             :             // repaint all affected sprites directly to output device
     430             :             ::std::for_each( rUpdateArea.maComponentList.begin(),
     431             :                              rUpdateArea.maComponentList.end(),
     432             :                              ::boost::bind(
     433             :                                  &spriteRedrawStub3,
     434             :                                  ::boost::ref( rOutDev ),
     435           0 :                                  _1 ) );
     436             :         }
     437             :         else
     438             :         {
     439             :             // scroll rOutDev content
     440             :             rOutDev.CopyArea( ::vcl::unotools::pointFromB2IPoint( aDestPos ),
     441           0 :                               ::vcl::unotools::pointFromB2IPoint( aSourceRect.getMinimum() ),
     442             :                               // TODO(Q2): use numeric_cast to check range
     443           0 :                               ::Size( static_cast<sal_Int32>(aSourceRect.getRange().getX()),
     444           0 :                                       static_cast<sal_Int32>(aSourceRect.getRange().getY()) ) );
     445             : 
     446             :             const ::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
     447           0 :                 aFirst( rUpdateArea.maComponentList.begin() );
     448             : 
     449           0 :             ENSURE_OR_THROW( aFirst->second.getSprite().is(),
     450             :                               "VCLCanvas::scrollUpdate(): no sprite" );
     451             : 
     452             :             // repaint uncovered areas from sprite. Need to actually
     453             :             // clip here, since we're only repainting _parts_ of the
     454             :             // sprite
     455           0 :             rOutDev.Push( PUSH_CLIPREGION );
     456             :             ::std::for_each( aUnscrollableAreas.begin(),
     457             :                              aUnscrollableAreas.end(),
     458             :                              ::boost::bind( &opaqueUpdateSpriteArea,
     459           0 :                                             ::boost::cref(aFirst->second.getSprite()),
     460             :                                             ::boost::ref(rOutDev),
     461           0 :                                             _1 ) );
     462           0 :             rOutDev.Pop();
     463             :         }
     464             : 
     465             :         // repaint uncovered areas from backbuffer - take the
     466             :         // _rounded_ rectangles from above, to have the update
     467             :         // consistent with the scroll above.
     468           0 :         ::std::vector< ::basegfx::B2DRange > aUncoveredAreas;
     469             :         ::basegfx::computeSetDifference( aUncoveredAreas,
     470             :                                          rUpdateArea.maTotalBounds,
     471           0 :                                          ::basegfx::B2DRange( rDestRect ) );
     472             :         ::std::for_each( aUncoveredAreas.begin(),
     473             :                          aUncoveredAreas.end(),
     474             :                          ::boost::bind( &repaintBackground,
     475             :                                         ::boost::ref(rOutDev),
     476             :                                         ::boost::ref(rBackOutDev),
     477           0 :                                         _1 ) );
     478           0 :     }
     479             : 
     480           0 :     void SpriteCanvasHelper::opaqueUpdate( SAL_UNUSED_PARAMETER const ::basegfx::B2DRange&,
     481             :                                            const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
     482             :     {
     483           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     484             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     485             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     486             :                          "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
     487             : 
     488           0 :         OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     489             : 
     490             :         // no need to clip output to actual update region - there will
     491             :         // always be ALL sprites contained in the rectangular update
     492             :         // area containd in rTotalArea (that's the way
     493             :         // B2DConnectedRanges work). If rTotalArea appears to be
     494             :         // smaller than the sprite - then this sprite carries a clip,
     495             :         // and the update will be constrained to that rect.
     496             : 
     497             :         // repaint all affected sprites directly to output device
     498             :         ::std::for_each( rSortedUpdateSprites.begin(),
     499             :                          rSortedUpdateSprites.end(),
     500             :                          ::boost::bind(
     501             :                              &spriteRedrawStub,
     502             :                              ::boost::ref( rOutDev ),
     503           0 :                              _1 ) );
     504           0 :     }
     505             : 
     506           0 :     void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange&                          rRequestedArea,
     507             :                                             const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
     508             :     {
     509           0 :         ENSURE_OR_THROW( mpOwningSpriteCanvas &&
     510             :                          mpOwningSpriteCanvas->getBackBuffer() &&
     511             :                          mpOwningSpriteCanvas->getFrontBuffer(),
     512             :                          "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
     513             : 
     514           0 :         OutputDevice&       rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
     515           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     516           0 :         OutputDevice&       rBackOutDev( pBackBuffer->getOutDev() );
     517             : 
     518             :         // limit size of update VDev to target outdev's size
     519           0 :         const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
     520             : 
     521             :         // round output position towards zero. Don't want to truncate
     522             :         // a fraction of a sprite pixel...  Clip position at origin,
     523             :         // otherwise, truncation of size below might leave visible
     524             :         // areas uncovered by VDev.
     525             :         const ::Point aOutputPosition(
     526             :             ::std::max( sal_Int32( 0 ),
     527           0 :                         static_cast< sal_Int32 >(rRequestedArea.getMinX()) ),
     528             :             ::std::max( sal_Int32( 0 ),
     529           0 :                         static_cast< sal_Int32 >(rRequestedArea.getMinY()) ) );
     530             :         // round output size towards +infty. Don't want to truncate a
     531             :         // fraction of a sprite pixel... Limit coverage of VDev to
     532             :         // output device's area (i.e. not only to total size, but to
     533             :         // cover _only_ the visible parts).
     534             :         const ::Size aOutputSize(
     535             :             ::std::max( sal_Int32( 0 ),
     536           0 :                         ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Width() - aOutputPosition.X()),
     537           0 :                                     ::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X() ))),
     538             :             ::std::max( sal_Int32( 0 ),
     539           0 :                         ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Height() - aOutputPosition.Y()),
     540           0 :                                     ::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y() ))));
     541             : 
     542             :         // early exit for empty output area.
     543           0 :         if( aOutputSize.Width() == 0 &&
     544           0 :             aOutputSize.Height() == 0 )
     545             :         {
     546           0 :             return;
     547             :         }
     548             : 
     549           0 :         const Point aEmptyPoint(0,0);
     550           0 :         const Size  aCurrOutputSize( maVDev->GetOutputSizePixel() );
     551             : 
     552             :         // adapt maVDev's size to the area that actually needs the
     553             :         // repaint.
     554           0 :         if( aCurrOutputSize.Width() < aOutputSize.Width() ||
     555           0 :             aCurrOutputSize.Height() < aOutputSize.Height() )
     556             :         {
     557             :             // TODO(P1): Come up with a clever tactic to reduce maVDev
     558             :             // from time to time. Reduction with threshold (say, if
     559             :             // maVDev is more than twice too large) is not wise, as
     560             :             // this might then toggle within the same updateScreen(),
     561             :             // but for different disjunct sprite areas.
     562           0 :             maVDev->SetOutputSizePixel( aOutputSize );
     563             :         }
     564             : 
     565             :         // paint background
     566           0 :         maVDev->EnableMapMode( sal_False );
     567           0 :         maVDev->SetClipRegion();
     568           0 :         maVDev->DrawOutDev( aEmptyPoint, aOutputSize,
     569             :                             aOutputPosition, aOutputSize,
     570           0 :                             rBackOutDev );
     571             : 
     572             :         // repaint all affected sprites on top of background into
     573             :         // VDev.
     574             :         ::std::for_each( rSortedUpdateSprites.begin(),
     575             :                          rSortedUpdateSprites.end(),
     576             :                          ::boost::bind( &spriteRedrawStub2,
     577           0 :                                         ::boost::ref( maVDev.get() ),
     578             :                                         ::boost::cref(
     579             :                                             ::vcl::unotools::b2DPointFromPoint(aOutputPosition)),
     580           0 :                                         _1 ) );
     581             : 
     582             :         // flush to screen
     583           0 :         rOutDev.EnableMapMode( sal_False );
     584             :         rOutDev.DrawOutDev( aOutputPosition, aOutputSize,
     585             :                             aEmptyPoint, aOutputSize,
     586           0 :                             *maVDev );
     587             :     }
     588             : 
     589           0 :     void SpriteCanvasHelper::renderFrameCounter( OutputDevice& rOutDev )
     590             :     {
     591           0 :         const double denominator( maLastUpdate.getElapsedTime() );
     592           0 :         maLastUpdate.reset();
     593             : 
     594             :         ::rtl::OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
     595             :                                                             rtl_math_StringFormat_F,
     596           0 :                                                             2,'.',NULL,' ') );
     597             : 
     598             :         // pad with leading space
     599           0 :         while( text.getLength() < 6 )
     600           0 :             text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
     601             : 
     602           0 :         text += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" fps"));
     603             : 
     604             :         renderInfoText( rOutDev,
     605             :                         text,
     606           0 :                         Point(0, 0) );
     607           0 :     }
     608             : 
     609             :     namespace
     610             :     {
     611             :         template< typename T > struct Adder
     612             :         {
     613             :             typedef void result_type;
     614             : 
     615           0 :             Adder( T& rAdderTarget,
     616             :                    T  nIncrement ) :
     617             :                 mpTarget( &rAdderTarget ),
     618           0 :                 mnIncrement( nIncrement )
     619             :             {
     620           0 :             }
     621             : 
     622             :             void operator()() { *mpTarget += mnIncrement; }
     623           0 :             void operator()( const ::canvas::Sprite::Reference& ) { *mpTarget += mnIncrement; }
     624           0 :             void operator()( T nIncrement ) { *mpTarget += nIncrement; }
     625             : 
     626             :             T* mpTarget;
     627             :             T  mnIncrement;
     628             :         };
     629             : 
     630           0 :         template< typename T> Adder<T> makeAdder( T& rAdderTarget,
     631             :                                                   T  nIncrement )
     632             :         {
     633           0 :             return Adder<T>(rAdderTarget, nIncrement);
     634             :         }
     635             :     }
     636             : 
     637           0 :     void SpriteCanvasHelper::renderSpriteCount( OutputDevice& rOutDev )
     638             :     {
     639           0 :         if( mpRedrawManager )
     640             :         {
     641           0 :             sal_Int32 nCount(0);
     642             : 
     643           0 :             mpRedrawManager->forEachSprite( makeAdder(nCount,sal_Int32(1)) );
     644             :             ::rtl::OUString text(
     645             :                 ::rtl::OUString::valueOf(
     646             :                     // disambiguate overload...
     647           0 :                     static_cast<sal_Int64>(nCount) ) );
     648             : 
     649             :             // pad with leading space
     650           0 :             while( text.getLength() < 3 )
     651           0 :                 text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
     652             : 
     653           0 :             text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("Sprites: ")) + text;
     654             : 
     655             :             renderInfoText( rOutDev,
     656             :                             text,
     657           0 :                             Point(0, 30) );
     658             :         }
     659           0 :     }
     660             : 
     661           0 :     void SpriteCanvasHelper::renderMemUsage( OutputDevice& rOutDev )
     662             :     {
     663           0 :         BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
     664             : 
     665           0 :         if( mpRedrawManager &&
     666           0 :             pBackBuffer )
     667             :         {
     668           0 :             double nPixel(0.0);
     669             : 
     670             :             // accumulate pixel count for each sprite into fCount
     671             :             mpRedrawManager->forEachSprite( ::boost::bind(
     672             :                                                 makeAdder(nPixel,1.0),
     673             :                                                 ::boost::bind(
     674             :                                                     &calcNumPixel,
     675           0 :                                                     _1 ) ) );
     676             : 
     677             :             static const int NUM_VIRDEV(2);
     678             :             static const int BYTES_PER_PIXEL(3);
     679             : 
     680           0 :             const Size& rVDevSize( maVDev->GetOutputSizePixel() );
     681           0 :             const Size& rBackBufferSize( pBackBuffer->getOutDev().GetOutputSizePixel() );
     682             : 
     683             :             const double nMemUsage( nPixel * NUM_VIRDEV * BYTES_PER_PIXEL +
     684           0 :                                     rVDevSize.Width()*rVDevSize.Height() * BYTES_PER_PIXEL +
     685           0 :                                     rBackBufferSize.Width()*rBackBufferSize.Height() * BYTES_PER_PIXEL );
     686             : 
     687             :             ::rtl::OUString text( ::rtl::math::doubleToUString( nMemUsage / 1048576.0,
     688             :                                                                 rtl_math_StringFormat_F,
     689           0 :                                                                 2,'.',NULL,' ') );
     690             : 
     691             :             // pad with leading space
     692           0 :             while( text.getLength() < 4 )
     693           0 :                 text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
     694             : 
     695             :             text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("Mem: ")) +
     696           0 :                 text +
     697           0 :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("MB"));
     698             : 
     699             :             renderInfoText( rOutDev,
     700             :                             text,
     701           0 :                             Point(0, 60) );
     702           0 :         }
     703           0 :     }
     704           0 : }
     705             : 
     706             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10