LCOV - code coverage report
Current view: top level - libreoffice/slideshow/source/engine/shapes - drawshape.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 380 0.0 %
Date: 2012-12-27 Functions: 0 52 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10