LCOV - code coverage report
Current view: top level - include/canvas - spriteredrawmanager.hxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 0 62 0.0 %
Date: 2015-06-13 12:38:46 Functions: 0 27 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             : #ifndef INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX
      21             : #define INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX
      22             : 
      23             : #include <basegfx/range/b2dconnectedranges.hxx>
      24             : #include <basegfx/point/b2dpoint.hxx>
      25             : #include <basegfx/vector/b2dvector.hxx>
      26             : #include <basegfx/range/b2drange.hxx>
      27             : #include <basegfx/range/b2irange.hxx>
      28             : #include <basegfx/matrix/b2dhommatrix.hxx>
      29             : #include <canvas/base/spritesurface.hxx>
      30             : 
      31             : #include <list>
      32             : #include <vector>
      33             : #include <algorithm>
      34             : 
      35             : #include <boost/utility.hpp>
      36             : #include <boost/bind.hpp>
      37             : 
      38             : #include <canvas/canvastoolsdllapi.h>
      39             : 
      40             : /* Definition of SpriteRedrawManager class */
      41             : 
      42             : namespace canvas
      43             : {
      44             :     /** This class manages smooth SpriteCanvas updates
      45             : 
      46             :         Use this class to handle the ::canvas::SpriteSurface methods,
      47             :         that track and process sprite update events. Recorded update
      48             :         events are later grouped by connected areas (i.e. all sprites
      49             :         that somehow overlap over a rectangular area are grouped
      50             :         together); the forEachSpriteArea() method calls the passed
      51             :         functor for each of those connected areas.
      52             : 
      53             :         Note that, although this class generally works with IEEE
      54             :         doubles, the calculation of connected areas happens in the
      55             :         integer domain - it is generally expected that repaints can
      56             :         only be divided at pixel boundaries, without causing visible
      57             :         artifacts. Therefore, sprites that touch the same pixel (but
      58             :         don't necessarily have the same floating point coordinates
      59             :         there) will reside in a common sprite area and handled
      60             :         together in the forEachSpriteArea functor call.
      61             :      */
      62           0 :     class CANVASTOOLS_DLLPUBLIC SpriteRedrawManager : private ::boost::noncopyable
      63             :     {
      64             :     public:
      65             :         /** Data container for the connected components list
      66             :          */
      67           0 :         class SpriteInfo
      68             :         {
      69             :         public:
      70           0 :             ~SpriteInfo() {}
      71             : 
      72             :             /** Create sprite info
      73             : 
      74             :                 @param rRef
      75             :                 Sprite this info represents (might be the NULL ref)
      76             : 
      77             :                 @param rTrueUpdateArea
      78             :                 True (un-rounded) update area this sprite has recorded
      79             : 
      80             :                 @param bNeedsUpdate
      81             :                 When false, this sprite is not a member of the change
      82             :                 record list. Thus, it only needs redraw if within the
      83             :                 update area of other, changed sprites.
      84             : 
      85             :                 @internal
      86             :              */
      87           0 :             SpriteInfo( const Sprite::Reference&    rRef,
      88             :                         const ::basegfx::B2DRange&  rTrueUpdateArea,
      89             :                         bool                        bNeedsUpdate ) :
      90             :                 mpSprite( rRef ),
      91             :                 maTrueUpdateArea( rTrueUpdateArea ),
      92             :                 mbNeedsUpdate( bNeedsUpdate ),
      93           0 :                 mbIsPureMove( false )
      94             :             {
      95           0 :             }
      96             : 
      97             :             /** Create sprite info, specify move type
      98             : 
      99             :                 @param rRef
     100             :                 Sprite this info represents (might be the NULL ref)
     101             : 
     102             :                 @param rTrueUpdateArea
     103             :                 True (un-rounded) update area this sprite has recorded
     104             : 
     105             :                 @param bNeedsUpdate
     106             :                 When false, this sprite is not a member of the change
     107             :                 record list. Thus, it only needs redraw if within the
     108             :                 update area of other, changed sprites.
     109             : 
     110             :                 @param bIsPureMove
     111             :                 When true, this sprite is _only_ moved, no other
     112             :                 changes happened.
     113             : 
     114             :                 @internal
     115             :              */
     116           0 :             SpriteInfo( const Sprite::Reference&    rRef,
     117             :                         const ::basegfx::B2DRange&  rTrueUpdateArea,
     118             :                         bool                        bNeedsUpdate,
     119             :                         bool                        bIsPureMove ) :
     120             :                 mpSprite( rRef ),
     121             :                 maTrueUpdateArea( rTrueUpdateArea ),
     122             :                 mbNeedsUpdate( bNeedsUpdate ),
     123           0 :                 mbIsPureMove( bIsPureMove )
     124             :             {
     125           0 :             }
     126             : 
     127           0 :             const Sprite::Reference&    getSprite() const { return mpSprite; }
     128             : 
     129             :             // #i61843# need to return by value here, to be used safely from bind
     130           0 :             ::basegfx::B2DRange         getUpdateArea() const { return maTrueUpdateArea; }
     131           0 :             bool                        needsUpdate() const { return mbNeedsUpdate; }
     132           0 :             bool                        isPureMove() const { return mbIsPureMove; }
     133             : 
     134             :         private:
     135             :             Sprite::Reference       mpSprite;
     136             :             ::basegfx::B2DRange     maTrueUpdateArea;
     137             :             bool                    mbNeedsUpdate;
     138             :             bool                    mbIsPureMove;
     139             :         };
     140             : 
     141             : 
     142             :         /** Helper struct for SpriteTracer template
     143             : 
     144             :             This struct stores change information to a sprite's visual
     145             :             appearance (move, content updated, and the like).
     146             :          */
     147           0 :         struct SpriteChangeRecord
     148             :         {
     149             :             typedef enum{ none=0, move, update } ChangeType;
     150             : 
     151             :             SpriteChangeRecord() :
     152             :                 meChangeType( none ),
     153             :                 mpAffectedSprite(),
     154             :                 maOldPos(),
     155             :                 maUpdateArea()
     156             :             {
     157             :             }
     158             : 
     159           0 :             SpriteChangeRecord( const Sprite::Reference&    rSprite,
     160             :                                 const ::basegfx::B2DPoint&  rOldPos,
     161             :                                 const ::basegfx::B2DPoint&  rNewPos,
     162             :                                 const ::basegfx::B2DVector& rSpriteSize ) :
     163             :                 meChangeType( move ),
     164             :                 mpAffectedSprite( rSprite ),
     165             :                 maOldPos( rOldPos ),
     166             :                 maUpdateArea( rNewPos.getX(),
     167             :                               rNewPos.getY(),
     168           0 :                               rNewPos.getX() + rSpriteSize.getX(),
     169           0 :                               rNewPos.getY() + rSpriteSize.getY() )
     170             :             {
     171           0 :             }
     172             : 
     173           0 :             SpriteChangeRecord( const Sprite::Reference&    rSprite,
     174             :                                 const ::basegfx::B2DPoint&  rPos,
     175             :                                 const ::basegfx::B2DRange&  rUpdateArea ) :
     176             :                 meChangeType( update ),
     177             :                 mpAffectedSprite( rSprite ),
     178             :                 maOldPos( rPos ),
     179           0 :                 maUpdateArea( rUpdateArea )
     180             :             {
     181           0 :             }
     182             : 
     183           0 :             Sprite::Reference getSprite() const { return mpAffectedSprite; }
     184             : 
     185             :             ChangeType          meChangeType;
     186             :             Sprite::Reference   mpAffectedSprite;
     187             :             ::basegfx::B2DPoint maOldPos;
     188             :             ::basegfx::B2DRange maUpdateArea;
     189             :         };
     190             : 
     191             :         typedef ::std::vector< SpriteChangeRecord >             VectorOfChangeRecords;
     192             :         typedef ::std::list< Sprite::Reference >                ListOfSprites;
     193             :         typedef ::basegfx::B2DConnectedRanges< SpriteInfo >     SpriteConnectedRanges;
     194             :         typedef SpriteConnectedRanges::ComponentType            AreaComponent;
     195             :         typedef SpriteConnectedRanges::ConnectedComponents      UpdateArea;
     196             :         typedef ::std::vector< Sprite::Reference >              VectorOfSprites;
     197             : 
     198             :         SpriteRedrawManager();
     199             : 
     200             :         /** Must be called when user of this object gets
     201             :             disposed. Frees all internal references.
     202             :          */
     203             :         void disposing();
     204             : 
     205             :         /** Functor, to be used from forEachSpriteArea
     206             :          */
     207             :         template< typename Functor > struct AreaUpdateCaller
     208             :         {
     209           0 :             AreaUpdateCaller( Functor&                      rFunc,
     210             :                               const SpriteRedrawManager&    rManager ) :
     211             :                 mrFunc( rFunc ),
     212           0 :                 mrManager( rManager )
     213             :             {
     214           0 :             }
     215             : 
     216           0 :             void operator()( const UpdateArea& rUpdateArea )
     217             :             {
     218           0 :                 mrManager.handleArea( mrFunc, rUpdateArea );
     219           0 :             }
     220             : 
     221             :             Functor&                    mrFunc;
     222             :             const SpriteRedrawManager&  mrManager;
     223             :         };
     224             : 
     225             :         /** Call given functor for each sprite area that needs an
     226             :             update.
     227             : 
     228             :             This method calls the given functor for each update area
     229             :             (calculated from the sprite change records).
     230             : 
     231             :             @tpl Functor
     232             :             Must provide the following four methods:
     233             :             <pre>
     234             :             void backgroundPaint( ::basegfx::B2DRange aUpdateRect );
     235             :             void scrollUpdate( ::basegfx::B2DRange& o_rMoveStart,
     236             :                                ::basegfx::B2DRange& o_rMoveEnd,
     237             :                                UpdateArea           aUpdateArea );
     238             :             void opaqueUpdate( const ::basegfx::B2DRange&                          rTotalArea,
     239             :                                const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
     240             :             void genericUpdate( const ::basegfx::B2DRange&                          rTotalArea,
     241             :                                 const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
     242             :             </pre>
     243             :             The backgroundPaint() method is called to simply repaint
     244             :             background content, the scrollUpdate() method is used to
     245             :             scroll a given area, and paint background in the uncovered
     246             :             areas, the opaqueUpdate() method is called when a sprite
     247             :             can be painted in the given area without taking background
     248             :             content into account, and finally, genericUpdate() is
     249             :             called for complex updates, where first the background and
     250             :             then all sprites consecutively have to be repainted.
     251             :          */
     252           0 :         template< typename Functor > void forEachSpriteArea( Functor& rFunc ) const
     253             :         {
     254           0 :             SpriteConnectedRanges aUpdateAreas;
     255             : 
     256           0 :             setupUpdateAreas( aUpdateAreas );
     257             : 
     258           0 :             aUpdateAreas.forEachAggregate(
     259           0 :                 AreaUpdateCaller< Functor >( rFunc, *this ) );
     260           0 :         }
     261             : 
     262             :         /** Call given functor for each active sprite.
     263             : 
     264             :             This method calls the given functor for each active
     265             :             sprite, in the order of sprite priority.
     266             : 
     267             :             @tpl Functor
     268             :             Must provide a Functor::operator( Sprite::Reference& )
     269             :             method.
     270             :          */
     271           0 :         template< typename Functor > void forEachSprite( const Functor& rFunc ) const
     272             :         {
     273           0 :             ::std::for_each( maSprites.begin(),
     274             :                              maSprites.end(),
     275           0 :                              rFunc );
     276           0 :         }
     277             : 
     278             :         /// Clear sprite change records (typically directly after a screen update)
     279             :         void clearChangeRecords();
     280             : 
     281             :         // SpriteSurface interface, is delegated to e.g. from SpriteCanvas
     282             :         void showSprite( const Sprite::Reference& rSprite );
     283             :         void hideSprite( const Sprite::Reference& rSprite );
     284             :         void moveSprite( const Sprite::Reference&       rSprite,
     285             :                          const ::basegfx::B2DPoint&     rOldPos,
     286             :                          const ::basegfx::B2DPoint&     rNewPos,
     287             :                          const ::basegfx::B2DVector&    rSpriteSize );
     288             :         void updateSprite( const Sprite::Reference&     rSprite,
     289             :                            const ::basegfx::B2DPoint&   rPos,
     290             :                            const ::basegfx::B2DRange&   rUpdateArea );
     291             : 
     292             :         /** Internal, handles each distinct component for forEachAggregate()
     293             : 
     294             :             The reason why this must be public is that it needs to be
     295             :             accessible from the AreaUpdateCaller functor.
     296             : 
     297             :             @internal
     298             :          */
     299           0 :         template< typename Functor > void handleArea( Functor&          rFunc,
     300             :                                                       const UpdateArea& rUpdateArea ) const
     301             :         {
     302             :             // check whether this area contains changed sprites at all
     303             :             // (if not, just ignore it)
     304           0 :             if( areSpritesChanged( rUpdateArea ) )
     305             :             {
     306             :                 // at least one of the sprites actually needs an
     307             :                 // update - process whole area.
     308             : 
     309             :                 // check whether this area could be handled special
     310             :                 // (background paint, direct update, scroll, etc.)
     311           0 :                 ::basegfx::B2DRange aMoveStart;
     312           0 :                 ::basegfx::B2DRange aMoveEnd;
     313           0 :                 if( rUpdateArea.maComponentList.empty() )
     314             :                 {
     315           0 :                     rFunc.backgroundPaint( rUpdateArea.maTotalBounds );
     316             :                 }
     317             :                 else
     318             :                 {
     319             :                     // cache number of sprites in this area (it's a
     320             :                     // list, and both isAreaUpdateScroll() and
     321             :                     // isAreaUpdateOpaque() need it).
     322             :                     const ::std::size_t nNumSprites(
     323           0 :                         rUpdateArea.maComponentList.size() );
     324             : 
     325           0 :                     if( isAreaUpdateScroll( aMoveStart,
     326             :                                             aMoveEnd,
     327             :                                             rUpdateArea,
     328             :                                             nNumSprites ) )
     329             :                     {
     330           0 :                         rFunc.scrollUpdate( aMoveStart,
     331             :                                             aMoveEnd,
     332             :                                             rUpdateArea );
     333             :                     }
     334             :                     else
     335             :                     {
     336             :                         // potentially, more than a single sprite
     337             :                         // involved. Have to sort component lists for
     338             :                         // sprite prio.
     339           0 :                         VectorOfSprites aSortedUpdateSprites;
     340             :                         SpriteConnectedRanges::ComponentListType::const_iterator aCurr(
     341           0 :                             rUpdateArea.maComponentList.begin() );
     342             :                         const SpriteConnectedRanges::ComponentListType::const_iterator aEnd(
     343           0 :                             rUpdateArea.maComponentList.end() );
     344           0 :                         while( aCurr != aEnd )
     345             :                         {
     346           0 :                             const Sprite::Reference& rSprite( aCurr->second.getSprite() );
     347           0 :                             if( rSprite.is() )
     348           0 :                                 aSortedUpdateSprites.push_back( rSprite );
     349             : 
     350           0 :                             ++aCurr;
     351             :                         }
     352             : 
     353           0 :                         ::std::sort( aSortedUpdateSprites.begin(),
     354             :                                      aSortedUpdateSprites.end(),
     355           0 :                                      SpriteWeakOrder() );
     356             : 
     357           0 :                         if( isAreaUpdateOpaque( rUpdateArea,
     358             :                                                 nNumSprites ) )
     359             :                         {
     360           0 :                             rFunc.opaqueUpdate( rUpdateArea.maTotalBounds,
     361             :                                                 aSortedUpdateSprites );
     362             :                         }
     363             :                         else
     364             :                         {
     365           0 :                             rFunc.genericUpdate( rUpdateArea.maTotalBounds,
     366             :                                                  aSortedUpdateSprites );
     367           0 :                         }
     368             :                     }
     369             :                 }
     370             :             }
     371           0 :         }
     372             : 
     373             :     private:
     374             :         /** Central method of this class. Calculates the set of
     375             :             disjunct components that need an update.
     376             :          */
     377             :         void setupUpdateAreas( SpriteConnectedRanges& rUpdateAreas ) const;
     378             : 
     379             :         bool areSpritesChanged( const UpdateArea& rUpdateArea ) const;
     380             : 
     381             :         bool isAreaUpdateNotOpaque( const ::basegfx::B2DRange&  rUpdateRect,
     382             :                                     const AreaComponent&        rComponent ) const;
     383             : 
     384             :         bool isAreaUpdateOpaque( const UpdateArea&  rUpdateArea,
     385             :                                  ::std::size_t      nNumSprites ) const;
     386             : 
     387             :         /** Check whether given update area can be handled by a simple
     388             :             scroll
     389             : 
     390             :             @param o_rMoveStart
     391             :             Start rect of the move
     392             : 
     393             :             @param o_rMoveEnd
     394             :             End rect of the move. The content must be moved from start
     395             :             to end rect
     396             : 
     397             :             @param rUpdateArea
     398             :             Area to check for scroll update optimization
     399             :          */
     400             :         bool isAreaUpdateScroll( ::basegfx::B2DRange&   o_rMoveStart,
     401             :                                  ::basegfx::B2DRange&   o_rMoveEnd,
     402             :                                  const UpdateArea&      rUpdateArea,
     403             :                                  ::std::size_t          nNumSprites ) const;
     404             : 
     405             : 
     406             :         ListOfSprites                   maSprites; // list of active
     407             :                                                    // sprite
     408             :                                                    // objects. this
     409             :                                                    // list is only
     410             :                                                    // used for full
     411             :                                                    // repaints,
     412             :                                                    // otherwise, we
     413             :                                                    // rely on the
     414             :                                                    // active sprites
     415             :                                                    // itself to notify
     416             :                                                    // us.
     417             : 
     418             :         VectorOfChangeRecords           maChangeRecords; // vector of
     419             :                                                          // sprites
     420             :                                                          // changes
     421             :                                                          // since last
     422             :                                                          // updateScreen()
     423             :                                                          // call
     424             :     };
     425             : }
     426             : 
     427             : #endif /* INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX */
     428             : 
     429             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11