LCOV - code coverage report
Current view: top level - slideshow/source/engine/shapes - drawshape.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 1 382 0.3 %
Date: 2014-04-11 Functions: 2 52 3.8 %
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             : // must be first
      21             : #include <canvas/debug.hxx>
      22             : #include <tools/diagnose_ex.h>
      23             : #include <canvas/verbosetrace.hxx>
      24             : 
      25             : #include <osl/diagnose.hxx>
      26             : #include <com/sun/star/awt/Rectangle.hpp>
      27             : #include <com/sun/star/beans/XPropertySet.hpp>
      28             : #include <com/sun/star/awt/FontWeight.hpp>
      29             : #include <comphelper/anytostring.hxx>
      30             : #include <cppuhelper/exc_hlp.hxx>
      31             : 
      32             : #include <vcl/metaact.hxx>
      33             : #include <vcl/gdimtf.hxx>
      34             : #include <vcl/wrkwin.hxx>
      35             : 
      36             : #include <basegfx/numeric/ftools.hxx>
      37             : 
      38             : #include <rtl/math.hxx>
      39             : 
      40             : #include <com/sun/star/drawing/TextAnimationKind.hpp>
      41             : 
      42             : #include <vcl/svapp.hxx>
      43             : #include <vcl/window.hxx>
      44             : #include <tools/stream.hxx>
      45             : #include <com/sun/star/frame/XModel.hpp>
      46             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      47             : #include <com/sun/star/datatransfer/XTransferable.hpp>
      48             : 
      49             : #include <comphelper/scopeguard.hxx>
      50             : #include <canvas/canvastools.hxx>
      51             : 
      52             : #include <cmath>
      53             : #include <algorithm>
      54             : #include <functional>
      55             : #include <limits>
      56             : 
      57             : #include "drawshapesubsetting.hxx"
      58             : #include "drawshape.hxx"
      59             : #include "eventqueue.hxx"
      60             : #include "wakeupevent.hxx"
      61             : #include "subsettableshapemanager.hxx"
      62             : #include "intrinsicanimationactivity.hxx"
      63             : #include "slideshowexceptions.hxx"
      64             : #include "tools.hxx"
      65             : #include "gdimtftools.hxx"
      66             : #include "drawinglayeranimation.hxx"
      67             : 
      68             : #include <boost/bind.hpp>
      69             : #include <math.h>
      70             : 
      71             : using namespace ::com::sun::star;
      72             : 
      73             : 
      74             : namespace slideshow
      75             : {
      76             :     namespace internal
      77             :     {
      78             : 
      79             : 
      80             :         // Private methods
      81             : 
      82             : 
      83             : 
      84           0 :         GDIMetaFileSharedPtr DrawShape::forceScrollTextMetaFile()
      85             :         {
      86           0 :             if ((mnCurrMtfLoadFlags & MTF_LOAD_SCROLL_TEXT_MTF) != MTF_LOAD_SCROLL_TEXT_MTF)
      87             :             {
      88             :                 // reload with added flags:
      89           0 :                 mpCurrMtf.reset( new GDIMetaFile );
      90           0 :                 mnCurrMtfLoadFlags |= MTF_LOAD_SCROLL_TEXT_MTF;
      91             :                 getMetaFile(
      92             :                     uno::Reference<lang::XComponent>(mxShape, uno::UNO_QUERY),
      93           0 :                     mxPage, *mpCurrMtf, mnCurrMtfLoadFlags,
      94           0 :                     mxComponentContext );
      95             : 
      96             :                 // TODO(F1): Currently, the scroll metafile will
      97             :                 // never contain any verbose text comments. Thus,
      98             :                 // can only display the full mtf content, no
      99             :                 // subsets.
     100           0 :                 maSubsetting.reset( mpCurrMtf );
     101             : 
     102             :                 // adapt maBounds. the requested scroll text metafile
     103             :                 // will typically have dimension different from the
     104             :                 // actual shape
     105           0 :                 ::basegfx::B2DRectangle aScrollRect, aPaintRect;
     106           0 :                 ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect,
     107             :                                                               aPaintRect,
     108             :                                                               mpCurrMtf ),
     109             :                                   "DrawShape::forceScrollTextMetaFile(): Could "
     110             :                                   "not extract scroll anim rectangles from mtf" );
     111             : 
     112             :                 // take the larger one of the two rectangles (that
     113             :                 // should be the bound rect of the retrieved
     114             :                 // metafile)
     115           0 :                 if( aScrollRect.isInside( aPaintRect ) )
     116           0 :                     maBounds = aScrollRect;
     117             :                 else
     118           0 :                     maBounds = aPaintRect;
     119             :             }
     120           0 :             return mpCurrMtf;
     121             :         }
     122             : 
     123           0 :         void DrawShape::updateStateIds() const
     124             :         {
     125             :             // Update the states, we've just redrawn or created a new
     126             :             // attribute layer.
     127           0 :             if( mpAttributeLayer )
     128             :             {
     129           0 :                 mnAttributeTransformationState = mpAttributeLayer->getTransformationState();
     130           0 :                 mnAttributeClipState = mpAttributeLayer->getClipState();
     131           0 :                 mnAttributeAlphaState = mpAttributeLayer->getAlphaState();
     132           0 :                 mnAttributePositionState = mpAttributeLayer->getPositionState();
     133           0 :                 mnAttributeContentState = mpAttributeLayer->getContentState();
     134           0 :                 mnAttributeVisibilityState = mpAttributeLayer->getVisibilityState();
     135             :             }
     136           0 :         }
     137             : 
     138           0 :         ViewShape::RenderArgs DrawShape::getViewRenderArgs() const
     139             :         {
     140             :             return ViewShape::RenderArgs(
     141             :                 maBounds,
     142           0 :                 getUpdateArea(),
     143           0 :                 getBounds(),
     144             :                 getActualUnitShapeBounds(),
     145             :                 mpAttributeLayer,
     146           0 :                 maSubsetting.getActiveSubsets(),
     147           0 :                 mnPriority);
     148             :         }
     149             : 
     150           0 :         bool DrawShape::implRender( int nUpdateFlags ) const
     151             :         {
     152             :             SAL_INFO( "slideshow", "::presentation::internal::DrawShape::implRender()" );
     153             :             SAL_INFO( "slideshow", "::presentation::internal::DrawShape: 0x" << std::hex << this );
     154             : 
     155             :             // will perform the update now, clear update-enforcing
     156             :             // flags
     157           0 :             mbForceUpdate = false;
     158           0 :             mbAttributeLayerRevoked = false;
     159             : 
     160           0 :             ENSURE_OR_RETURN_FALSE( !maViewShapes.empty(),
     161             :                                "DrawShape::implRender(): render called on DrawShape without views" );
     162             : 
     163           0 :             if( maBounds.isEmpty() )
     164             :             {
     165             :                 // zero-sized shapes are effectively invisible,
     166             :                 // thus, we save us the rendering...
     167           0 :                 return true;
     168             :             }
     169             : 
     170             :             // redraw all view shapes, by calling their update() method
     171           0 :             if( ::std::count_if( maViewShapes.begin(),
     172             :                                  maViewShapes.end(),
     173             :                                  ::boost::bind<bool>(
     174             :                                      ::boost::mem_fn( &ViewShape::update ), // though _theoretically_,
     175             :                                                                              // bind should eat this even
     176             :                                                                              // with _1 being a shared_ptr,
     177             :                                                                              // it does _not_ for MSVC without
     178             :                                                                              // the extra mem_fn. WTF.
     179             :                                      _1,
     180             :                                      ::boost::cref( mpCurrMtf ),
     181             :                                      ::boost::cref(
     182             :                                          getViewRenderArgs() ),
     183             :                                      nUpdateFlags,
     184           0 :                                      isVisible() ) )
     185           0 :                 != static_cast<ViewShapeVector::difference_type>(maViewShapes.size()) )
     186             :             {
     187             :                 // at least one of the ViewShape::update() calls did return
     188             :                 // false - update failed on at least one ViewLayer
     189           0 :                 return false;
     190             :             }
     191             : 
     192             :             // successfully redrawn - update state IDs to detect next changes
     193           0 :             updateStateIds();
     194             : 
     195           0 :             return true;
     196             :         }
     197             : 
     198           0 :         int DrawShape::getUpdateFlags() const
     199             :         {
     200             :             // default: update nothing, unless ShapeAttributeStack
     201             :             // tells us below, or if the attribute layer was revoked
     202           0 :             int nUpdateFlags(ViewShape::NONE);
     203             : 
     204             :             // possibly the whole shape content changed
     205           0 :             if( mbAttributeLayerRevoked )
     206           0 :                 nUpdateFlags = ViewShape::CONTENT;
     207             : 
     208             : 
     209             :             // determine what has to be updated
     210             : 
     211             : 
     212             :             // do we have an attribute layer?
     213           0 :             if( mpAttributeLayer )
     214             :             {
     215             :                 // Prevent nUpdateFlags to be modified when the shape is not
     216             :                 // visible, except when it just was hidden.
     217           0 :                 if (mpAttributeLayer->getVisibility()
     218           0 :                     || mpAttributeLayer->getVisibilityState() != mnAttributeVisibilityState )
     219             :                 {
     220           0 :                     if (mpAttributeLayer->getVisibilityState() != mnAttributeVisibilityState )
     221             :                     {
     222             :                         // Change of the visibility state is mapped to
     223             :                         // content change because when the visibility
     224             :                         // changes then usually a sprite is shown or hidden
     225             :                         // and the background under has to be painted once.
     226           0 :                         nUpdateFlags |= ViewShape::CONTENT;
     227             :                     }
     228             : 
     229             :                     // TODO(P1): This can be done without conditional branching.
     230             :                     // See HAKMEM.
     231           0 :                     if( mpAttributeLayer->getPositionState() != mnAttributePositionState )
     232             :                     {
     233           0 :                         nUpdateFlags |= ViewShape::POSITION;
     234             :                     }
     235           0 :                     if( mpAttributeLayer->getAlphaState() != mnAttributeAlphaState )
     236             :                     {
     237           0 :                         nUpdateFlags |= ViewShape::ALPHA;
     238             :                     }
     239           0 :                     if( mpAttributeLayer->getClipState() != mnAttributeClipState )
     240             :                     {
     241           0 :                         nUpdateFlags |= ViewShape::CLIP;
     242             :                     }
     243           0 :                     if( mpAttributeLayer->getTransformationState() != mnAttributeTransformationState )
     244             :                     {
     245           0 :                         nUpdateFlags |= ViewShape::TRANSFORMATION;
     246             :                     }
     247           0 :                     if( mpAttributeLayer->getContentState() != mnAttributeContentState )
     248             :                     {
     249           0 :                         nUpdateFlags |= ViewShape::CONTENT;
     250             :                     }
     251             :                 }
     252             :             }
     253             : 
     254           0 :             return nUpdateFlags;
     255             :         }
     256             : 
     257           0 :         ::basegfx::B2DRectangle DrawShape::getActualUnitShapeBounds() const
     258             :         {
     259           0 :             ENSURE_OR_THROW( !maViewShapes.empty(),
     260             :                               "DrawShape::getActualUnitShapeBounds(): called on DrawShape without views" );
     261             : 
     262             :             const VectorOfDocTreeNodes& rSubsets(
     263           0 :                 maSubsetting.getActiveSubsets() );
     264             : 
     265           0 :             const ::basegfx::B2DRectangle aDefaultBounds( 0.0,0.0,1.0,1.0 );
     266             : 
     267             :             // perform the cheapest check first
     268           0 :             if( rSubsets.empty() )
     269             :             {
     270             :                 // if subset contains the whole shape, no need to call
     271             :                 // the somewhat expensive bound calculation, since as
     272             :                 // long as the subset is empty, this branch will be
     273             :                 // taken.
     274           0 :                 return aDefaultBounds;
     275             :             }
     276             :             else
     277             :             {
     278             :                 OSL_ENSURE( rSubsets.size() != 1 ||
     279             :                             !rSubsets.front().isEmpty(),
     280             :                             "DrawShape::getActualUnitShapeBounds() expects a "
     281             :                             "_non-empty_ subset vector for a subsetted shape!" );
     282             : 
     283             :                 // are the cached bounds still valid?
     284           0 :                 if( !maCurrentShapeUnitBounds )
     285             :                 {
     286             :                     // no, (re)generate them
     287             :                     // =====================
     288             : 
     289             :                     // setup cached values to defaults (might fail to
     290             :                     // retrieve true bounds below)
     291           0 :                     maCurrentShapeUnitBounds.reset( aDefaultBounds );
     292             : 
     293             :                     // TODO(P2): the subset of the master shape (that from
     294             :                     // which the subsets are subtracted) changes
     295             :                     // relatively often (every time a subset shape is
     296             :                     // added or removed). Maybe we should exclude it here,
     297             :                     // always assuming full bounds?
     298             : 
     299             :                     ::cppcanvas::CanvasSharedPtr pDestinationCanvas(
     300           0 :                         maViewShapes.front()->getViewLayer()->getCanvas() );
     301             : 
     302             :                     // TODO(Q2): Although this _is_ currently
     303             :                     // view-agnostic, it might not stay like
     304             :                     // that. Maybe this method should again be moved
     305             :                     // to the ViewShape
     306             :                     ::cppcanvas::RendererSharedPtr pRenderer(
     307           0 :                         maViewShapes.front()->getRenderer(
     308           0 :                             pDestinationCanvas, mpCurrMtf, mpAttributeLayer ) );
     309             : 
     310             :                     // If we cannot not prefetch, be defensive and assume
     311             :                     // full shape size
     312           0 :                     if( pRenderer )
     313             :                     {
     314             :                         // temporarily, switch total transformation to identity
     315             :                         // (need the bounds in the [0,1]x[0,1] unit coordinate
     316             :                         // system.
     317           0 :                         ::basegfx::B2DHomMatrix      aEmptyTransformation;
     318             : 
     319           0 :                         ::basegfx::B2DHomMatrix      aOldTransform( pDestinationCanvas->getTransformation() );
     320           0 :                         pDestinationCanvas->setTransformation( aEmptyTransformation );
     321           0 :                         pRenderer->setTransformation( aEmptyTransformation );
     322             : 
     323             :                         // restore old transformation when leaving the scope
     324             :                         const ::comphelper::ScopeGuard aGuard(
     325             :                             boost::bind( &::cppcanvas::Canvas::setTransformation,
     326           0 :                                          pDestinationCanvas, aOldTransform ) );
     327             : 
     328             : 
     329             :                         // retrieve bounds for subset of whole metafile
     330             : 
     331             : 
     332           0 :                         ::basegfx::B2DRange aTotalBounds;
     333             : 
     334             :                         // cannot use ::boost::bind, ::basegfx::B2DRange::expand()
     335             :                         // is overloaded.
     336           0 :                         VectorOfDocTreeNodes::const_iterator        aCurr( rSubsets.begin() );
     337           0 :                         const VectorOfDocTreeNodes::const_iterator  aEnd( rSubsets.end() );
     338           0 :                         while( aCurr != aEnd )
     339             :                         {
     340           0 :                             aTotalBounds.expand( pRenderer->getSubsetArea(
     341             :                                                      aCurr->getStartIndex(),
     342           0 :                                                      aCurr->getEndIndex() )  );
     343           0 :                             ++aCurr;
     344             :                         }
     345             : 
     346             :                         OSL_ENSURE( aTotalBounds.getMinX() >= -0.1 &&
     347             :                                     aTotalBounds.getMinY() >= -0.1 &&
     348             :                                     aTotalBounds.getMaxX() <= 1.1 &&
     349             :                                     aTotalBounds.getMaxY() <= 1.1,
     350             :                                     "DrawShape::getActualUnitShapeBounds(): bounds noticeably larger than original shape - clipping!" );
     351             : 
     352             :                         // really make sure no shape appears larger than its
     353             :                         // original bounds (there _are_ some pathologic cases,
     354             :                         // especially when imported from PPT, that have
     355             :                         // e.g. obscenely large polygon bounds)
     356             :                         aTotalBounds.intersect(
     357             :                             ::basegfx::B2DRange( 0.0, 0.0,
     358           0 :                                                  1.0, 1.0 ));
     359             : 
     360           0 :                         maCurrentShapeUnitBounds.reset( aTotalBounds );
     361           0 :                     }
     362             :                 }
     363             : 
     364           0 :                 return *maCurrentShapeUnitBounds;
     365             :             }
     366             :         }
     367             : 
     368           0 :         DrawShape::DrawShape( const uno::Reference< drawing::XShape >&      xShape,
     369             :                               const uno::Reference< drawing::XDrawPage >&   xContainingPage,
     370             :                               double                                        nPrio,
     371             :                               bool                                          bForeignSource,
     372             :                               const SlideShowContext&                       rContext ) :
     373             :             mxShape( xShape ),
     374             :             mxPage( xContainingPage ),
     375             :             maAnimationFrames(), // empty, we don't have no intrinsic animation
     376             :             mnCurrFrame(0),
     377             :             mpCurrMtf(),
     378             :             mnCurrMtfLoadFlags( bForeignSource
     379             :                                 ? MTF_LOAD_FOREIGN_SOURCE : MTF_LOAD_NONE ),
     380             :             maCurrentShapeUnitBounds(),
     381             :             mnPriority( nPrio ), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ),
     382             :             maBounds( getAPIShapeBounds( xShape ) ),
     383             :             mpAttributeLayer(),
     384             :             mpIntrinsicAnimationActivity(),
     385             :             mnAttributeTransformationState(0),
     386             :             mnAttributeClipState(0),
     387             :             mnAttributeAlphaState(0),
     388             :             mnAttributePositionState(0),
     389             :             mnAttributeContentState(0),
     390             :             mnAttributeVisibilityState(0),
     391             :             maViewShapes(),
     392             :             mxComponentContext( rContext.mxComponentContext ),
     393             :             maHyperlinkIndices(),
     394             :             maHyperlinkRegions(),
     395             :             maSubsetting(),
     396             :             mnIsAnimatedCount(0),
     397             :             mnAnimationLoopCount(0),
     398             :             meCycleMode(CYCLE_LOOP),
     399             :             mbIsVisible( true ),
     400             :             mbForceUpdate( false ),
     401             :             mbAttributeLayerRevoked( false ),
     402           0 :             mbDrawingLayerAnim( false )
     403             :         {
     404           0 :             ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" );
     405           0 :             ENSURE_OR_THROW( mxPage.is(), "DrawShape::DrawShape(): Invalid containing page" );
     406             : 
     407             :             // check for drawing layer animations:
     408           0 :             drawing::TextAnimationKind eKind = drawing::TextAnimationKind_NONE;
     409             :             uno::Reference<beans::XPropertySet> xPropSet( mxShape,
     410           0 :                                                           uno::UNO_QUERY );
     411           0 :             if( xPropSet.is() )
     412             :                 getPropertyValue( eKind, xPropSet,
     413           0 :                                   "TextAnimationKind" );
     414           0 :             mbDrawingLayerAnim = (eKind != drawing::TextAnimationKind_NONE);
     415             : 
     416             :             // must NOT be called from within initializer list, uses
     417             :             // state from mnCurrMtfLoadFlags!
     418           0 :             mpCurrMtf.reset( new GDIMetaFile );
     419             :             getMetaFile(
     420             :                 uno::Reference<lang::XComponent>(xShape, uno::UNO_QUERY),
     421           0 :                 xContainingPage, *mpCurrMtf, mnCurrMtfLoadFlags,
     422           0 :                 mxComponentContext );
     423           0 :             ENSURE_OR_THROW( mpCurrMtf,
     424             :                               "DrawShape::DrawShape(): Invalid metafile" );
     425           0 :             maSubsetting.reset( mpCurrMtf );
     426             : 
     427           0 :             prepareHyperlinkIndices();
     428           0 :         }
     429             : 
     430           0 :         DrawShape::DrawShape( const uno::Reference< drawing::XShape >&      xShape,
     431             :                               const uno::Reference< drawing::XDrawPage >&   xContainingPage,
     432             :                               double                                        nPrio,
     433             :                               const Graphic&                                rGraphic,
     434             :                               const SlideShowContext&                       rContext ) :
     435             :             mxShape( xShape ),
     436             :             mxPage( xContainingPage ),
     437             :             maAnimationFrames(),
     438             :             mnCurrFrame(0),
     439             :             mpCurrMtf(),
     440             :             mnCurrMtfLoadFlags( MTF_LOAD_NONE ),
     441             :             maCurrentShapeUnitBounds(),
     442             :             mnPriority( nPrio ), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ),
     443             :             maBounds( getAPIShapeBounds( xShape ) ),
     444             :             mpAttributeLayer(),
     445             :             mpIntrinsicAnimationActivity(),
     446             :             mnAttributeTransformationState(0),
     447             :             mnAttributeClipState(0),
     448             :             mnAttributeAlphaState(0),
     449             :             mnAttributePositionState(0),
     450             :             mnAttributeContentState(0),
     451             :             mnAttributeVisibilityState(0),
     452             :             maViewShapes(),
     453             :             mxComponentContext( rContext.mxComponentContext ),
     454             :             maHyperlinkIndices(),
     455             :             maHyperlinkRegions(),
     456             :             maSubsetting(),
     457             :             mnIsAnimatedCount(0),
     458             :             mnAnimationLoopCount(0),
     459             :             meCycleMode(CYCLE_LOOP),
     460             :             mbIsVisible( true ),
     461             :             mbForceUpdate( false ),
     462             :             mbAttributeLayerRevoked( false ),
     463           0 :             mbDrawingLayerAnim( false )
     464             :         {
     465           0 :             ENSURE_OR_THROW( rGraphic.IsAnimated(),
     466             :                               "DrawShape::DrawShape(): Graphic is no animation" );
     467             : 
     468             :             getAnimationFromGraphic( maAnimationFrames,
     469             :                                      mnAnimationLoopCount,
     470             :                                      meCycleMode,
     471           0 :                                      rGraphic );
     472             : 
     473           0 :             ENSURE_OR_THROW( !maAnimationFrames.empty() &&
     474             :                               maAnimationFrames.front().mpMtf,
     475             :                               "DrawShape::DrawShape(): " );
     476           0 :             mpCurrMtf = maAnimationFrames.front().mpMtf;
     477             : 
     478           0 :             ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" );
     479           0 :             ENSURE_OR_THROW( mxPage.is(), "DrawShape::DrawShape(): Invalid containing page" );
     480           0 :             ENSURE_OR_THROW( mpCurrMtf, "DrawShape::DrawShape(): Invalid metafile" );
     481           0 :         }
     482             : 
     483           0 :         DrawShape::DrawShape( const DrawShape&      rSrc,
     484             :                               const DocTreeNode&    rTreeNode,
     485             :                               double                nPrio ) :
     486             :             mxShape( rSrc.mxShape ),
     487             :             mxPage( rSrc.mxPage ),
     488             :             maAnimationFrames(), // don't copy animations for subsets,
     489             :                                  // only the current frame!
     490             :             mnCurrFrame(0),
     491             :             mpCurrMtf( rSrc.mpCurrMtf ),
     492             :             mnCurrMtfLoadFlags( rSrc.mnCurrMtfLoadFlags ),
     493             :             maCurrentShapeUnitBounds(),
     494             :             mnPriority( nPrio ),
     495             :             maBounds( rSrc.maBounds ),
     496             :             mpAttributeLayer(),
     497             :             mpIntrinsicAnimationActivity(),
     498             :             mnAttributeTransformationState(0),
     499             :             mnAttributeClipState(0),
     500             :             mnAttributeAlphaState(0),
     501             :             mnAttributePositionState(0),
     502             :             mnAttributeContentState(0),
     503             :             mnAttributeVisibilityState(0),
     504             :             maViewShapes(),
     505             :             mxComponentContext( rSrc.mxComponentContext ),
     506             :             maHyperlinkIndices(),
     507             :             maHyperlinkRegions(),
     508             :             maSubsetting( rTreeNode, mpCurrMtf ),
     509             :             mnIsAnimatedCount(0),
     510             :             mnAnimationLoopCount(0),
     511             :             meCycleMode(CYCLE_LOOP),
     512             :             mbIsVisible( rSrc.mbIsVisible ),
     513             :             mbForceUpdate( false ),
     514             :             mbAttributeLayerRevoked( false ),
     515           0 :             mbDrawingLayerAnim( false )
     516             :         {
     517           0 :             ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" );
     518           0 :             ENSURE_OR_THROW( mpCurrMtf, "DrawShape::DrawShape(): Invalid metafile" );
     519             : 
     520             :             // xxx todo: currently not implemented for subsetted shapes;
     521             :             //           would mean modifying set of hyperlink regions when
     522             :             //           subsetting text portions. N.B.: there's already an
     523             :             //           issue for this #i72828#
     524           0 :         }
     525             : 
     526             : 
     527             : 
     528             :         // Public methods
     529             : 
     530             : 
     531             : 
     532           0 :         DrawShapeSharedPtr DrawShape::create(
     533             :             const uno::Reference< drawing::XShape >&    xShape,
     534             :             const uno::Reference< drawing::XDrawPage >& xContainingPage,
     535             :             double                                      nPrio,
     536             :             bool                                        bForeignSource,
     537             :             const SlideShowContext&                     rContext )
     538             :         {
     539             :             DrawShapeSharedPtr pShape( new DrawShape(xShape,
     540             :                                                      xContainingPage,
     541             :                                                      nPrio,
     542             :                                                      bForeignSource,
     543           0 :                                                      rContext) );
     544             : 
     545           0 :             if( pShape->hasIntrinsicAnimation() )
     546             :             {
     547             :                 OSL_ASSERT( pShape->maAnimationFrames.empty() );
     548           0 :                 if( pShape->getNumberOfTreeNodes(
     549           0 :                         DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH) > 0 )
     550             :                 {
     551           0 :                     pShape->mpIntrinsicAnimationActivity =
     552             :                         createDrawingLayerAnimActivity(
     553             :                             rContext,
     554           0 :                             pShape);
     555             :                 }
     556             :             }
     557             : 
     558           0 :             if( pShape->hasHyperlinks() )
     559           0 :                 rContext.mpSubsettableShapeManager->addHyperlinkArea( pShape );
     560             : 
     561           0 :             return pShape;
     562             :         }
     563             : 
     564           0 :         DrawShapeSharedPtr DrawShape::create(
     565             :             const uno::Reference< drawing::XShape >&    xShape,
     566             :             const uno::Reference< drawing::XDrawPage >& xContainingPage,
     567             :             double                                      nPrio,
     568             :             const Graphic&                              rGraphic,
     569             :             const SlideShowContext&                     rContext )
     570             :         {
     571             :             DrawShapeSharedPtr pShape( new DrawShape(xShape,
     572             :                                                      xContainingPage,
     573             :                                                      nPrio,
     574             :                                                      rGraphic,
     575           0 :                                                      rContext) );
     576             : 
     577           0 :             if( pShape->hasIntrinsicAnimation() )
     578             :             {
     579             :                 OSL_ASSERT( !pShape->maAnimationFrames.empty() );
     580             : 
     581           0 :                 std::vector<double> aTimeout;
     582             :                 std::transform(
     583           0 :                     pShape->maAnimationFrames.begin(),
     584           0 :                     pShape->maAnimationFrames.end(),
     585             :                     std::back_insert_iterator< std::vector<double> >( aTimeout ),
     586           0 :                     boost::mem_fn(&MtfAnimationFrame::getDuration) );
     587             : 
     588             :                 WakeupEventSharedPtr pWakeupEvent(
     589           0 :                     new WakeupEvent( rContext.mrEventQueue.getTimer(),
     590           0 :                                      rContext.mrActivitiesQueue ) );
     591             : 
     592             :                 ActivitySharedPtr pActivity =
     593             :                     createIntrinsicAnimationActivity(
     594             :                         rContext,
     595             :                         pShape,
     596             :                         pWakeupEvent,
     597             :                         aTimeout,
     598           0 :                         pShape->mnAnimationLoopCount,
     599           0 :                         pShape->meCycleMode);
     600             : 
     601           0 :                 pWakeupEvent->setActivity( pActivity );
     602           0 :                 pShape->mpIntrinsicAnimationActivity = pActivity;
     603             :             }
     604             : 
     605             :             OSL_ENSURE( !pShape->hasHyperlinks(),
     606             :                         "DrawShape::create(): graphic-only shapes must not have hyperlinks!" );
     607             : 
     608           0 :             return pShape;
     609             :         }
     610             : 
     611           0 :         DrawShape::~DrawShape()
     612             :         {
     613             :             try
     614             :             {
     615             :                 // dispose intrinsic animation activity, else, it will
     616             :                 // linger forever
     617           0 :                 ActivitySharedPtr pActivity( mpIntrinsicAnimationActivity.lock() );
     618           0 :                 if( pActivity )
     619           0 :                     pActivity->dispose();
     620             :             }
     621           0 :             catch (uno::Exception &)
     622             :             {
     623             :                 SAL_WARN( "slideshow", "" << comphelper::anyToString(cppu::getCaughtException() ) );
     624             :             }
     625           0 :         }
     626             : 
     627           0 :         uno::Reference< drawing::XShape > DrawShape::getXShape() const
     628             :         {
     629           0 :             return mxShape;
     630             :         }
     631             : 
     632           0 :         void DrawShape::addViewLayer( const ViewLayerSharedPtr& rNewLayer,
     633             :                                       bool                      bRedrawLayer )
     634             :         {
     635           0 :             ViewShapeVector::iterator aEnd( maViewShapes.end() );
     636             : 
     637             :             // already added?
     638           0 :             if( ::std::find_if( maViewShapes.begin(),
     639             :                                 aEnd,
     640             :                                 ::boost::bind<bool>(
     641             :                                     ::std::equal_to< ViewLayerSharedPtr >(),
     642             :                                     ::boost::bind( &ViewShape::getViewLayer,
     643             :                                                    _1 ),
     644           0 :                                     ::boost::cref( rNewLayer ) ) ) != aEnd )
     645             :             {
     646             :                 // yes, nothing to do
     647           0 :                 return;
     648             :             }
     649             : 
     650           0 :             ViewShapeSharedPtr pNewShape( new ViewShape( rNewLayer ) );
     651             : 
     652           0 :             maViewShapes.push_back( pNewShape );
     653             : 
     654             :             // pass on animation state
     655           0 :             if( mnIsAnimatedCount )
     656             :             {
     657           0 :                 for( int i=0; i<mnIsAnimatedCount; ++i )
     658           0 :                     pNewShape->enterAnimationMode();
     659             :             }
     660             : 
     661             :             // render the Shape on the newly added ViewLayer
     662           0 :             if( bRedrawLayer )
     663             :             {
     664             :                 pNewShape->update( mpCurrMtf,
     665             :                                    getViewRenderArgs(),
     666             :                                    ViewShape::FORCE,
     667           0 :                                    isVisible() );
     668           0 :             }
     669             :         }
     670             : 
     671           0 :         bool DrawShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
     672             :         {
     673           0 :             const ViewShapeVector::iterator aEnd( maViewShapes.end() );
     674             : 
     675             :             OSL_ENSURE( ::std::count_if(maViewShapes.begin(),
     676             :                                         aEnd,
     677             :                                         ::boost::bind<bool>(
     678             :                                             ::std::equal_to< ViewLayerSharedPtr >(),
     679             :                                             ::boost::bind( &ViewShape::getViewLayer,
     680             :                                                            _1 ),
     681             :                                             ::boost::cref( rLayer ) ) ) < 2,
     682             :                         "DrawShape::removeViewLayer(): Duplicate ViewLayer entries!" );
     683             : 
     684           0 :             ViewShapeVector::iterator aIter;
     685             : 
     686           0 :             if( (aIter=::std::remove_if( maViewShapes.begin(),
     687             :                                          aEnd,
     688             :                                          ::boost::bind<bool>(
     689             :                                              ::std::equal_to< ViewLayerSharedPtr >(),
     690             :                                              ::boost::bind( &ViewShape::getViewLayer,
     691             :                                                             _1 ),
     692           0 :                                              ::boost::cref( rLayer ) ) )) == aEnd )
     693             :             {
     694             :                 // view layer seemingly was not added, failed
     695           0 :                 return false;
     696             :             }
     697             : 
     698             :             // actually erase from container
     699           0 :             maViewShapes.erase( aIter, aEnd );
     700             : 
     701           0 :             return true;
     702             :         }
     703             : 
     704           0 :         bool DrawShape::clearAllViewLayers()
     705             :         {
     706           0 :             maViewShapes.clear();
     707           0 :             return true;
     708             :         }
     709             : 
     710           0 :         bool DrawShape::update() const
     711             :         {
     712           0 :             if( mbForceUpdate )
     713             :             {
     714           0 :                 return render();
     715             :             }
     716             :             else
     717             :             {
     718           0 :                 return implRender( getUpdateFlags() );
     719             :             }
     720             :         }
     721             : 
     722           0 :         bool DrawShape::render() const
     723             :         {
     724             :             // force redraw. Have to also pass on the update flags,
     725             :             // because e.g. content update (regeneration of the
     726             :             // metafile renderer) is normally not performed. A simple
     727             :             // ViewShape::FORCE would only paint the metafile in its
     728             :             // old state.
     729           0 :             return implRender( ViewShape::FORCE | getUpdateFlags() );
     730             :         }
     731             : 
     732           0 :         bool DrawShape::isContentChanged() const
     733             :         {
     734             :             return mbForceUpdate ?
     735             :                 true :
     736           0 :                 getUpdateFlags() != ViewShape::NONE;
     737             :         }
     738             : 
     739             : 
     740           0 :         ::basegfx::B2DRectangle DrawShape::getBounds() const
     741             :         {
     742             :             // little optimization: for non-modified shapes, we don't
     743             :             // create an ShapeAttributeStack, and therefore also don't
     744             :             // have to check it.
     745             :             return getShapePosSize( maBounds,
     746           0 :                                     mpAttributeLayer );
     747             :         }
     748             : 
     749           0 :         ::basegfx::B2DRectangle DrawShape::getDomBounds() const
     750             :         {
     751           0 :             return maBounds;
     752             :         }
     753             : 
     754             :         namespace
     755             :         {
     756             :             /** Functor expanding AA border for each passed ViewShape
     757             : 
     758             :                 Could not use ::boost::bind here, since
     759             :                 B2DRange::expand is overloaded (which yields one or
     760             :                 the other template type deduction ambiguous)
     761             :              */
     762             :             class Expander
     763             :             {
     764             :             public:
     765           0 :                 Expander( ::basegfx::B2DSize& rBounds ) :
     766           0 :                     mrBounds( rBounds )
     767             :                 {
     768           0 :                 }
     769             : 
     770           0 :                 void operator()( const ViewShapeSharedPtr& rShape ) const
     771             :                 {
     772           0 :                     const ::basegfx::B2DSize& rShapeBorder( rShape->getAntialiasingBorder() );
     773             : 
     774             :                     mrBounds.setX(
     775             :                         ::std::max(
     776           0 :                             rShapeBorder.getX(),
     777           0 :                             mrBounds.getX() ) );
     778             :                     mrBounds.setY(
     779             :                         ::std::max(
     780           0 :                             rShapeBorder.getY(),
     781           0 :                             mrBounds.getY() ) );
     782           0 :                 }
     783             : 
     784             :             private:
     785             :                 ::basegfx::B2DSize& mrBounds;
     786             :             };
     787             :         }
     788             : 
     789           0 :         ::basegfx::B2DRectangle DrawShape::getUpdateArea() const
     790             :         {
     791           0 :             ::basegfx::B2DRectangle aBounds;
     792             : 
     793             :             // an already empty shape bound need no further
     794             :             // treatment. In fact, any changes applied below would
     795             :             // actually remove the special empty state, thus, don't
     796             :             // change!
     797           0 :             if( !maBounds.isEmpty() )
     798             :             {
     799           0 :                 basegfx::B2DRectangle aUnitBounds(0.0,0.0,1.0,1.0);
     800             : 
     801           0 :                 if( !maViewShapes.empty() )
     802           0 :                     aUnitBounds = getActualUnitShapeBounds();
     803             : 
     804           0 :                 if( !aUnitBounds.isEmpty() )
     805             :                 {
     806           0 :                     if( mpAttributeLayer )
     807             :                     {
     808             :                         // calc actual shape area (in user coordinate
     809             :                         // space) from the transformation as given by the
     810             :                         // shape attribute layer
     811             :                         aBounds = getShapeUpdateArea( aUnitBounds,
     812           0 :                                                       getShapeTransformation( getBounds(),
     813             :                                                                               mpAttributeLayer ),
     814           0 :                                                       mpAttributeLayer );
     815             :                     }
     816             :                     else
     817             :                     {
     818             :                         // no attribute layer, thus, the true shape bounds
     819             :                         // can be directly derived from the XShape bound
     820             :                         // attribute
     821             :                         aBounds = getShapeUpdateArea( aUnitBounds,
     822           0 :                                                       maBounds );
     823             :                     }
     824             : 
     825           0 :                     if( !maViewShapes.empty() )
     826             :                     {
     827             :                         // determine border needed for antialiasing the shape
     828           0 :                         ::basegfx::B2DSize aAABorder(0.0,0.0);
     829             : 
     830             :                         // for every view, get AA border and 'expand' aAABorder
     831             :                         // appropriately.
     832             :                         ::std::for_each( maViewShapes.begin(),
     833             :                                          maViewShapes.end(),
     834           0 :                                          Expander( aAABorder ) );
     835             : 
     836             :                         // add calculated AA border to aBounds
     837           0 :                         aBounds = ::basegfx::B2DRectangle( aBounds.getMinX() - aAABorder.getX(),
     838           0 :                                                            aBounds.getMinY() - aAABorder.getY(),
     839           0 :                                                            aBounds.getMaxX() + aAABorder.getX(),
     840           0 :                                                            aBounds.getMaxY() + aAABorder.getY() );
     841             :                     }
     842             :                 }
     843             :             }
     844             : 
     845           0 :             return aBounds;
     846             :         }
     847             : 
     848           0 :         bool DrawShape::isVisible() const
     849             :         {
     850           0 :             bool bIsVisible( mbIsVisible );
     851             : 
     852           0 :             if( mpAttributeLayer )
     853             :             {
     854             :                 // check whether visibility and alpha are not default
     855             :                 // (mpAttributeLayer->isVisibilityValid() returns true
     856             :                 // then): bVisible becomes true, if shape visibility
     857             :                 // is on and alpha is not 0.0 (fully transparent)
     858           0 :                 if( mpAttributeLayer->isVisibilityValid() )
     859           0 :                     bIsVisible = mpAttributeLayer->getVisibility();
     860             : 
     861             :                 // only touch bIsVisible, if the shape is still
     862             :                 // visible - if getVisibility already made us
     863             :                 // invisible, no alpha value will make us appear
     864             :                 // again.
     865           0 :                 if( bIsVisible && mpAttributeLayer->isAlphaValid() )
     866           0 :                     bIsVisible = !::basegfx::fTools::equalZero( mpAttributeLayer->getAlpha() );
     867             :             }
     868             : 
     869           0 :             return bIsVisible;
     870             :         }
     871             : 
     872           0 :         double DrawShape::getPriority() const
     873             :         {
     874           0 :             return mnPriority;
     875             :         }
     876             : 
     877           0 :         bool DrawShape::isBackgroundDetached() const
     878             :         {
     879           0 :             return mnIsAnimatedCount > 0;
     880             :         }
     881             : 
     882           0 :         bool DrawShape::hasIntrinsicAnimation() const
     883             :         {
     884           0 :             return (!maAnimationFrames.empty() || mbDrawingLayerAnim);
     885             :         }
     886             : 
     887           0 :         bool DrawShape::setIntrinsicAnimationFrame( ::std::size_t nCurrFrame )
     888             :         {
     889           0 :             ENSURE_OR_RETURN_FALSE( nCurrFrame < maAnimationFrames.size(),
     890             :                                "DrawShape::setIntrinsicAnimationFrame(): frame index out of bounds" );
     891             : 
     892           0 :             if( mnCurrFrame != nCurrFrame )
     893             :             {
     894           0 :                 mnCurrFrame   = nCurrFrame;
     895           0 :                 mpCurrMtf     = maAnimationFrames[ mnCurrFrame ].mpMtf;
     896           0 :                 mbForceUpdate = true;
     897             :             }
     898             : 
     899           0 :             return true;
     900             :         }
     901             : 
     902             :         // hyperlink support
     903           0 :         void DrawShape::prepareHyperlinkIndices() const
     904             :         {
     905           0 :             if ( !maHyperlinkIndices.empty())
     906             :             {
     907           0 :                 maHyperlinkIndices.clear();
     908           0 :                 maHyperlinkRegions.clear();
     909             :             }
     910             : 
     911           0 :             sal_Int32 nIndex = 0;
     912           0 :             for ( MetaAction * pCurrAct = mpCurrMtf->FirstAction();
     913           0 :                   pCurrAct != 0; pCurrAct = mpCurrMtf->NextAction() )
     914             :             {
     915           0 :                 if (pCurrAct->GetType() == META_COMMENT_ACTION) {
     916             :                     MetaCommentAction * pAct =
     917           0 :                         static_cast<MetaCommentAction *>(pCurrAct);
     918             :                     // skip comment if not a special XTEXT comment
     919           0 :                     if (pAct->GetComment().equalsIgnoreAsciiCase("FIELD_SEQ_BEGIN") &&
     920             :                         // e.g. date field doesn't have data!
     921             :                         // currently assuming that only url field, this is
     922             :                         // somehow fragile! xxx todo if possible
     923           0 :                         pAct->GetData() != 0 &&
     924           0 :                         pAct->GetDataSize() > 0)
     925             :                     {
     926           0 :                         if (!maHyperlinkIndices.empty() &&
     927           0 :                             maHyperlinkIndices.back().second == -1) {
     928             :                             SAL_WARN( "slideshow", "### pending FIELD_SEQ_END!" );
     929           0 :                             maHyperlinkIndices.pop_back();
     930           0 :                             maHyperlinkRegions.pop_back();
     931             :                         }
     932             :                         maHyperlinkIndices.push_back(
     933           0 :                             HyperlinkIndexPair( nIndex + 1,
     934           0 :                                                 -1 /* to be filled below */ ) );
     935             :                         maHyperlinkRegions.push_back(
     936             :                             HyperlinkRegion(
     937             :                                 basegfx::B2DRectangle(),
     938             :                                 OUString(
     939             :                                     reinterpret_cast<sal_Unicode const*>(
     940           0 :                                         pAct->GetData()),
     941           0 :                                     pAct->GetDataSize() / sizeof(sal_Unicode) )
     942           0 :                                 ) );
     943             :                     }
     944           0 :                     else if (pAct->GetComment().equalsIgnoreAsciiCase("FIELD_SEQ_END") &&
     945             :                              // pending end is expected:
     946           0 :                              !maHyperlinkIndices.empty() &&
     947           0 :                              maHyperlinkIndices.back().second == -1)
     948             :                     {
     949           0 :                         maHyperlinkIndices.back().second = nIndex;
     950             :                     }
     951           0 :                     ++nIndex;
     952             :                 }
     953             :                 else
     954           0 :                     nIndex += getNextActionOffset(pCurrAct);
     955             :             }
     956           0 :             if (!maHyperlinkIndices.empty() &&
     957           0 :                 maHyperlinkIndices.back().second == -1) {
     958             :                 SAL_WARN( "slideshow", "### pending FIELD_SEQ_END!" );
     959           0 :                 maHyperlinkIndices.pop_back();
     960           0 :                 maHyperlinkRegions.pop_back();
     961             :             }
     962             :             OSL_ASSERT( maHyperlinkIndices.size() == maHyperlinkRegions.size());
     963           0 :         }
     964             : 
     965           0 :         bool DrawShape::hasHyperlinks() const
     966             :         {
     967           0 :             return ! maHyperlinkRegions.empty();
     968             :         }
     969             : 
     970           0 :         HyperlinkArea::HyperlinkRegions DrawShape::getHyperlinkRegions() const
     971             :         {
     972             :             OSL_ASSERT( !maViewShapes.empty() );
     973             : 
     974           0 :             if( !isVisible() )
     975           0 :                 return HyperlinkArea::HyperlinkRegions();
     976             : 
     977             :             // late init, determine regions:
     978           0 :             if( !maHyperlinkRegions.empty() &&
     979           0 :                 !maViewShapes.empty() &&
     980             :                 // region already inited?
     981           0 :                 maHyperlinkRegions.front().first.getWidth() == 0 &&
     982           0 :                 maHyperlinkRegions.front().first.getHeight() == 0 &&
     983           0 :                 maHyperlinkRegions.size() == maHyperlinkIndices.size() )
     984             :             {
     985             :                 // TODO(Q2): Although this _is_ currently
     986             :                 // view-agnostic, it might not stay like that.
     987           0 :                 ViewShapeSharedPtr const& pViewShape = maViewShapes.front();
     988             :                 cppcanvas::CanvasSharedPtr const pCanvas(
     989           0 :                     pViewShape->getViewLayer()->getCanvas() );
     990             : 
     991             :                 // reuse Renderer of first view shape:
     992             :                 cppcanvas::RendererSharedPtr const pRenderer(
     993             :                     pViewShape->getRenderer(
     994           0 :                         pCanvas, mpCurrMtf, mpAttributeLayer ) );
     995             : 
     996             :                 OSL_ASSERT( pRenderer );
     997             : 
     998           0 :                 if (pRenderer)
     999             :                 {
    1000             :                     basegfx::B2DHomMatrix const aOldTransform(
    1001           0 :                         pCanvas->getTransformation() );
    1002           0 :                     basegfx::B2DHomMatrix aTransform;
    1003           0 :                     pCanvas->setTransformation( aTransform /* empty */ );
    1004             : 
    1005             :                     comphelper::ScopeGuard const resetOldTransformation(
    1006             :                         boost::bind( &cppcanvas::Canvas::setTransformation,
    1007             :                                      pCanvas.get(),
    1008           0 :                                      boost::cref(aOldTransform) ));
    1009             : 
    1010             :                     aTransform.scale( maBounds.getWidth(),
    1011           0 :                                       maBounds.getHeight() );
    1012           0 :                     pRenderer->setTransformation( aTransform );
    1013           0 :                     pRenderer->setClip();
    1014             : 
    1015           0 :                     for( std::size_t pos = maHyperlinkRegions.size(); pos--; )
    1016             :                     {
    1017             :                         // get region:
    1018           0 :                         HyperlinkIndexPair const& rIndices = maHyperlinkIndices[pos];
    1019             :                         basegfx::B2DRectangle const region(
    1020           0 :                             pRenderer->getSubsetArea( rIndices.first,
    1021           0 :                                                       rIndices.second ));
    1022           0 :                         maHyperlinkRegions[pos].first = region;
    1023           0 :                     }
    1024           0 :                 }
    1025             :             }
    1026             : 
    1027             :             // shift shape-relative hyperlink regions to
    1028             :             // slide-absolute position
    1029             : 
    1030           0 :             HyperlinkRegions aTranslatedRegions;
    1031           0 :             const basegfx::B2DPoint& rOffset(getBounds().getMinimum());
    1032           0 :             HyperlinkRegions::const_iterator       aIter( maHyperlinkRegions.begin() );
    1033           0 :             HyperlinkRegions::const_iterator const aEnd ( maHyperlinkRegions.end() );
    1034           0 :             while( aIter != aEnd )
    1035             :             {
    1036           0 :                 basegfx::B2DRange const& relRegion( aIter->first );
    1037             :                 aTranslatedRegions.push_back(
    1038             :                     std::make_pair(
    1039             :                         basegfx::B2DRange(
    1040           0 :                             relRegion.getMinimum() + rOffset,
    1041           0 :                             relRegion.getMaximum() + rOffset),
    1042           0 :                         aIter->second) );
    1043           0 :                 ++aIter;
    1044             :             }
    1045             : 
    1046           0 :             return aTranslatedRegions;
    1047             :         }
    1048             : 
    1049           0 :         double DrawShape::getHyperlinkPriority() const
    1050             :         {
    1051           0 :             return getPriority();
    1052             :         }
    1053             : 
    1054             : 
    1055             :         // AnimatableShape methods
    1056             : 
    1057             : 
    1058           0 :         void DrawShape::enterAnimationMode()
    1059             :         {
    1060             :             OSL_ENSURE( !maViewShapes.empty(),
    1061             :                         "DrawShape::enterAnimationMode(): called on DrawShape without views" );
    1062             : 
    1063           0 :             if( mnIsAnimatedCount == 0 )
    1064             :             {
    1065             :                 // notify all ViewShapes, by calling their enterAnimationMode method.
    1066             :                 // We're now entering animation mode
    1067             :                 ::std::for_each( maViewShapes.begin(),
    1068             :                                  maViewShapes.end(),
    1069           0 :                                  ::boost::mem_fn( &ViewShape::enterAnimationMode ) );
    1070             :             }
    1071             : 
    1072           0 :             ++mnIsAnimatedCount;
    1073           0 :         }
    1074             : 
    1075           0 :         void DrawShape::leaveAnimationMode()
    1076             :         {
    1077             :             OSL_ENSURE( !maViewShapes.empty(),
    1078             :                         "DrawShape::leaveAnimationMode(): called on DrawShape without views" );
    1079             : 
    1080           0 :             --mnIsAnimatedCount;
    1081             : 
    1082           0 :             if( mnIsAnimatedCount == 0 )
    1083             :             {
    1084             :                 // notify all ViewShapes, by calling their leaveAnimationMode method.
    1085             :                 // we're now leaving animation mode
    1086             :                 ::std::for_each( maViewShapes.begin(),
    1087             :                                  maViewShapes.end(),
    1088           0 :                                  ::boost::mem_fn( &ViewShape::leaveAnimationMode ) );
    1089             :             }
    1090           0 :         }
    1091             : 
    1092             : 
    1093             :         // AttributableShape methods
    1094             : 
    1095             : 
    1096           0 :         ShapeAttributeLayerSharedPtr DrawShape::createAttributeLayer()
    1097             :         {
    1098             :             // create new layer, with last as its new child
    1099           0 :             mpAttributeLayer.reset( new ShapeAttributeLayer( mpAttributeLayer ) );
    1100             : 
    1101             :             // Update the local state ids to reflect those of the new layer.
    1102           0 :             updateStateIds();
    1103             : 
    1104           0 :             return mpAttributeLayer;
    1105             :         }
    1106             : 
    1107           0 :         bool DrawShape::revokeAttributeLayer( const ShapeAttributeLayerSharedPtr& rLayer )
    1108             :         {
    1109           0 :             if( !mpAttributeLayer )
    1110           0 :                 return false; // no layers
    1111             : 
    1112           0 :             if( mpAttributeLayer == rLayer )
    1113             :             {
    1114             :                 // it's the toplevel layer
    1115           0 :                 mpAttributeLayer = mpAttributeLayer->getChildLayer();
    1116             : 
    1117             :                 // force content redraw, all state variables have
    1118             :                 // possibly changed
    1119           0 :                 mbAttributeLayerRevoked = true;
    1120             : 
    1121           0 :                 return true;
    1122             :             }
    1123             :             else
    1124             :             {
    1125             :                 // pass on to the layer, to try its children
    1126           0 :                 return mpAttributeLayer->revokeChildLayer( rLayer );
    1127             :             }
    1128             :         }
    1129             : 
    1130           0 :         ShapeAttributeLayerSharedPtr DrawShape::getTopmostAttributeLayer() const
    1131             :         {
    1132           0 :             return mpAttributeLayer;
    1133             :         }
    1134             : 
    1135           0 :         void DrawShape::setVisibility( bool bVisible )
    1136             :         {
    1137           0 :             if( mbIsVisible != bVisible )
    1138             :             {
    1139           0 :                 mbIsVisible = bVisible;
    1140           0 :                 mbForceUpdate = true;
    1141             :             }
    1142           0 :         }
    1143             : 
    1144           0 :         const DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier() const
    1145             :         {
    1146           0 :             return *this;
    1147             :         }
    1148             : 
    1149           0 :         DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier()
    1150             :         {
    1151           0 :             return *this;
    1152             :         }
    1153             : 
    1154           0 :         DocTreeNode DrawShape::getSubsetNode() const
    1155             :         {
    1156             :             // forward to delegate
    1157           0 :             return maSubsetting.getSubsetNode();
    1158             :         }
    1159             : 
    1160           0 :         AttributableShapeSharedPtr DrawShape::getSubset( const DocTreeNode& rTreeNode ) const
    1161             :         {
    1162             :             // forward to delegate
    1163           0 :             return maSubsetting.getSubsetShape( rTreeNode );
    1164             :         }
    1165             : 
    1166           0 :         bool DrawShape::createSubset( AttributableShapeSharedPtr&   o_rSubset,
    1167             :                                       const DocTreeNode&            rTreeNode )
    1168             :         {
    1169             :             // subset shape already created for this DocTreeNode?
    1170           0 :             AttributableShapeSharedPtr pSubset( maSubsetting.getSubsetShape( rTreeNode ) );
    1171             : 
    1172             :             // when true, this method has created a new subset
    1173             :             // DrawShape
    1174           0 :             bool bNewlyCreated( false );
    1175             : 
    1176           0 :             if( pSubset )
    1177             :             {
    1178           0 :                 o_rSubset = pSubset;
    1179             : 
    1180             :                 // reusing existing subset
    1181             :             }
    1182             :             else
    1183             :             {
    1184             :                 // not yet created, init entry
    1185             :                 o_rSubset.reset( new DrawShape( *this,
    1186             :                                                 rTreeNode,
    1187             :                                                 // TODO(Q3): That's a
    1188             :                                                 // hack. We assume
    1189             :                                                 // that start and end
    1190             :                                                 // index will always
    1191             :                                                 // be less than 65535
    1192           0 :                                                 mnPriority +
    1193           0 :                                                 rTreeNode.getStartIndex()/double(SAL_MAX_INT16) ));
    1194             : 
    1195           0 :                 bNewlyCreated = true; // subset newly created
    1196             :             }
    1197             : 
    1198             :             // always register shape at DrawShapeSubsetting, to keep
    1199             :             // refcount up-to-date
    1200           0 :             maSubsetting.addSubsetShape( o_rSubset );
    1201             : 
    1202             :             // flush bounds cache
    1203           0 :             maCurrentShapeUnitBounds.reset();
    1204             : 
    1205           0 :             return bNewlyCreated;
    1206             :         }
    1207             : 
    1208           0 :         bool DrawShape::revokeSubset( const AttributableShapeSharedPtr& rShape )
    1209             :         {
    1210             :             // flush bounds cache
    1211           0 :             maCurrentShapeUnitBounds.reset();
    1212             : 
    1213             :             // forward to delegate
    1214           0 :             if( maSubsetting.revokeSubsetShape( rShape ) )
    1215             :             {
    1216             :                 // force redraw, our content has possibly changed (as
    1217             :                 // one of the subsets now display within our shape
    1218             :                 // again).
    1219           0 :                 mbForceUpdate = true;
    1220             : 
    1221             :                 // #i47428# TEMP FIX: synchronize visibility of subset
    1222             :                 // with parent.
    1223             : 
    1224             :                 // TODO(F3): Remove here, and implement
    1225             :                 // TEXT_ONLY/BACKGROUND_ONLY with the proverbial
    1226             :                 // additional level of indirection: create a
    1227             :                 // persistent subset, containing all text/only the
    1228             :                 // background respectively. From _that_ object,
    1229             :                 // generate the temporary character subset shapes.
    1230             :                 const ShapeAttributeLayerSharedPtr& rAttrLayer(
    1231           0 :                     rShape->getTopmostAttributeLayer() );
    1232           0 :                 if( rAttrLayer &&
    1233           0 :                     rAttrLayer->isVisibilityValid() &&
    1234           0 :                     rAttrLayer->getVisibility() != isVisible() )
    1235             :                 {
    1236           0 :                     const bool bVisibility( rAttrLayer->getVisibility() );
    1237             : 
    1238             :                     // visibilities differ - adjust ours, then
    1239           0 :                     if( mpAttributeLayer )
    1240           0 :                         mpAttributeLayer->setVisibility( bVisibility );
    1241             :                     else
    1242           0 :                         mbIsVisible = bVisibility;
    1243             :                 }
    1244             : 
    1245             :                 // END TEMP FIX
    1246             : 
    1247           0 :                 return true;
    1248             :             }
    1249             : 
    1250           0 :             return false;
    1251             :         }
    1252             : 
    1253           0 :         sal_Int32 DrawShape::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
    1254             :         {
    1255           0 :             return maSubsetting.getNumberOfTreeNodes( eNodeType );
    1256             :         }
    1257             : 
    1258           0 :         DocTreeNode DrawShape::getTreeNode( sal_Int32               nNodeIndex,
    1259             :                                             DocTreeNode::NodeType   eNodeType ) const // throw ShapeLoadFailedException
    1260             :         {
    1261           0 :             if ( hasHyperlinks())
    1262             :             {
    1263           0 :                 prepareHyperlinkIndices();
    1264             :             }
    1265             : 
    1266           0 :             return maSubsetting.getTreeNode( nNodeIndex, eNodeType );
    1267             :         }
    1268             : 
    1269           0 :         sal_Int32 DrawShape::getNumberOfSubsetTreeNodes ( const DocTreeNode&    rParentNode,
    1270             :                                                           DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
    1271             :         {
    1272           0 :             return maSubsetting.getNumberOfSubsetTreeNodes( rParentNode, eNodeType );
    1273             :         }
    1274             : 
    1275           0 :         DocTreeNode DrawShape::getSubsetTreeNode( const DocTreeNode&    rParentNode,
    1276             :                                                   sal_Int32             nNodeIndex,
    1277             :                                                   DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
    1278             :         {
    1279           0 :             return maSubsetting.getSubsetTreeNode( rParentNode, nNodeIndex, eNodeType );
    1280             :         }
    1281             :     }
    1282           3 : }
    1283             : 
    1284             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10