LCOV - code coverage report
Current view: top level - slideshow/source/engine - slideview.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 338 0.0 %
Date: 2012-08-25 Functions: 0 64 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     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                 :            : #include <canvas/debug.hxx>
      21                 :            : #include <tools/diagnose_ex.h>
      22                 :            : #include <canvas/canvastools.hxx>
      23                 :            : 
      24                 :            : #include "eventqueue.hxx"
      25                 :            : #include "eventmultiplexer.hxx"
      26                 :            : #include "slideview.hxx"
      27                 :            : #include "delayevent.hxx"
      28                 :            : #include "unoview.hxx"
      29                 :            : 
      30                 :            : #include <rtl/instance.hxx>
      31                 :            : #include <cppuhelper/basemutex.hxx>
      32                 :            : #include <cppuhelper/compbase2.hxx>
      33                 :            : #include <cppuhelper/implementationentry.hxx>
      34                 :            : #include <cppuhelper/interfacecontainer.h>
      35                 :            : #include <comphelper/make_shared_from_uno.hxx>
      36                 :            : 
      37                 :            : #include <cppcanvas/spritecanvas.hxx>
      38                 :            : #include <cppcanvas/customsprite.hxx>
      39                 :            : #include <cppcanvas/vclfactory.hxx>
      40                 :            : #include <cppcanvas/basegfxfactory.hxx>
      41                 :            : 
      42                 :            : #include <tools/debug.hxx>
      43                 :            : 
      44                 :            : #include <basegfx/range/b1drange.hxx>
      45                 :            : #include <basegfx/range/b2drange.hxx>
      46                 :            : #include <basegfx/range/b2irange.hxx>
      47                 :            : #include <basegfx/point/b2dpoint.hxx>
      48                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      49                 :            : #include <basegfx/matrix/b2dhommatrix.hxx>
      50                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      51                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      52                 :            : #include <basegfx/tools/canvastools.hxx>
      53                 :            : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      54                 :            : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
      55                 :            : 
      56                 :            : #include <com/sun/star/presentation/XSlideShow.hpp>
      57                 :            : 
      58                 :            : #include <boost/noncopyable.hpp>
      59                 :            : #include <boost/bind.hpp>
      60                 :            : #include <boost/weak_ptr.hpp>
      61                 :            : 
      62                 :            : #include <vector>
      63                 :            : #include <iterator>
      64                 :            : #include <algorithm>
      65                 :            : 
      66                 :            : using namespace com::sun::star;
      67                 :            : 
      68                 :            : namespace slideshow {
      69                 :            : namespace internal {
      70                 :            : 
      71                 :            : namespace {
      72                 :            : 
      73                 :            : struct StaticUnitRectPoly : public rtl::StaticWithInit<basegfx::B2DPolygon, StaticUnitRectPoly>
      74                 :            : {
      75                 :            :     basegfx::B2DPolygon operator()()
      76                 :            :     {
      77                 :            :         return basegfx::tools::createUnitPolygon();
      78                 :            :     }
      79                 :            : };
      80                 :            : 
      81                 :            : /** Sprite entry, to store sprite plus priority
      82                 :            : 
      83                 :            :     The operator<() defines a strict weak ordering of sprites, sort
      84                 :            :     key is the sprite priority.
      85                 :            :  */
      86                 :          0 : struct SpriteEntry
      87                 :            : {
      88                 :          0 :     SpriteEntry( const cppcanvas::CustomSpriteSharedPtr& rSprite,
      89                 :            :                  double                                  nPrio ) :
      90                 :            :         mpSprite( rSprite ),
      91                 :          0 :         mnPriority( nPrio )
      92                 :            :     {
      93                 :          0 :     }
      94                 :            : 
      95                 :          0 :     bool operator<(const SpriteEntry& rRHS) const
      96                 :            :     {
      97                 :          0 :         return mnPriority < rRHS.mnPriority;
      98                 :            :     }
      99                 :            : 
     100                 :            :     boost::weak_ptr< cppcanvas::CustomSprite > mpSprite;
     101                 :            :     double                                     mnPriority;
     102                 :            : };
     103                 :            : 
     104                 :            : typedef std::vector< SpriteEntry > SpriteVector;
     105                 :            : 
     106                 :            : 
     107                 :            : /** Create a clip polygon for slide views
     108                 :            : 
     109                 :            :     @param rClip
     110                 :            :     Clip to set (can be empty)
     111                 :            : 
     112                 :            :     @param rCanvas
     113                 :            :     Canvas to create the clip polygon for
     114                 :            : 
     115                 :            :     @param rUserSize
     116                 :            :     The size of the view. Note that the returned clip will
     117                 :            :     <em>always</em> clip to at least the rect defined herein.
     118                 :            : 
     119                 :            :     @return the view clip polygon, in view coordinates, which is
     120                 :            :     guaranteed to at least clip to the view size.
     121                 :            :  */
     122                 :          0 : basegfx::B2DPolyPolygon createClipPolygon( const basegfx::B2DPolyPolygon&    rClip,
     123                 :            :                                            const cppcanvas::CanvasSharedPtr& /*rCanvas*/,
     124                 :            :                                            const basegfx::B2DSize&           rUserSize )
     125                 :            : {
     126                 :            :     // setup canvas clipping
     127                 :            :     // =====================
     128                 :            : 
     129                 :            :     // AW: Simplified
     130                 :          0 :     const basegfx::B2DRange aClipRange(0, 0, rUserSize.getX(), rUserSize.getY());
     131                 :            : 
     132                 :          0 :     if(rClip.count())
     133                 :            :     {
     134                 :          0 :         return basegfx::tools::clipPolyPolygonOnRange(rClip, aClipRange, true, false);
     135                 :            :     }
     136                 :            :     else
     137                 :            :     {
     138                 :          0 :         return basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aClipRange));
     139                 :            :     }
     140                 :            : }
     141                 :            : 
     142                 :            : /** Prepare given clip polygon to be stored as the current clip
     143                 :            : 
     144                 :            :     Note that this is separate from createClipPolygon(), to allow
     145                 :            :     SlideView implementations to store this intermediate result
     146                 :            :     (createClipPolygon() has to be called every time the view size
     147                 :            :     changes)
     148                 :            :  */
     149                 :          0 : basegfx::B2DPolyPolygon prepareClip( const basegfx::B2DPolyPolygon& rClip )
     150                 :            : {
     151                 :          0 :     basegfx::B2DPolyPolygon aClip( rClip );
     152                 :            : 
     153                 :            :     // TODO(P2): unnecessary, once XCanvas is correctly handling this
     154                 :            :     // AW: Should be no longer necessary; tools are now bezier-safe
     155                 :          0 :     if( aClip.areControlPointsUsed() )
     156                 :          0 :         aClip = basegfx::tools::adaptiveSubdivideByAngle( aClip );
     157                 :            : 
     158                 :            :     // normalize polygon, preparation for clipping
     159                 :            :     // in updateCanvas()
     160                 :          0 :     aClip = basegfx::tools::correctOrientations(aClip);
     161                 :          0 :     aClip = basegfx::tools::solveCrossovers(aClip);
     162                 :          0 :     aClip = basegfx::tools::stripNeutralPolygons(aClip);
     163                 :          0 :     aClip = basegfx::tools::stripDispensablePolygons(aClip, false);
     164                 :            : 
     165                 :          0 :     return aClip;
     166                 :            : }
     167                 :            : 
     168                 :            : 
     169                 :          0 : void clearRect( ::cppcanvas::CanvasSharedPtr const& pCanvas,
     170                 :            :                 basegfx::B2IRange const&            rArea )
     171                 :            : {
     172                 :            :     // convert clip polygon to device coordinate system
     173                 :          0 :     ::basegfx::B2DPolyPolygon const* pClipPoly( pCanvas->getClip() );
     174                 :          0 :     if( pClipPoly )
     175                 :            :     {
     176                 :          0 :         ::basegfx::B2DPolyPolygon aClipPoly( *pClipPoly );
     177                 :          0 :         aClipPoly.transform( pCanvas->getTransformation() );
     178                 :          0 :         pCanvas->setClip( aClipPoly );
     179                 :            :     }
     180                 :            : 
     181                 :            :     // set transformation to identitiy (->device pixel)
     182                 :          0 :     pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
     183                 :            : 
     184                 :            :     // #i42440# Fill the _full_ background in
     185                 :            :     // black. Since we had to extend the bitmap by one
     186                 :            :     // pixel, and the bitmap is initialized white,
     187                 :            :     // depending on the slide content a one pixel wide
     188                 :            :     // line will show to the bottom and the right.
     189                 :            :     const ::basegfx::B2DPolygon aPoly(
     190                 :            :         ::basegfx::tools::createPolygonFromRect(
     191                 :          0 :             basegfx::B2DRange(rArea)));
     192                 :            : 
     193                 :            :     ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
     194                 :          0 :         ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCanvas,
     195                 :          0 :                                                                       aPoly ) );
     196                 :            : 
     197                 :          0 :     if( pPolyPoly )
     198                 :            :     {
     199                 :          0 :         pPolyPoly->setCompositeOp( cppcanvas::CanvasGraphic::SOURCE );
     200                 :          0 :         pPolyPoly->setRGBAFillColor( 0xFFFFFF00U );
     201                 :          0 :         pPolyPoly->draw();
     202                 :          0 :     }
     203                 :            : 
     204                 :            : #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
     205                 :            :     ::cppcanvas::CanvasSharedPtr pCliplessCanvas( pCanvas->clone() );
     206                 :            :     pCliplessCanvas->setClip();
     207                 :            : 
     208                 :            :     if( pCanvas->getClip() )
     209                 :            :     {
     210                 :            :         ::cppcanvas::PolyPolygonSharedPtr pPolyPoly2(
     211                 :            :             ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCliplessCanvas,
     212                 :            :                                                                           aPoly ));
     213                 :            :         if( pPolyPoly2 )
     214                 :            :         {
     215                 :            :             pPolyPoly2->setRGBALineColor( 0x008000FFU );
     216                 :            :             pPolyPoly2->draw();
     217                 :            :         }
     218                 :            :     }
     219                 :            : #endif
     220                 :          0 : }
     221                 :            : 
     222                 :            : /** Get bounds in pixel
     223                 :            : 
     224                 :            :     @param rLayerBounds
     225                 :            :     Bound rect, in user space coordinates
     226                 :            : 
     227                 :            :     @param rTransformation
     228                 :            :     User space to device pixel transformation
     229                 :            : 
     230                 :            :     @return the layer bounds in pixel, extended by one pixel to the
     231                 :            :     right and bottom
     232                 :            :  */
     233                 :          0 : basegfx::B2IRange getLayerBoundsPixel( basegfx::B2DRange const&     rLayerBounds,
     234                 :            :                                        basegfx::B2DHomMatrix const& rTransformation )
     235                 :            : {
     236                 :          0 :     ::basegfx::B2DRange aTmpRect;
     237                 :            :     ::canvas::tools::calcTransformedRectBounds( aTmpRect,
     238                 :            :                                                 rLayerBounds,
     239                 :          0 :                                                 rTransformation );
     240                 :            : 
     241                 :          0 :     if( aTmpRect.isEmpty() )
     242                 :          0 :         return ::basegfx::B2IRange();
     243                 :            : 
     244                 :            :     // #i42440# Returned layer size is one pixel too small, as
     245                 :            :     // rendering happens one pixel to the right and below the
     246                 :            :     // actual bound rect.
     247                 :            :     return ::basegfx::B2IRange( ::basegfx::fround(aTmpRect.getMinX()),
     248                 :            :                                 ::basegfx::fround(aTmpRect.getMinY()),
     249                 :          0 :                                 ::basegfx::fround(aTmpRect.getMaxX()) + 1,
     250                 :          0 :                                 ::basegfx::fround(aTmpRect.getMaxY()) + 1 );
     251                 :            : }
     252                 :            : 
     253                 :            : 
     254                 :            : // ----------------------------------------------------------------
     255                 :            : 
     256                 :            : /** Container class for sprites issued by a ViewLayer
     257                 :            : 
     258                 :            :     This class handles the sprite prioritization issues, that are
     259                 :            :     needed for layer sprites (e.g. the need to re-prioritize sprites
     260                 :            :     when the layer changes prio).
     261                 :            :  */
     262                 :          0 : class LayerSpriteContainer
     263                 :            : {
     264                 :            :     /** Max fill level of maSprites, before we try to prune it from
     265                 :            :         deceased sprites
     266                 :            :     */
     267                 :            :     enum{ SPRITE_ULLAGE=256 };
     268                 :            : 
     269                 :            :     /** All sprites that have been issued by this container (pruned
     270                 :            :         from time to time, for invalid references). This vector is
     271                 :            :         kept sorted with increasing sprite priority.
     272                 :            :     */
     273                 :            :     SpriteVector       maSprites;
     274                 :            : 
     275                 :            :     /// Priority of this layer, relative to other view layers
     276                 :            :     basegfx::B1DRange  maLayerPrioRange;
     277                 :            : 
     278                 :          0 :     double getSpritePriority( std::size_t nSpriteNum ) const
     279                 :            :     {
     280                 :            :         // divide the available layer range equally between all
     281                 :            :         // sprites, assign upper bound of individual sprite range as
     282                 :            :         // sprite prio (the layer itself gets assigned the lower bound
     283                 :            :         // of sprite 0's individual range):
     284                 :            :         //
     285                 :            :         // | layer 0                    | layer 1                    | ...
     286                 :            :         // |    sprite 0 |    sprite 1  |    sprite 0 |    sprite 1  | ...
     287                 :          0 :         return maLayerPrioRange.getMinimum() + maLayerPrioRange.getRange()*(nSpriteNum+1)/(maSprites.size()+1);
     288                 :            :     }
     289                 :            : 
     290                 :            :     /** Rescan sprite vector, and remove deceased sprites (and reset
     291                 :            :         sprite prio)
     292                 :            : 
     293                 :            :         @param aBegin
     294                 :            :         Iterator to the first entry to rescan
     295                 :            :      */
     296                 :          0 :     void updateSprites()
     297                 :            :     {
     298                 :          0 :         SpriteVector aValidSprites;
     299                 :            : 
     300                 :            :         // check all sprites for validity and set new priority
     301                 :          0 :         SpriteVector::iterator       aCurrSprite( maSprites.begin() );
     302                 :          0 :         const SpriteVector::iterator aEnd( maSprites.end() );
     303                 :          0 :         while( aCurrSprite != aEnd )
     304                 :            :         {
     305                 :          0 :             cppcanvas::CustomSpriteSharedPtr pCurrSprite( aCurrSprite->mpSprite.lock() );
     306                 :            : 
     307                 :          0 :             if( pCurrSprite )
     308                 :            :             {
     309                 :            :                 // only copy still valid sprites over to the refreshed
     310                 :            :                 // sprite vector.
     311                 :          0 :                 aValidSprites.push_back( *aCurrSprite );
     312                 :            : 
     313                 :          0 :                 pCurrSprite->setPriority(
     314                 :          0 :                     getSpritePriority( aValidSprites.size()-1 ));
     315                 :            :             }
     316                 :            : 
     317                 :          0 :             ++aCurrSprite;
     318                 :          0 :         }
     319                 :            : 
     320                 :            :         // replace sprite list with pruned one
     321                 :          0 :         maSprites.swap( aValidSprites );
     322                 :          0 :     }
     323                 :            : 
     324                 :            : public:
     325                 :          0 :     LayerSpriteContainer() :
     326                 :            :         maSprites(),
     327                 :          0 :         maLayerPrioRange()
     328                 :            :     {
     329                 :          0 :     }
     330                 :            : 
     331                 :          0 :     basegfx::B1DRange getLayerPriority() const
     332                 :            :     {
     333                 :          0 :         return maLayerPrioRange;
     334                 :            :     }
     335                 :            : 
     336                 :          0 :     void setLayerPriority( const basegfx::B1DRange& rRange )
     337                 :            :     {
     338                 :          0 :         if( rRange != maLayerPrioRange )
     339                 :            :         {
     340                 :          0 :             maLayerPrioRange = rRange;
     341                 :            : 
     342                 :            :             // prune and recalc sprite prios
     343                 :          0 :             updateSprites();
     344                 :            :         }
     345                 :          0 :     }
     346                 :            : 
     347                 :          0 :     void addSprite( const cppcanvas::CustomSpriteSharedPtr& pSprite,
     348                 :            :                     double                                  nPriority )
     349                 :            :     {
     350                 :          0 :         if( !pSprite )
     351                 :          0 :             return;
     352                 :            : 
     353                 :          0 :         SpriteEntry aEntry( pSprite,nPriority );
     354                 :            : 
     355                 :            :         // insert new sprite, such that vector stays sorted
     356                 :            :         SpriteVector::iterator aInsertPos(
     357                 :            :             maSprites.insert(
     358                 :            :                 std::lower_bound( maSprites.begin(),
     359                 :            :                                   maSprites.end(),
     360                 :            :                                   aEntry ),
     361                 :          0 :                 aEntry ));
     362                 :            : 
     363                 :          0 :         const std::size_t nNumSprites( maSprites.size() );
     364                 :          0 :         if( nNumSprites > SPRITE_ULLAGE ||
     365                 :          0 :             maSprites.end() - aInsertPos > 1 )
     366                 :            :         {
     367                 :            :             // updateSprites() also updates all sprite prios
     368                 :          0 :             updateSprites();
     369                 :            :         }
     370                 :            :         else
     371                 :            :         {
     372                 :            :             // added sprite to the end, and not too many sprites in
     373                 :            :             // vector - perform optimized update (only need to set
     374                 :            :             // prio). This basically caters for the common case of
     375                 :            :             // iterated character animations, which generate lots of
     376                 :            :             // sprites, all added to the end.
     377                 :          0 :             pSprite->setPriority(
     378                 :          0 :                 getSpritePriority( nNumSprites-1 ));
     379                 :          0 :         }
     380                 :            :     }
     381                 :            : 
     382                 :          0 :     void clear()
     383                 :            :     {
     384                 :          0 :         maSprites.clear();
     385                 :          0 :     }
     386                 :            : };
     387                 :            : 
     388                 :            : 
     389                 :            : // ----------------------------------------------------------------
     390                 :            : 
     391                 :            : 
     392                 :            : /** This class provides layers for a slide view
     393                 :            : 
     394                 :            :     Layers are used to render animations with the correct z order -
     395                 :            :     because sprites are always in front of the static canvas
     396                 :            :     background, shapes that must appear <em<before</em> an animation
     397                 :            :     must also be displayed as a sprite.
     398                 :            : 
     399                 :            :     Each layer has a priority assigned to it (valid range [0,1]), which
     400                 :            :     also affects all sprites created for this specific layer - i.e. if
     401                 :            :     the layer priority changes, the sprites change z order together
     402                 :            :     with their parent.
     403                 :            :  */
     404                 :          0 : class SlideViewLayer : public ViewLayer,
     405                 :            :                        private boost::noncopyable
     406                 :            : {
     407                 :            :     /// Smart container for all sprites issued by this layer
     408                 :            :     mutable LayerSpriteContainer             maSpriteContainer;
     409                 :            : 
     410                 :            :     /// Bounds of this layer in user space coordinates
     411                 :            :     basegfx::B2DRange                        maLayerBounds;
     412                 :            : 
     413                 :            :     /// Bounds of this layer in device pixel
     414                 :            :     mutable basegfx::B2IRange                maLayerBoundsPixel;
     415                 :            : 
     416                 :            :     /// Current clip polygon in user coordinates
     417                 :            :     basegfx::B2DPolyPolygon                  maClip;
     418                 :            : 
     419                 :            :     /// Current size of the view in user coordinates
     420                 :            :     basegfx::B2DSize                         maUserSize;
     421                 :            : 
     422                 :            :     /// Current overall view transformation
     423                 :            :     basegfx::B2DHomMatrix                    maTransformation;
     424                 :            : 
     425                 :            :     /// 'parent' canvas, this viewlayer is associated with
     426                 :            :     const cppcanvas::SpriteCanvasSharedPtr   mpSpriteCanvas;
     427                 :            : 
     428                 :            :     /** output surface (necessarily a sprite, won't otherwise be able
     429                 :            :         to display anything <em>before</em> other sprites)
     430                 :            :     */
     431                 :            :     mutable cppcanvas::CustomSpriteSharedPtr mpSprite;
     432                 :            : 
     433                 :            :     /// actual output canvas retrieved from a sprite
     434                 :            :     mutable cppcanvas::CanvasSharedPtr       mpOutputCanvas;
     435                 :            : 
     436                 :            :     /// ptr back to owning view. needed for isOnView() method
     437                 :            :     View const* const                        mpParentView;
     438                 :            : 
     439                 :            : public:
     440                 :            :     /** Create a new layer
     441                 :            : 
     442                 :            :         @param pCanvas
     443                 :            :         Sprite canvas to create the layer on
     444                 :            : 
     445                 :            :         @param rTransform
     446                 :            :         Initial overall canvas transformation
     447                 :            : 
     448                 :            :         @param rLayerBounds
     449                 :            :         Initial layer bounds, in view coordinate system
     450                 :            :      */
     451                 :          0 :     SlideViewLayer( const cppcanvas::SpriteCanvasSharedPtr& pCanvas,
     452                 :            :                     const basegfx::B2DHomMatrix&            rTransform,
     453                 :            :                     const basegfx::B2DRange&                rLayerBounds,
     454                 :            :                     const basegfx::B2DSize&                 rUserSize,
     455                 :            :                     View const* const                       pParentView) :
     456                 :            :         maSpriteContainer(),
     457                 :            :         maLayerBounds(rLayerBounds),
     458                 :            :         maLayerBoundsPixel(),
     459                 :            :         maClip(),
     460                 :            :         maUserSize(rUserSize),
     461                 :            :         maTransformation(rTransform),
     462                 :            :         mpSpriteCanvas(pCanvas),
     463                 :            :         mpSprite(),
     464                 :            :         mpOutputCanvas(),
     465                 :          0 :         mpParentView(pParentView)
     466                 :            :     {
     467                 :          0 :     }
     468                 :            : 
     469                 :          0 :     void updateView( const basegfx::B2DHomMatrix& rMatrix,
     470                 :            :                      const basegfx::B2DSize&      rUserSize )
     471                 :            :     {
     472                 :          0 :         maTransformation = rMatrix;
     473                 :          0 :         maUserSize = rUserSize;
     474                 :            : 
     475                 :            :         // limit layer bounds to visible screen
     476                 :            :         maLayerBounds.intersect( basegfx::B2DRange(0.0,
     477                 :            :                                                    0.0,
     478                 :            :                                                    maUserSize.getX(),
     479                 :          0 :                                                    maUserSize.getY()) );
     480                 :            : 
     481                 :            :         basegfx::B2IRange const& rNewLayerPixel(
     482                 :            :             getLayerBoundsPixel(maLayerBounds,
     483                 :          0 :                                 maTransformation) );
     484                 :          0 :         if( rNewLayerPixel != maLayerBoundsPixel )
     485                 :            :         {
     486                 :            :             // re-gen sprite with new size
     487                 :          0 :             mpOutputCanvas.reset();
     488                 :          0 :             mpSprite.reset();
     489                 :            :         }
     490                 :          0 :     }
     491                 :            : 
     492                 :            : private:
     493                 :            :     // ViewLayer interface
     494                 :            :     // ----------------------------------------------
     495                 :            : 
     496                 :          0 :     virtual cppcanvas::CustomSpriteSharedPtr createSprite(
     497                 :            :         const ::basegfx::B2DSize& rSpriteSizePixel,
     498                 :            :         double                    nPriority ) const
     499                 :            :     {
     500                 :            :         cppcanvas::CustomSpriteSharedPtr pSprite(
     501                 :          0 :             mpSpriteCanvas->createCustomSprite( rSpriteSizePixel ) );
     502                 :            : 
     503                 :            :         maSpriteContainer.addSprite( pSprite,
     504                 :          0 :                                      nPriority );
     505                 :            : 
     506                 :          0 :         return pSprite;
     507                 :            :     }
     508                 :            : 
     509                 :          0 :     virtual void setPriority( const basegfx::B1DRange& rRange )
     510                 :            :     {
     511                 :            :         OSL_ENSURE( !rRange.isEmpty() &&
     512                 :            :                     rRange.getMinimum() >= 1.0,
     513                 :            :                     "SlideViewLayer::setPriority(): prio MUST be larger than 1.0 (because "
     514                 :            :                     "the background layer already lies there)" );
     515                 :            : 
     516                 :          0 :         maSpriteContainer.setLayerPriority( rRange );
     517                 :            : 
     518                 :          0 :         if( mpSprite )
     519                 :          0 :             mpSprite->setPriority( rRange.getMinimum() );
     520                 :          0 :     }
     521                 :            : 
     522                 :          0 :     virtual basegfx::B2DHomMatrix getTransformation() const
     523                 :            :     {
     524                 :            :         // Offset given transformation by left, top border of given
     525                 :            :         // range (after transformation through given transformation)
     526                 :          0 :         basegfx::B2DRectangle aTmpRect;
     527                 :            :         canvas::tools::calcTransformedRectBounds( aTmpRect,
     528                 :            :                                                   maLayerBounds,
     529                 :          0 :                                                   maTransformation );
     530                 :            : 
     531                 :          0 :         basegfx::B2DHomMatrix aMatrix( maTransformation );
     532                 :            : 
     533                 :            :         // Add translation according to the origin of aTmpRect.  Ignore the
     534                 :            :         // translation when aTmpRect was not properly initialized.
     535                 :          0 :         if ( ! aTmpRect.isEmpty())
     536                 :            :         {
     537                 :          0 :             aMatrix.translate( -basegfx::fround(aTmpRect.getMinX()),
     538                 :          0 :                                -basegfx::fround(aTmpRect.getMinY()) );
     539                 :            :         }
     540                 :            : 
     541                 :          0 :         return aMatrix;
     542                 :            :     }
     543                 :            : 
     544                 :          0 :     virtual basegfx::B2DHomMatrix getSpriteTransformation() const
     545                 :            :     {
     546                 :          0 :         return maTransformation;
     547                 :            :     }
     548                 :            : 
     549                 :          0 :     virtual void clear() const
     550                 :            :     {
     551                 :            :         // grab canvas - that also lazy-initializes maLayerBoundsPixel
     552                 :          0 :         cppcanvas::CanvasSharedPtr pCanvas=getCanvas()->clone();
     553                 :            : 
     554                 :            :         // clear whole canvas
     555                 :          0 :         const basegfx::B2I64Tuple& rSpriteSize(maLayerBoundsPixel.getRange());
     556                 :            :         clearRect(pCanvas,
     557                 :          0 :                   basegfx::B2IRange(0,0,rSpriteSize.getX(),rSpriteSize.getY()));
     558                 :          0 :     }
     559                 :            : 
     560                 :          0 :     virtual void clearAll() const
     561                 :            :     {
     562                 :            :         // grab canvas - that also lazy-initializes maLayerBoundsPixel
     563                 :          0 :         ::cppcanvas::CanvasSharedPtr pCanvas( getCanvas()->clone() );
     564                 :            : 
     565                 :            :         // clear layer clip, to clear whole area
     566                 :          0 :         pCanvas->setClip();
     567                 :            : 
     568                 :            :         // clear whole canvas
     569                 :          0 :         const basegfx::B2I64Tuple& rSpriteSize(maLayerBoundsPixel.getRange());
     570                 :            :         clearRect(pCanvas,
     571                 :          0 :                   basegfx::B2IRange(0,0,rSpriteSize.getX(),rSpriteSize.getY()));
     572                 :          0 :     }
     573                 :            : 
     574                 :          0 :     virtual bool isOnView(boost::shared_ptr<View> const& rView) const
     575                 :            :     {
     576                 :          0 :         return rView.get() == mpParentView;
     577                 :            :     }
     578                 :            : 
     579                 :          0 :     virtual cppcanvas::CanvasSharedPtr getCanvas() const
     580                 :            :     {
     581                 :          0 :         if( !mpOutputCanvas )
     582                 :            :         {
     583                 :          0 :             if( !mpSprite )
     584                 :            :             {
     585                 :            :                 maLayerBoundsPixel = getLayerBoundsPixel(maLayerBounds,
     586                 :          0 :                                                          maTransformation);
     587                 :            : 
     588                 :            :                 // HACK: ensure at least 1x1 pixel size. clients might
     589                 :            :                 // need an actual canvas (e.g. for bound rect
     590                 :            :                 // calculations) without rendering anything. Better
     591                 :            :                 // solution: introduce something like a reference
     592                 :            :                 // canvas for ViewLayers, which is always available.
     593                 :          0 :                 if( maLayerBoundsPixel.isEmpty() )
     594                 :          0 :                     maLayerBoundsPixel = basegfx::B2IRange(0,0,1,1);
     595                 :            : 
     596                 :          0 :                 const basegfx::B2I64Tuple& rSpriteSize(maLayerBoundsPixel.getRange());
     597                 :          0 :                 mpSprite = mpSpriteCanvas->createCustomSprite(
     598                 :          0 :                     basegfx::B2DVector(sal::static_int_cast<sal_Int32>(rSpriteSize.getX()),
     599                 :          0 :                                        sal::static_int_cast<sal_Int32>(rSpriteSize.getY())) );
     600                 :            : 
     601                 :          0 :                 mpSprite->setPriority(
     602                 :          0 :                     maSpriteContainer.getLayerPriority().getMinimum() );
     603                 :            : 
     604                 :            : #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
     605                 :            :                 mpSprite->movePixel(
     606                 :            :                     basegfx::B2DPoint(maLayerBoundsPixel.getMinimum()) +
     607                 :            :                     basegfx::B2DPoint(10,10) );
     608                 :            : 
     609                 :            :                 mpSprite->setAlpha(0.5);
     610                 :            : #else
     611                 :          0 :                 mpSprite->movePixel(
     612                 :          0 :                     basegfx::B2DPoint(maLayerBoundsPixel.getMinimum()) );
     613                 :            : 
     614                 :          0 :                 mpSprite->setAlpha(1.0);
     615                 :            : #endif
     616                 :          0 :                 mpSprite->show();
     617                 :            :             }
     618                 :            : 
     619                 :          0 :             ENSURE_OR_THROW( mpSprite,
     620                 :            :                               "SlideViewLayer::getCanvas(): no layer sprite" );
     621                 :            : 
     622                 :          0 :             mpOutputCanvas = mpSprite->getContentCanvas();
     623                 :            : 
     624                 :          0 :             ENSURE_OR_THROW( mpOutputCanvas,
     625                 :            :                               "SlideViewLayer::getCanvas(): sprite doesn't yield a canvas" );
     626                 :            : 
     627                 :            :             // new canvas retrieved - setup transformation and clip
     628                 :          0 :             mpOutputCanvas->setTransformation( getTransformation() );
     629                 :          0 :             mpOutputCanvas->setClip(
     630                 :            :                 createClipPolygon( maClip,
     631                 :            :                                    mpOutputCanvas,
     632                 :          0 :                                    maUserSize ));
     633                 :            :         }
     634                 :            : 
     635                 :          0 :         return mpOutputCanvas;
     636                 :            :     }
     637                 :            : 
     638                 :          0 :     virtual void setClip( const basegfx::B2DPolyPolygon& rClip )
     639                 :            :     {
     640                 :          0 :         basegfx::B2DPolyPolygon aNewClip = prepareClip( rClip );
     641                 :            : 
     642                 :          0 :         if( aNewClip != maClip )
     643                 :            :         {
     644                 :          0 :             maClip = aNewClip;
     645                 :            : 
     646                 :          0 :             if(mpOutputCanvas )
     647                 :          0 :                 mpOutputCanvas->setClip(
     648                 :            :                     createClipPolygon( maClip,
     649                 :            :                                        mpOutputCanvas,
     650                 :          0 :                                        maUserSize ));
     651                 :          0 :         }
     652                 :          0 :     }
     653                 :            : 
     654                 :          0 :     virtual bool resize( const ::basegfx::B2DRange& rArea )
     655                 :            :     {
     656                 :          0 :         const bool bRet( maLayerBounds != rArea );
     657                 :          0 :         maLayerBounds = rArea;
     658                 :            :         updateView( maTransformation,
     659                 :          0 :                     maUserSize );
     660                 :            : 
     661                 :          0 :         return bRet;
     662                 :            :     }
     663                 :            : };
     664                 :            : 
     665                 :            : 
     666                 :            : // ---------------------------------------------------------
     667                 :            : 
     668                 :            : typedef cppu::WeakComponentImplHelper2<
     669                 :            :     ::com::sun::star::util::XModifyListener,
     670                 :            :       ::com::sun::star::awt::XPaintListener> SlideViewBase;
     671                 :            : 
     672                 :            : /** SlideView class
     673                 :            : 
     674                 :            :     This class implements the View interface, encapsulating
     675                 :            :     <em>one</em> view a slideshow is displayed on.
     676                 :            :  */
     677                 :          0 : class SlideView : private cppu::BaseMutex,
     678                 :            :                   public SlideViewBase,
     679                 :            :                   public UnoView
     680                 :            : {
     681                 :            : public:
     682                 :            :     SlideView( const uno::Reference<presentation::XSlideShowView>& xView,
     683                 :            :                EventQueue&                                         rEventQueue,
     684                 :            :                EventMultiplexer&                                   rEventMultiplexer );
     685                 :            :     void updateCanvas();
     686                 :            : 
     687                 :            : private:
     688                 :            :     // View:
     689                 :            :     virtual ViewLayerSharedPtr createViewLayer( const basegfx::B2DRange& rLayerBounds ) const;
     690                 :            :     virtual bool updateScreen() const;
     691                 :            :     virtual bool paintScreen() const;
     692                 :            :     virtual void setViewSize( const ::basegfx::B2DSize& );
     693                 :            :     virtual void setCursorShape( sal_Int16 nPointerShape );
     694                 :            : 
     695                 :            :     // ViewLayer interface
     696                 :            :     virtual bool isOnView(boost::shared_ptr<View> const& rView) const;
     697                 :            :     virtual void clear() const;
     698                 :            :     virtual void clearAll() const;
     699                 :            :     virtual cppcanvas::CanvasSharedPtr getCanvas() const;
     700                 :            :     virtual cppcanvas::CustomSpriteSharedPtr createSprite( const ::basegfx::B2DSize& rSpriteSizePixel,
     701                 :            :                                                            double                    nPriority ) const;
     702                 :            :     virtual void setPriority( const basegfx::B1DRange& rRange );
     703                 :            :     virtual ::basegfx::B2DHomMatrix getTransformation() const;
     704                 :            :     virtual basegfx::B2DHomMatrix getSpriteTransformation() const;
     705                 :            :     virtual void setClip( const ::basegfx::B2DPolyPolygon& rClip );
     706                 :            :     virtual bool resize( const ::basegfx::B2DRange& rArea );
     707                 :            : 
     708                 :            :     // UnoView:
     709                 :            :     virtual void _dispose();
     710                 :            :     virtual uno::Reference<presentation::XSlideShowView> getUnoView()const;
     711                 :            :     virtual void setIsSoundEnabled (const bool bValue);
     712                 :            :     virtual bool isSoundEnabled (void) const;
     713                 :            : 
     714                 :            :     // XEventListener:
     715                 :            :     virtual void SAL_CALL disposing( lang::EventObject const& evt )
     716                 :            :         throw (uno::RuntimeException);
     717                 :            :     // XModifyListener:
     718                 :            :     virtual void SAL_CALL modified( const lang::EventObject& aEvent )
     719                 :            :         throw (uno::RuntimeException);
     720                 :            :     // XPaintListener:
     721                 :            :     virtual void SAL_CALL windowPaint( const awt::PaintEvent& e )
     722                 :            :         throw (uno::RuntimeException);
     723                 :            : 
     724                 :            :     // WeakComponentImplHelperBase:
     725                 :            :     virtual void SAL_CALL disposing();
     726                 :            : 
     727                 :            :     void updateClip();
     728                 :            : 
     729                 :            : private:
     730                 :            :     typedef std::vector< boost::weak_ptr<SlideViewLayer> > ViewLayerVector;
     731                 :            : 
     732                 :            :     /// Prune viewlayers from deceased ones, optionally update them
     733                 :            :     void pruneLayers( bool bWithViewLayerUpdate=false ) const;
     734                 :            : 
     735                 :            :     /** Max fill level of maViewLayers, before we try to prune it from
     736                 :            :         deceased layers
     737                 :            :     */
     738                 :            :     enum{ LAYER_ULLAGE=8 };
     739                 :            : 
     740                 :            :     uno::Reference<presentation::XSlideShowView>              mxView;
     741                 :            :     cppcanvas::SpriteCanvasSharedPtr                          mpCanvas;
     742                 :            : 
     743                 :            :     EventMultiplexer&                                         mrEventMultiplexer;
     744                 :            :     EventQueue&                                               mrEventQueue;
     745                 :            : 
     746                 :            :     mutable LayerSpriteContainer                              maSprites;
     747                 :            :     mutable ViewLayerVector                                   maViewLayers;
     748                 :            : 
     749                 :            :     basegfx::B2DPolyPolygon                                   maClip;
     750                 :            : 
     751                 :            :     basegfx::B2DHomMatrix                                     maViewTransform;
     752                 :            :     basegfx::B2DSize                                          maUserSize;
     753                 :            :     bool mbIsSoundEnabled;
     754                 :            : };
     755                 :            : 
     756                 :            : 
     757                 :          0 : SlideView::SlideView( const uno::Reference<presentation::XSlideShowView>& xView,
     758                 :            :                       EventQueue&                                         rEventQueue,
     759                 :            :                       EventMultiplexer&                                   rEventMultiplexer ) :
     760                 :            :     SlideViewBase( m_aMutex ),
     761                 :            :     mxView( xView ),
     762                 :            :     mpCanvas(),
     763                 :            :     mrEventMultiplexer( rEventMultiplexer ),
     764                 :            :     mrEventQueue( rEventQueue ),
     765                 :            :     maSprites(),
     766                 :            :     maViewLayers(),
     767                 :            :     maClip(),
     768                 :            :     maViewTransform(),
     769                 :            :     maUserSize( 1.0, 1.0 ), // default size: one-by-one rectangle
     770                 :          0 :     mbIsSoundEnabled(true)
     771                 :            : {
     772                 :            :     // take care not constructing any UNO references to this _inside_
     773                 :            :     // ctor, shift that code to createSlideView()!
     774                 :          0 :     ENSURE_OR_THROW( mxView.is(),
     775                 :            :                       "SlideView::SlideView(): Invalid view" );
     776                 :            : 
     777                 :          0 :     mpCanvas = cppcanvas::VCLFactory::getInstance().createSpriteCanvas(
     778                 :          0 :         xView->getCanvas() );
     779                 :          0 :     ENSURE_OR_THROW( mpCanvas,
     780                 :            :                       "Could not create cppcanvas" );
     781                 :            : 
     782                 :            :     geometry::AffineMatrix2D aViewTransform(
     783                 :          0 :         xView->getTransformation() );
     784                 :            : 
     785                 :          0 :     if( basegfx::fTools::equalZero(
     786                 :            :             basegfx::B2DVector(aViewTransform.m00,
     787                 :          0 :                                aViewTransform.m10).getLength()) ||
     788                 :            :         basegfx::fTools::equalZero(
     789                 :            :             basegfx::B2DVector(aViewTransform.m01,
     790                 :          0 :                                aViewTransform.m11).getLength()) )
     791                 :            :     {
     792                 :            :         OSL_FAIL( "SlideView::SlideView(): Singular matrix!" );
     793                 :            : 
     794                 :          0 :         canvas::tools::setIdentityAffineMatrix2D(aViewTransform);
     795                 :            :     }
     796                 :            : 
     797                 :            :     basegfx::unotools::homMatrixFromAffineMatrix(
     798                 :          0 :         maViewTransform, aViewTransform );
     799                 :            : 
     800                 :            :     // once and forever: set fixed prio to this 'layer' (we're always
     801                 :            :     // the background layer)
     802                 :          0 :     maSprites.setLayerPriority( basegfx::B1DRange(0.0,1.0) );
     803                 :          0 : }
     804                 :            : 
     805                 :          0 : void SlideView::disposing()
     806                 :            : {
     807                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     808                 :            : 
     809                 :          0 :     maViewLayers.clear();
     810                 :          0 :     maSprites.clear();
     811                 :          0 :     mpCanvas.reset();
     812                 :            : 
     813                 :            :     // additionally, also de-register from XSlideShowView
     814                 :          0 :     if (mxView.is())
     815                 :            :     {
     816                 :          0 :         mxView->removeTransformationChangedListener( this );
     817                 :          0 :         mxView->removePaintListener( this );
     818                 :          0 :         mxView.clear();
     819                 :          0 :     }
     820                 :          0 : }
     821                 :            : 
     822                 :          0 : ViewLayerSharedPtr SlideView::createViewLayer( const basegfx::B2DRange& rLayerBounds ) const
     823                 :            : {
     824                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     825                 :            : 
     826                 :          0 :     ENSURE_OR_THROW( mpCanvas,
     827                 :            :                       "SlideView::createViewLayer(): Disposed" );
     828                 :            : 
     829                 :          0 :     const std::size_t nNumLayers( maViewLayers.size() );
     830                 :            : 
     831                 :            :     // avoid filling up layer vector with lots of deceased layer weak
     832                 :            :     // ptrs
     833                 :          0 :     if( nNumLayers > LAYER_ULLAGE )
     834                 :          0 :         pruneLayers();
     835                 :            : 
     836                 :            :     boost::shared_ptr<SlideViewLayer> pViewLayer( new SlideViewLayer(mpCanvas,
     837                 :          0 :                                                                      getTransformation(),
     838                 :            :                                                                      rLayerBounds,
     839                 :            :                                                                      maUserSize,
     840                 :          0 :                                                                      this) );
     841                 :          0 :     maViewLayers.push_back( pViewLayer );
     842                 :            : 
     843                 :          0 :     return pViewLayer;
     844                 :            : }
     845                 :            : 
     846                 :          0 : bool SlideView::updateScreen() const
     847                 :            : {
     848                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     849                 :            : 
     850                 :          0 :     ENSURE_OR_RETURN_FALSE( mpCanvas.get(),
     851                 :            :                        "SlideView::updateScreen(): Disposed" );
     852                 :            : 
     853                 :          0 :     return mpCanvas->updateScreen( false );
     854                 :            : }
     855                 :            : 
     856                 :          0 : bool SlideView::paintScreen() const
     857                 :            : {
     858                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     859                 :            : 
     860                 :          0 :     ENSURE_OR_RETURN_FALSE( mpCanvas.get(),
     861                 :            :                        "SlideView::paintScreen(): Disposed" );
     862                 :            : 
     863                 :          0 :     return mpCanvas->updateScreen( true );
     864                 :            : }
     865                 :            : 
     866                 :          0 : void SlideView::clear() const
     867                 :            : {
     868                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     869                 :            : 
     870                 :            :     OSL_ENSURE( mxView.is() && mpCanvas,
     871                 :            :                 "SlideView::clear(): Disposed" );
     872                 :          0 :     if( !mxView.is() || !mpCanvas )
     873                 :          0 :         return;
     874                 :            : 
     875                 :            :     // keep layer clip
     876                 :          0 :     clearRect(getCanvas()->clone(),
     877                 :            :               getLayerBoundsPixel(
     878                 :            :                   basegfx::B2DRange(0,0,
     879                 :            :                                     maUserSize.getX(),
     880                 :            :                                     maUserSize.getY()),
     881                 :          0 :                   getTransformation()));
     882                 :            : }
     883                 :            : 
     884                 :          0 : void SlideView::clearAll() const
     885                 :            : {
     886                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     887                 :            : 
     888                 :            :     OSL_ENSURE( mxView.is() && mpCanvas,
     889                 :            :                 "SlideView::clear(): Disposed" );
     890                 :          0 :     if( !mxView.is() || !mpCanvas )
     891                 :          0 :         return;
     892                 :            : 
     893                 :            :     // clear whole view
     894                 :          0 :     mxView->clear();
     895                 :            : }
     896                 :            : 
     897                 :          0 : void SlideView::setViewSize( const basegfx::B2DSize& rSize )
     898                 :            : {
     899                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     900                 :            : 
     901                 :          0 :     maUserSize = rSize;
     902                 :          0 :     updateCanvas();
     903                 :          0 : }
     904                 :            : 
     905                 :          0 : void SlideView::setCursorShape( sal_Int16 nPointerShape )
     906                 :            : {
     907                 :          0 :     osl::MutexGuard const guard( m_aMutex );
     908                 :            : 
     909                 :          0 :     if (mxView.is())
     910                 :          0 :         mxView->setMouseCursor( nPointerShape );
     911                 :          0 : }
     912                 :            : 
     913                 :          0 : bool SlideView::isOnView(boost::shared_ptr<View> const& rView) const
     914                 :            : {
     915                 :          0 :     return rView.get() == this;
     916                 :            : }
     917                 :            : 
     918                 :          0 : cppcanvas::CanvasSharedPtr SlideView::getCanvas() const
     919                 :            : {
     920                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     921                 :            : 
     922                 :          0 :     ENSURE_OR_THROW( mpCanvas,
     923                 :            :                       "SlideView::getCanvas(): Disposed" );
     924                 :            : 
     925                 :          0 :     return mpCanvas;
     926                 :            : }
     927                 :            : 
     928                 :          0 : cppcanvas::CustomSpriteSharedPtr SlideView::createSprite(
     929                 :            :     const basegfx::B2DSize& rSpriteSizePixel,
     930                 :            :     double                  nPriority ) const
     931                 :            : {
     932                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     933                 :            : 
     934                 :          0 :     ENSURE_OR_THROW( mpCanvas, "SlideView::createSprite(): Disposed" );
     935                 :            : 
     936                 :            :     cppcanvas::CustomSpriteSharedPtr pSprite(
     937                 :          0 :         mpCanvas->createCustomSprite( rSpriteSizePixel ) );
     938                 :            : 
     939                 :            :     maSprites.addSprite( pSprite,
     940                 :          0 :                          nPriority );
     941                 :            : 
     942                 :          0 :     return pSprite;
     943                 :            : }
     944                 :            : 
     945                 :          0 : void SlideView::setPriority( const basegfx::B1DRange& /*rRange*/ )
     946                 :            : {
     947                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     948                 :            : 
     949                 :            :     OSL_FAIL( "SlideView::setPriority() is a NOOP for slide view - "
     950                 :          0 :                 "content will always be shown in the background" );
     951                 :          0 : }
     952                 :            : 
     953                 :          0 : basegfx::B2DHomMatrix SlideView::getTransformation() const
     954                 :            : {
     955                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     956                 :            : 
     957                 :          0 :     basegfx::B2DHomMatrix aMatrix;
     958                 :          0 :     aMatrix.scale( 1.0/maUserSize.getX(), 1.0/maUserSize.getY() );
     959                 :            : 
     960                 :          0 :     return maViewTransform * aMatrix;
     961                 :            : }
     962                 :            : 
     963                 :          0 : basegfx::B2DHomMatrix SlideView::getSpriteTransformation() const
     964                 :            : {
     965                 :          0 :     return getTransformation();
     966                 :            : }
     967                 :            : 
     968                 :          0 : void SlideView::setClip( const basegfx::B2DPolyPolygon& rClip )
     969                 :            : {
     970                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     971                 :            : 
     972                 :          0 :     basegfx::B2DPolyPolygon aNewClip = prepareClip( rClip );
     973                 :            : 
     974                 :          0 :     if( aNewClip != maClip )
     975                 :            :     {
     976                 :          0 :         maClip = aNewClip;
     977                 :            : 
     978                 :          0 :         updateClip();
     979                 :          0 :     }
     980                 :          0 : }
     981                 :            : 
     982                 :          0 : bool SlideView::resize( const ::basegfx::B2DRange& /*rArea*/ )
     983                 :            : {
     984                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     985                 :            : 
     986                 :            :     OSL_FAIL( "SlideView::resize(): ignored for the View, can't change size "
     987                 :            :                 "effectively, anyway" );
     988                 :            : 
     989                 :          0 :     return false;
     990                 :            : }
     991                 :            : 
     992                 :          0 : uno::Reference<presentation::XSlideShowView> SlideView::getUnoView() const
     993                 :            : {
     994                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
     995                 :          0 :     return mxView;
     996                 :            : }
     997                 :            : 
     998                 :          0 : void SlideView::setIsSoundEnabled (const bool bValue)
     999                 :            : {
    1000                 :          0 :     mbIsSoundEnabled = bValue;
    1001                 :          0 : }
    1002                 :            : 
    1003                 :          0 : bool SlideView::isSoundEnabled (void) const
    1004                 :            : {
    1005                 :          0 :     return mbIsSoundEnabled;
    1006                 :            : }
    1007                 :            : 
    1008                 :          0 : void SlideView::_dispose()
    1009                 :            : {
    1010                 :          0 :     dispose();
    1011                 :          0 : }
    1012                 :            : 
    1013                 :            : // XEventListener
    1014                 :          0 : void SlideView::disposing( lang::EventObject const& evt )
    1015                 :            :     throw (uno::RuntimeException)
    1016                 :            : {
    1017                 :            :     (void)evt;
    1018                 :            : 
    1019                 :            :     // no deregistration necessary anymore, XView has left:
    1020                 :          0 :     osl::MutexGuard const guard( m_aMutex );
    1021                 :            : 
    1022                 :          0 :     if (mxView.is())
    1023                 :            :     {
    1024                 :            :         OSL_ASSERT( evt.Source == mxView );
    1025                 :          0 :         mxView.clear();
    1026                 :            :     }
    1027                 :            : 
    1028                 :          0 :     dispose();
    1029                 :          0 : }
    1030                 :            : 
    1031                 :            : // XModifyListener
    1032                 :          0 : void SlideView::modified( const lang::EventObject& /*aEvent*/ )
    1033                 :            :     throw (uno::RuntimeException)
    1034                 :            : {
    1035                 :          0 :     osl::MutexGuard const guard( m_aMutex );
    1036                 :            : 
    1037                 :            :     OSL_ENSURE( mxView.is(), "SlideView::modified(): "
    1038                 :            :                 "Disposed, but event received from XSlideShowView?!");
    1039                 :            : 
    1040                 :          0 :     if( !mxView.is() )
    1041                 :            :         return;
    1042                 :            : 
    1043                 :            :     geometry::AffineMatrix2D aViewTransform(
    1044                 :          0 :         mxView->getTransformation() );
    1045                 :            : 
    1046                 :          0 :     if( basegfx::fTools::equalZero(
    1047                 :            :             basegfx::B2DVector(aViewTransform.m00,
    1048                 :          0 :                                aViewTransform.m10).getLength()) ||
    1049                 :            :         basegfx::fTools::equalZero(
    1050                 :            :             basegfx::B2DVector(aViewTransform.m01,
    1051                 :          0 :                                aViewTransform.m11).getLength()) )
    1052                 :            :     {
    1053                 :            :         OSL_FAIL( "SlideView::modified(): Singular matrix!" );
    1054                 :            : 
    1055                 :          0 :         canvas::tools::setIdentityAffineMatrix2D(aViewTransform);
    1056                 :            :     }
    1057                 :            : 
    1058                 :            :     // view transformation really changed?
    1059                 :          0 :     basegfx::B2DHomMatrix aNewTransform;
    1060                 :            :     basegfx::unotools::homMatrixFromAffineMatrix(
    1061                 :            :         aNewTransform,
    1062                 :          0 :         aViewTransform );
    1063                 :            : 
    1064                 :          0 :     if( aNewTransform == maViewTransform )
    1065                 :            :         return; // No change, nothing to do
    1066                 :            : 
    1067                 :          0 :     maViewTransform = aNewTransform;
    1068                 :            : 
    1069                 :          0 :     updateCanvas();
    1070                 :            : 
    1071                 :            :     // notify view change. Don't call EventMultiplexer directly, this
    1072                 :            :     // might not be the main thread!
    1073                 :            :     mrEventQueue.addEvent(
    1074                 :            :         makeEvent( boost::bind( (bool (EventMultiplexer::*)(
    1075                 :            :                                      const uno::Reference<presentation::XSlideShowView>&))
    1076                 :            :                                 &EventMultiplexer::notifyViewChanged,
    1077                 :            :                                 boost::ref(mrEventMultiplexer), mxView ),
    1078                 :          0 :                    "EventMultiplexer::notifyViewChanged"));
    1079                 :            : }
    1080                 :            : 
    1081                 :            : // XPaintListener
    1082                 :          0 : void SlideView::windowPaint( const awt::PaintEvent& /*e*/ )
    1083                 :            :     throw (uno::RuntimeException)
    1084                 :            : {
    1085                 :          0 :     osl::MutexGuard aGuard( m_aMutex );
    1086                 :            : 
    1087                 :            :     OSL_ENSURE( mxView.is() && mpCanvas, "Disposed, but event received?!" );
    1088                 :            : 
    1089                 :            :     // notify view clobbering. Don't call EventMultiplexer directly,
    1090                 :            :     // this might not be the main thread!
    1091                 :            :     mrEventQueue.addEvent(
    1092                 :            :         makeEvent( boost::bind( &EventMultiplexer::notifyViewClobbered,
    1093                 :            :                                 boost::ref(mrEventMultiplexer), mxView ),
    1094                 :          0 :                    "EventMultiplexer::notifyViewClobbered") );
    1095                 :          0 : }
    1096                 :            : 
    1097                 :          0 : void SlideView::updateCanvas()
    1098                 :            : {
    1099                 :            :     OSL_ENSURE( mpCanvas,
    1100                 :            :                 "SlideView::updateCanvasTransform(): Disposed" );
    1101                 :            : 
    1102                 :          0 :     if( !mpCanvas || !mxView.is())
    1103                 :          0 :         return;
    1104                 :            : 
    1105                 :          0 :     mpCanvas->clear(); // this is unnecessary, strictly speaking. but
    1106                 :            :                        // it makes the SlideView behave exactly like a
    1107                 :            :                        // sprite-based SlideViewLayer, because those
    1108                 :            :                        // are created from scratch after a resize
    1109                 :          0 :     clearAll();
    1110                 :          0 :     mpCanvas->setTransformation( getTransformation() );
    1111                 :          0 :     mpCanvas->setClip(
    1112                 :            :         createClipPolygon( maClip,
    1113                 :            :                            mpCanvas,
    1114                 :          0 :                            maUserSize ));
    1115                 :            : 
    1116                 :            :     // forward update to viewlayers
    1117                 :          0 :     pruneLayers( true );
    1118                 :            : }
    1119                 :            : 
    1120                 :          0 : void SlideView::updateClip()
    1121                 :            : {
    1122                 :            :     OSL_ENSURE( mpCanvas,
    1123                 :            :                 "SlideView::updateClip(): Disposed" );
    1124                 :            : 
    1125                 :          0 :     if( !mpCanvas )
    1126                 :          0 :         return;
    1127                 :            : 
    1128                 :          0 :     mpCanvas->setClip(
    1129                 :            :         createClipPolygon( maClip,
    1130                 :            :                            mpCanvas,
    1131                 :          0 :                            maUserSize ));
    1132                 :            : 
    1133                 :          0 :     pruneLayers( false );
    1134                 :            : }
    1135                 :            : 
    1136                 :          0 : void SlideView::pruneLayers( bool bWithViewLayerUpdate ) const
    1137                 :            : {
    1138                 :          0 :     ViewLayerVector aValidLayers;
    1139                 :            : 
    1140                 :            :     const basegfx::B2DHomMatrix& rCurrTransform(
    1141                 :          0 :         getTransformation() );
    1142                 :            : 
    1143                 :            :     // check all layers for validity, and retain only the live ones
    1144                 :          0 :     ViewLayerVector::const_iterator       aCurr( maViewLayers.begin() );
    1145                 :          0 :     const ViewLayerVector::const_iterator aEnd( maViewLayers.end() );
    1146                 :          0 :     while( aCurr != aEnd )
    1147                 :            :     {
    1148                 :          0 :         boost::shared_ptr< SlideViewLayer > pCurrLayer( aCurr->lock() );
    1149                 :            : 
    1150                 :          0 :         if( pCurrLayer )
    1151                 :            :         {
    1152                 :          0 :             aValidLayers.push_back( pCurrLayer );
    1153                 :            : 
    1154                 :          0 :             if( bWithViewLayerUpdate )
    1155                 :            :                 pCurrLayer->updateView( rCurrTransform,
    1156                 :          0 :                                         maUserSize );
    1157                 :            :         }
    1158                 :            : 
    1159                 :          0 :         ++aCurr;
    1160                 :          0 :     }
    1161                 :            : 
    1162                 :            :     // replace layer list with pruned one
    1163                 :          0 :     maViewLayers.swap( aValidLayers );
    1164                 :          0 : }
    1165                 :            : 
    1166                 :            : } // anonymous namespace
    1167                 :            : 
    1168                 :          0 : UnoViewSharedPtr createSlideView( uno::Reference< presentation::XSlideShowView> const& xView,
    1169                 :            :                                   EventQueue&                                          rEventQueue,
    1170                 :            :                                   EventMultiplexer&                                    rEventMultiplexer )
    1171                 :            : {
    1172                 :            :     boost::shared_ptr<SlideView> const that(
    1173                 :            :         comphelper::make_shared_from_UNO(
    1174                 :            :             new SlideView(xView,
    1175                 :            :                           rEventQueue,
    1176                 :          0 :                           rEventMultiplexer)));
    1177                 :            : 
    1178                 :            :     // register listeners with XSlideShowView
    1179                 :          0 :     xView->addTransformationChangedListener( that.get() );
    1180                 :          0 :     xView->addPaintListener( that.get() );
    1181                 :            : 
    1182                 :            :     // set new transformation
    1183                 :          0 :     that->updateCanvas();
    1184                 :            : 
    1185                 :          0 :     return that;
    1186                 :            : }
    1187                 :            : 
    1188                 :            : } // namespace internal
    1189                 :          0 : } // namespace slideshow
    1190                 :            : 
    1191                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10