LCOV - code coverage report
Current view: top level - slideshow/source/engine/shapes - drawshape.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 383 0.3 %
Date: 2015-06-13 12:38:46 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 :             ViewShape::RenderArgs renderArgs( getViewRenderArgs() );
     172           0 :             if( ::std::count_if( maViewShapes.begin(),
     173             :                                  maViewShapes.end(),
     174             :                                  ::boost::bind<bool>(
     175             :                                      ::boost::mem_fn( &ViewShape::update ), // though _theoretically_,
     176             :                                                                              // bind should eat this even
     177             :                                                                              // with _1 being a shared_ptr,
     178             :                                                                              // it does _not_ for MSVC without
     179             :                                                                              // the extra mem_fn. WTF.
     180             :                                      _1,
     181             :                                      ::boost::cref( mpCurrMtf ),
     182             :                                      ::boost::cref( renderArgs ),
     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             :             // already added?
     636           0 :             if( ::std::any_of( maViewShapes.begin(),
     637             :                                maViewShapes.end(),
     638             :                                ::boost::bind<bool>(
     639             :                                     ::std::equal_to< ViewLayerSharedPtr >(),
     640             :                                     ::boost::bind( &ViewShape::getViewLayer,
     641             :                                                    _1 ),
     642           0 :                                     ::boost::cref( rNewLayer ) ) ))
     643             :             {
     644             :                 // yes, nothing to do
     645           0 :                 return;
     646             :             }
     647             : 
     648           0 :             ViewShapeSharedPtr pNewShape( new ViewShape( rNewLayer ) );
     649             : 
     650           0 :             maViewShapes.push_back( pNewShape );
     651             : 
     652             :             // pass on animation state
     653           0 :             if( mnIsAnimatedCount )
     654             :             {
     655           0 :                 for( int i=0; i<mnIsAnimatedCount; ++i )
     656           0 :                     pNewShape->enterAnimationMode();
     657             :             }
     658             : 
     659             :             // render the Shape on the newly added ViewLayer
     660           0 :             if( bRedrawLayer )
     661             :             {
     662             :                 pNewShape->update( mpCurrMtf,
     663             :                                    getViewRenderArgs(),
     664             :                                    ViewShape::FORCE,
     665           0 :                                    isVisible() );
     666           0 :             }
     667             :         }
     668             : 
     669           0 :         bool DrawShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
     670             :         {
     671           0 :             const ViewShapeVector::iterator aEnd( maViewShapes.end() );
     672             : 
     673             :             OSL_ENSURE( ::std::count_if(maViewShapes.begin(),
     674             :                                         aEnd,
     675             :                                         ::boost::bind<bool>(
     676             :                                             ::std::equal_to< ViewLayerSharedPtr >(),
     677             :                                             ::boost::bind( &ViewShape::getViewLayer,
     678             :                                                            _1 ),
     679             :                                             ::boost::cref( rLayer ) ) ) < 2,
     680             :                         "DrawShape::removeViewLayer(): Duplicate ViewLayer entries!" );
     681             : 
     682           0 :             ViewShapeVector::iterator aIter;
     683             : 
     684           0 :             if( (aIter=::std::remove_if( maViewShapes.begin(),
     685             :                                          aEnd,
     686             :                                          ::boost::bind<bool>(
     687             :                                              ::std::equal_to< ViewLayerSharedPtr >(),
     688             :                                              ::boost::bind( &ViewShape::getViewLayer,
     689             :                                                             _1 ),
     690           0 :                                              ::boost::cref( rLayer ) ) )) == aEnd )
     691             :             {
     692             :                 // view layer seemingly was not added, failed
     693           0 :                 return false;
     694             :             }
     695             : 
     696             :             // actually erase from container
     697           0 :             maViewShapes.erase( aIter, aEnd );
     698             : 
     699           0 :             return true;
     700             :         }
     701             : 
     702           0 :         bool DrawShape::clearAllViewLayers()
     703             :         {
     704           0 :             maViewShapes.clear();
     705           0 :             return true;
     706             :         }
     707             : 
     708           0 :         bool DrawShape::update() const
     709             :         {
     710           0 :             if( mbForceUpdate )
     711             :             {
     712           0 :                 return render();
     713             :             }
     714             :             else
     715             :             {
     716           0 :                 return implRender( getUpdateFlags() );
     717             :             }
     718             :         }
     719             : 
     720           0 :         bool DrawShape::render() const
     721             :         {
     722             :             // force redraw. Have to also pass on the update flags,
     723             :             // because e.g. content update (regeneration of the
     724             :             // metafile renderer) is normally not performed. A simple
     725             :             // ViewShape::FORCE would only paint the metafile in its
     726             :             // old state.
     727           0 :             return implRender( ViewShape::FORCE | getUpdateFlags() );
     728             :         }
     729             : 
     730           0 :         bool DrawShape::isContentChanged() const
     731             :         {
     732           0 :             return mbForceUpdate ||
     733           0 :                 getUpdateFlags() != ViewShape::NONE;
     734             :         }
     735             : 
     736             : 
     737           0 :         ::basegfx::B2DRectangle DrawShape::getBounds() const
     738             :         {
     739             :             // little optimization: for non-modified shapes, we don't
     740             :             // create an ShapeAttributeStack, and therefore also don't
     741             :             // have to check it.
     742             :             return getShapePosSize( maBounds,
     743           0 :                                     mpAttributeLayer );
     744             :         }
     745             : 
     746           0 :         ::basegfx::B2DRectangle DrawShape::getDomBounds() const
     747             :         {
     748           0 :             return maBounds;
     749             :         }
     750             : 
     751             :         namespace
     752             :         {
     753             :             /** Functor expanding AA border for each passed ViewShape
     754             : 
     755             :                 Could not use ::boost::bind here, since
     756             :                 B2DRange::expand is overloaded (which yields one or
     757             :                 the other template type deduction ambiguous)
     758             :              */
     759             :             class Expander
     760             :             {
     761             :             public:
     762           0 :                 Expander( ::basegfx::B2DSize& rBounds ) :
     763           0 :                     mrBounds( rBounds )
     764             :                 {
     765           0 :                 }
     766             : 
     767           0 :                 void operator()( const ViewShapeSharedPtr& rShape ) const
     768             :                 {
     769           0 :                     const ::basegfx::B2DSize& rShapeBorder( rShape->getAntialiasingBorder() );
     770             : 
     771             :                     mrBounds.setX(
     772             :                         ::std::max(
     773           0 :                             rShapeBorder.getX(),
     774           0 :                             mrBounds.getX() ) );
     775             :                     mrBounds.setY(
     776             :                         ::std::max(
     777           0 :                             rShapeBorder.getY(),
     778           0 :                             mrBounds.getY() ) );
     779           0 :                 }
     780             : 
     781             :             private:
     782             :                 ::basegfx::B2DSize& mrBounds;
     783             :             };
     784             :         }
     785             : 
     786           0 :         ::basegfx::B2DRectangle DrawShape::getUpdateArea() const
     787             :         {
     788           0 :             ::basegfx::B2DRectangle aBounds;
     789             : 
     790             :             // an already empty shape bound need no further
     791             :             // treatment. In fact, any changes applied below would
     792             :             // actually remove the special empty state, thus, don't
     793             :             // change!
     794           0 :             if( !maBounds.isEmpty() )
     795             :             {
     796           0 :                 basegfx::B2DRectangle aUnitBounds(0.0,0.0,1.0,1.0);
     797             : 
     798           0 :                 if( !maViewShapes.empty() )
     799           0 :                     aUnitBounds = getActualUnitShapeBounds();
     800             : 
     801           0 :                 if( !aUnitBounds.isEmpty() )
     802             :                 {
     803           0 :                     if( mpAttributeLayer )
     804             :                     {
     805             :                         // calc actual shape area (in user coordinate
     806             :                         // space) from the transformation as given by the
     807             :                         // shape attribute layer
     808             :                         aBounds = getShapeUpdateArea( aUnitBounds,
     809           0 :                                                       getShapeTransformation( getBounds(),
     810             :                                                                               mpAttributeLayer ),
     811           0 :                                                       mpAttributeLayer );
     812             :                     }
     813             :                     else
     814             :                     {
     815             :                         // no attribute layer, thus, the true shape bounds
     816             :                         // can be directly derived from the XShape bound
     817             :                         // attribute
     818             :                         aBounds = getShapeUpdateArea( aUnitBounds,
     819           0 :                                                       maBounds );
     820             :                     }
     821             : 
     822           0 :                     if( !maViewShapes.empty() )
     823             :                     {
     824             :                         // determine border needed for antialiasing the shape
     825           0 :                         ::basegfx::B2DSize aAABorder(0.0,0.0);
     826             : 
     827             :                         // for every view, get AA border and 'expand' aAABorder
     828             :                         // appropriately.
     829             :                         ::std::for_each( maViewShapes.begin(),
     830             :                                          maViewShapes.end(),
     831           0 :                                          Expander( aAABorder ) );
     832             : 
     833             :                         // add calculated AA border to aBounds
     834           0 :                         aBounds = ::basegfx::B2DRectangle( aBounds.getMinX() - aAABorder.getX(),
     835           0 :                                                            aBounds.getMinY() - aAABorder.getY(),
     836           0 :                                                            aBounds.getMaxX() + aAABorder.getX(),
     837           0 :                                                            aBounds.getMaxY() + aAABorder.getY() );
     838             :                     }
     839             :                 }
     840             :             }
     841             : 
     842           0 :             return aBounds;
     843             :         }
     844             : 
     845           0 :         bool DrawShape::isVisible() const
     846             :         {
     847           0 :             bool bIsVisible( mbIsVisible );
     848             : 
     849           0 :             if( mpAttributeLayer )
     850             :             {
     851             :                 // check whether visibility and alpha are not default
     852             :                 // (mpAttributeLayer->isVisibilityValid() returns true
     853             :                 // then): bVisible becomes true, if shape visibility
     854             :                 // is on and alpha is not 0.0 (fully transparent)
     855           0 :                 if( mpAttributeLayer->isVisibilityValid() )
     856           0 :                     bIsVisible = mpAttributeLayer->getVisibility();
     857             : 
     858             :                 // only touch bIsVisible, if the shape is still
     859             :                 // visible - if getVisibility already made us
     860             :                 // invisible, no alpha value will make us appear
     861             :                 // again.
     862           0 :                 if( bIsVisible && mpAttributeLayer->isAlphaValid() )
     863           0 :                     bIsVisible = !::basegfx::fTools::equalZero( mpAttributeLayer->getAlpha() );
     864             :             }
     865             : 
     866           0 :             return bIsVisible;
     867             :         }
     868             : 
     869           0 :         double DrawShape::getPriority() const
     870             :         {
     871           0 :             return mnPriority;
     872             :         }
     873             : 
     874           0 :         bool DrawShape::isBackgroundDetached() const
     875             :         {
     876           0 :             return mnIsAnimatedCount > 0;
     877             :         }
     878             : 
     879           0 :         bool DrawShape::hasIntrinsicAnimation() const
     880             :         {
     881           0 :             return (!maAnimationFrames.empty() || mbDrawingLayerAnim);
     882             :         }
     883             : 
     884           0 :         bool DrawShape::setIntrinsicAnimationFrame( ::std::size_t nCurrFrame )
     885             :         {
     886           0 :             ENSURE_OR_RETURN_FALSE( nCurrFrame < maAnimationFrames.size(),
     887             :                                "DrawShape::setIntrinsicAnimationFrame(): frame index out of bounds" );
     888             : 
     889           0 :             if( mnCurrFrame != nCurrFrame )
     890             :             {
     891           0 :                 mnCurrFrame   = nCurrFrame;
     892           0 :                 mpCurrMtf     = maAnimationFrames[ mnCurrFrame ].mpMtf;
     893           0 :                 mbForceUpdate = true;
     894             :             }
     895             : 
     896           0 :             return true;
     897             :         }
     898             : 
     899             :         // hyperlink support
     900           0 :         void DrawShape::prepareHyperlinkIndices() const
     901             :         {
     902           0 :             if ( !maHyperlinkIndices.empty())
     903             :             {
     904           0 :                 maHyperlinkIndices.clear();
     905           0 :                 maHyperlinkRegions.clear();
     906             :             }
     907             : 
     908           0 :             sal_Int32 nIndex = 0;
     909           0 :             for ( MetaAction * pCurrAct = mpCurrMtf->FirstAction();
     910           0 :                   pCurrAct != 0; pCurrAct = mpCurrMtf->NextAction() )
     911             :             {
     912           0 :                 if (pCurrAct->GetType() == MetaActionType::COMMENT) {
     913             :                     MetaCommentAction * pAct =
     914           0 :                         static_cast<MetaCommentAction *>(pCurrAct);
     915             :                     // skip comment if not a special XTEXT comment
     916           0 :                     if (pAct->GetComment().equalsIgnoreAsciiCase("FIELD_SEQ_BEGIN") &&
     917             :                         // e.g. date field doesn't have data!
     918             :                         // currently assuming that only url field, this is
     919             :                         // somehow fragile! xxx todo if possible
     920           0 :                         pAct->GetData() != 0 &&
     921           0 :                         pAct->GetDataSize() > 0)
     922             :                     {
     923           0 :                         if (!maHyperlinkIndices.empty() &&
     924           0 :                             maHyperlinkIndices.back().second == -1) {
     925             :                             SAL_WARN( "slideshow", "### pending FIELD_SEQ_END!" );
     926           0 :                             maHyperlinkIndices.pop_back();
     927           0 :                             maHyperlinkRegions.pop_back();
     928             :                         }
     929             :                         maHyperlinkIndices.push_back(
     930           0 :                             HyperlinkIndexPair( nIndex + 1,
     931           0 :                                                 -1 /* to be filled below */ ) );
     932             :                         maHyperlinkRegions.push_back(
     933             :                             HyperlinkRegion(
     934             :                                 basegfx::B2DRectangle(),
     935             :                                 OUString(
     936             :                                     reinterpret_cast<sal_Unicode const*>(
     937           0 :                                         pAct->GetData()),
     938           0 :                                     pAct->GetDataSize() / sizeof(sal_Unicode) )
     939           0 :                                 ) );
     940             :                     }
     941           0 :                     else if (pAct->GetComment().equalsIgnoreAsciiCase("FIELD_SEQ_END") &&
     942             :                              // pending end is expected:
     943           0 :                              !maHyperlinkIndices.empty() &&
     944           0 :                              maHyperlinkIndices.back().second == -1)
     945             :                     {
     946           0 :                         maHyperlinkIndices.back().second = nIndex;
     947             :                     }
     948           0 :                     ++nIndex;
     949             :                 }
     950             :                 else
     951           0 :                     nIndex += getNextActionOffset(pCurrAct);
     952             :             }
     953           0 :             if (!maHyperlinkIndices.empty() &&
     954           0 :                 maHyperlinkIndices.back().second == -1) {
     955             :                 SAL_WARN( "slideshow", "### pending FIELD_SEQ_END!" );
     956           0 :                 maHyperlinkIndices.pop_back();
     957           0 :                 maHyperlinkRegions.pop_back();
     958             :             }
     959             :             OSL_ASSERT( maHyperlinkIndices.size() == maHyperlinkRegions.size());
     960           0 :         }
     961             : 
     962           0 :         bool DrawShape::hasHyperlinks() const
     963             :         {
     964           0 :             return ! maHyperlinkRegions.empty();
     965             :         }
     966             : 
     967           0 :         HyperlinkArea::HyperlinkRegions DrawShape::getHyperlinkRegions() const
     968             :         {
     969             :             OSL_ASSERT( !maViewShapes.empty() );
     970             : 
     971           0 :             if( !isVisible() )
     972           0 :                 return HyperlinkArea::HyperlinkRegions();
     973             : 
     974             :             // late init, determine regions:
     975           0 :             if( !maHyperlinkRegions.empty() &&
     976           0 :                 !maViewShapes.empty() &&
     977             :                 // region already inited?
     978           0 :                 maHyperlinkRegions.front().first.getWidth() == 0 &&
     979           0 :                 maHyperlinkRegions.front().first.getHeight() == 0 &&
     980           0 :                 maHyperlinkRegions.size() == maHyperlinkIndices.size() )
     981             :             {
     982             :                 // TODO(Q2): Although this _is_ currently
     983             :                 // view-agnostic, it might not stay like that.
     984           0 :                 ViewShapeSharedPtr const& pViewShape = maViewShapes.front();
     985             :                 cppcanvas::CanvasSharedPtr const pCanvas(
     986           0 :                     pViewShape->getViewLayer()->getCanvas() );
     987             : 
     988             :                 // reuse Renderer of first view shape:
     989             :                 cppcanvas::RendererSharedPtr const pRenderer(
     990             :                     pViewShape->getRenderer(
     991           0 :                         pCanvas, mpCurrMtf, mpAttributeLayer ) );
     992             : 
     993             :                 OSL_ASSERT( pRenderer );
     994             : 
     995           0 :                 if (pRenderer)
     996             :                 {
     997             :                     basegfx::B2DHomMatrix const aOldTransform(
     998           0 :                         pCanvas->getTransformation() );
     999           0 :                     basegfx::B2DHomMatrix aTransform;
    1000           0 :                     pCanvas->setTransformation( aTransform /* empty */ );
    1001             : 
    1002             :                     comphelper::ScopeGuard const resetOldTransformation(
    1003             :                         boost::bind( &cppcanvas::Canvas::setTransformation,
    1004             :                                      pCanvas.get(),
    1005           0 :                                      boost::cref(aOldTransform) ));
    1006             : 
    1007             :                     aTransform.scale( maBounds.getWidth(),
    1008           0 :                                       maBounds.getHeight() );
    1009           0 :                     pRenderer->setTransformation( aTransform );
    1010           0 :                     pRenderer->setClip();
    1011             : 
    1012           0 :                     for( std::size_t pos = maHyperlinkRegions.size(); pos--; )
    1013             :                     {
    1014             :                         // get region:
    1015           0 :                         HyperlinkIndexPair const& rIndices = maHyperlinkIndices[pos];
    1016             :                         basegfx::B2DRectangle const region(
    1017           0 :                             pRenderer->getSubsetArea( rIndices.first,
    1018           0 :                                                       rIndices.second ));
    1019           0 :                         maHyperlinkRegions[pos].first = region;
    1020           0 :                     }
    1021           0 :                 }
    1022             :             }
    1023             : 
    1024             :             // shift shape-relative hyperlink regions to
    1025             :             // slide-absolute position
    1026             : 
    1027           0 :             HyperlinkRegions aTranslatedRegions;
    1028           0 :             const basegfx::B2DPoint& rOffset(getBounds().getMinimum());
    1029           0 :             HyperlinkRegions::const_iterator       aIter( maHyperlinkRegions.begin() );
    1030           0 :             HyperlinkRegions::const_iterator const aEnd ( maHyperlinkRegions.end() );
    1031           0 :             while( aIter != aEnd )
    1032             :             {
    1033           0 :                 basegfx::B2DRange const& relRegion( aIter->first );
    1034             :                 aTranslatedRegions.push_back(
    1035             :                     std::make_pair(
    1036             :                         basegfx::B2DRange(
    1037           0 :                             relRegion.getMinimum() + rOffset,
    1038           0 :                             relRegion.getMaximum() + rOffset),
    1039           0 :                         aIter->second) );
    1040           0 :                 ++aIter;
    1041             :             }
    1042             : 
    1043           0 :             return aTranslatedRegions;
    1044             :         }
    1045             : 
    1046           0 :         double DrawShape::getHyperlinkPriority() const
    1047             :         {
    1048           0 :             return getPriority();
    1049             :         }
    1050             : 
    1051             : 
    1052             :         // AnimatableShape methods
    1053             : 
    1054             : 
    1055           0 :         void DrawShape::enterAnimationMode()
    1056             :         {
    1057             :             OSL_ENSURE( !maViewShapes.empty(),
    1058             :                         "DrawShape::enterAnimationMode(): called on DrawShape without views" );
    1059             : 
    1060           0 :             if( mnIsAnimatedCount == 0 )
    1061             :             {
    1062             :                 // notify all ViewShapes, by calling their enterAnimationMode method.
    1063             :                 // We're now entering animation mode
    1064             :                 ::std::for_each( maViewShapes.begin(),
    1065             :                                  maViewShapes.end(),
    1066           0 :                                  ::boost::mem_fn( &ViewShape::enterAnimationMode ) );
    1067             :             }
    1068             : 
    1069           0 :             ++mnIsAnimatedCount;
    1070           0 :         }
    1071             : 
    1072           0 :         void DrawShape::leaveAnimationMode()
    1073             :         {
    1074             :             OSL_ENSURE( !maViewShapes.empty(),
    1075             :                         "DrawShape::leaveAnimationMode(): called on DrawShape without views" );
    1076             : 
    1077           0 :             --mnIsAnimatedCount;
    1078             : 
    1079           0 :             if( mnIsAnimatedCount == 0 )
    1080             :             {
    1081             :                 // notify all ViewShapes, by calling their leaveAnimationMode method.
    1082             :                 // we're now leaving animation mode
    1083             :                 ::std::for_each( maViewShapes.begin(),
    1084             :                                  maViewShapes.end(),
    1085           0 :                                  ::boost::mem_fn( &ViewShape::leaveAnimationMode ) );
    1086             :             }
    1087           0 :         }
    1088             : 
    1089             : 
    1090             :         // AttributableShape methods
    1091             : 
    1092             : 
    1093           0 :         ShapeAttributeLayerSharedPtr DrawShape::createAttributeLayer()
    1094             :         {
    1095             :             // create new layer, with last as its new child
    1096           0 :             mpAttributeLayer.reset( new ShapeAttributeLayer( mpAttributeLayer ) );
    1097             : 
    1098             :             // Update the local state ids to reflect those of the new layer.
    1099           0 :             updateStateIds();
    1100             : 
    1101           0 :             return mpAttributeLayer;
    1102             :         }
    1103             : 
    1104           0 :         bool DrawShape::revokeAttributeLayer( const ShapeAttributeLayerSharedPtr& rLayer )
    1105             :         {
    1106           0 :             if( !mpAttributeLayer )
    1107           0 :                 return false; // no layers
    1108             : 
    1109           0 :             if( mpAttributeLayer == rLayer )
    1110             :             {
    1111             :                 // it's the toplevel layer
    1112           0 :                 mpAttributeLayer = mpAttributeLayer->getChildLayer();
    1113             : 
    1114             :                 // force content redraw, all state variables have
    1115             :                 // possibly changed
    1116           0 :                 mbAttributeLayerRevoked = true;
    1117             : 
    1118           0 :                 return true;
    1119             :             }
    1120             :             else
    1121             :             {
    1122             :                 // pass on to the layer, to try its children
    1123           0 :                 return mpAttributeLayer->revokeChildLayer( rLayer );
    1124             :             }
    1125             :         }
    1126             : 
    1127           0 :         ShapeAttributeLayerSharedPtr DrawShape::getTopmostAttributeLayer() const
    1128             :         {
    1129           0 :             return mpAttributeLayer;
    1130             :         }
    1131             : 
    1132           0 :         void DrawShape::setVisibility( bool bVisible )
    1133             :         {
    1134           0 :             if( mbIsVisible != bVisible )
    1135             :             {
    1136           0 :                 mbIsVisible = bVisible;
    1137           0 :                 mbForceUpdate = true;
    1138             :             }
    1139           0 :         }
    1140             : 
    1141           0 :         const DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier() const
    1142             :         {
    1143           0 :             return *this;
    1144             :         }
    1145             : 
    1146           0 :         DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier()
    1147             :         {
    1148           0 :             return *this;
    1149             :         }
    1150             : 
    1151           0 :         DocTreeNode DrawShape::getSubsetNode() const
    1152             :         {
    1153             :             // forward to delegate
    1154           0 :             return maSubsetting.getSubsetNode();
    1155             :         }
    1156             : 
    1157           0 :         AttributableShapeSharedPtr DrawShape::getSubset( const DocTreeNode& rTreeNode ) const
    1158             :         {
    1159             :             // forward to delegate
    1160           0 :             return maSubsetting.getSubsetShape( rTreeNode );
    1161             :         }
    1162             : 
    1163           0 :         bool DrawShape::createSubset( AttributableShapeSharedPtr&   o_rSubset,
    1164             :                                       const DocTreeNode&            rTreeNode )
    1165             :         {
    1166             :             // subset shape already created for this DocTreeNode?
    1167           0 :             AttributableShapeSharedPtr pSubset( maSubsetting.getSubsetShape( rTreeNode ) );
    1168             : 
    1169             :             // when true, this method has created a new subset
    1170             :             // DrawShape
    1171           0 :             bool bNewlyCreated( false );
    1172             : 
    1173           0 :             if( pSubset )
    1174             :             {
    1175           0 :                 o_rSubset = pSubset;
    1176             : 
    1177             :                 // reusing existing subset
    1178             :             }
    1179             :             else
    1180             :             {
    1181             :                 // not yet created, init entry
    1182             :                 o_rSubset.reset( new DrawShape( *this,
    1183             :                                                 rTreeNode,
    1184             :                                                 // TODO(Q3): That's a
    1185             :                                                 // hack. We assume
    1186             :                                                 // that start and end
    1187             :                                                 // index will always
    1188             :                                                 // be less than 65535
    1189           0 :                                                 mnPriority +
    1190           0 :                                                 rTreeNode.getStartIndex()/double(SAL_MAX_INT16) ));
    1191             : 
    1192           0 :                 bNewlyCreated = true; // subset newly created
    1193             :             }
    1194             : 
    1195             :             // always register shape at DrawShapeSubsetting, to keep
    1196             :             // refcount up-to-date
    1197           0 :             maSubsetting.addSubsetShape( o_rSubset );
    1198             : 
    1199             :             // flush bounds cache
    1200           0 :             maCurrentShapeUnitBounds.reset();
    1201             : 
    1202           0 :             return bNewlyCreated;
    1203             :         }
    1204             : 
    1205           0 :         bool DrawShape::revokeSubset( const AttributableShapeSharedPtr& rShape )
    1206             :         {
    1207             :             // flush bounds cache
    1208           0 :             maCurrentShapeUnitBounds.reset();
    1209             : 
    1210             :             // forward to delegate
    1211           0 :             if( maSubsetting.revokeSubsetShape( rShape ) )
    1212             :             {
    1213             :                 // force redraw, our content has possibly changed (as
    1214             :                 // one of the subsets now display within our shape
    1215             :                 // again).
    1216           0 :                 mbForceUpdate = true;
    1217             : 
    1218             :                 // #i47428# TEMP FIX: synchronize visibility of subset
    1219             :                 // with parent.
    1220             : 
    1221             :                 // TODO(F3): Remove here, and implement
    1222             :                 // TEXT_ONLY/BACKGROUND_ONLY with the proverbial
    1223             :                 // additional level of indirection: create a
    1224             :                 // persistent subset, containing all text/only the
    1225             :                 // background respectively. From _that_ object,
    1226             :                 // generate the temporary character subset shapes.
    1227             :                 const ShapeAttributeLayerSharedPtr& rAttrLayer(
    1228           0 :                     rShape->getTopmostAttributeLayer() );
    1229           0 :                 if( rAttrLayer &&
    1230           0 :                     rAttrLayer->isVisibilityValid() &&
    1231           0 :                     rAttrLayer->getVisibility() != isVisible() )
    1232             :                 {
    1233           0 :                     const bool bVisibility( rAttrLayer->getVisibility() );
    1234             : 
    1235             :                     // visibilities differ - adjust ours, then
    1236           0 :                     if( mpAttributeLayer )
    1237           0 :                         mpAttributeLayer->setVisibility( bVisibility );
    1238             :                     else
    1239           0 :                         mbIsVisible = bVisibility;
    1240             :                 }
    1241             : 
    1242             :                 // END TEMP FIX
    1243             : 
    1244           0 :                 return true;
    1245             :             }
    1246             : 
    1247           0 :             return false;
    1248             :         }
    1249             : 
    1250           0 :         sal_Int32 DrawShape::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
    1251             :         {
    1252           0 :             return maSubsetting.getNumberOfTreeNodes( eNodeType );
    1253             :         }
    1254             : 
    1255           0 :         DocTreeNode DrawShape::getTreeNode( sal_Int32               nNodeIndex,
    1256             :                                             DocTreeNode::NodeType   eNodeType ) const // throw ShapeLoadFailedException
    1257             :         {
    1258           0 :             if ( hasHyperlinks())
    1259             :             {
    1260           0 :                 prepareHyperlinkIndices();
    1261             :             }
    1262             : 
    1263           0 :             return maSubsetting.getTreeNode( nNodeIndex, eNodeType );
    1264             :         }
    1265             : 
    1266           0 :         sal_Int32 DrawShape::getNumberOfSubsetTreeNodes ( const DocTreeNode&    rParentNode,
    1267             :                                                           DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
    1268             :         {
    1269           0 :             return maSubsetting.getNumberOfSubsetTreeNodes( rParentNode, eNodeType );
    1270             :         }
    1271             : 
    1272           0 :         DocTreeNode DrawShape::getSubsetTreeNode( const DocTreeNode&    rParentNode,
    1273             :                                                   sal_Int32             nNodeIndex,
    1274             :                                                   DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
    1275             :         {
    1276           0 :             return maSubsetting.getSubsetTreeNode( rParentNode, nNodeIndex, eNodeType );
    1277             :         }
    1278             :     }
    1279           3 : }
    1280             : 
    1281             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11