LCOV - code coverage report
Current view: top level - svtools/source/graphic - grfmgr.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 306 628 48.7 %
Date: 2014-11-03 Functions: 41 63 65.1 %
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             : #include <sal/config.h>
      21             : 
      22             : #include <algorithm>
      23             : 
      24             : #include <officecfg/Office/Common.hxx>
      25             : #include <tools/vcompat.hxx>
      26             : #include <tools/helpers.hxx>
      27             : #include <unotools/ucbstreamhelper.hxx>
      28             : #include <unotools/localfilehelper.hxx>
      29             : #include <unotools/tempfile.hxx>
      30             : #include <vcl/svapp.hxx>
      31             : #include <vcl/cvtgrf.hxx>
      32             : #include <vcl/metaact.hxx>
      33             : #include <vcl/virdev.hxx>
      34             : #include <svtools/grfmgr.hxx>
      35             : 
      36             : #include <vcl/pdfextoutdevdata.hxx>
      37             : 
      38             : #include <com/sun/star/container/XNameContainer.hpp>
      39             : #include <com/sun/star/beans/XPropertySet.hpp>
      40             : #include <boost/scoped_ptr.hpp>
      41             : 
      42             : using com::sun::star::uno::Reference;
      43             : using com::sun::star::uno::XInterface;
      44             : using com::sun::star::uno::UNO_QUERY;
      45             : using com::sun::star::uno::Sequence;
      46             : using com::sun::star::container::XNameContainer;
      47             : using com::sun::star::beans::XPropertySet;
      48             : 
      49             : GraphicManager* GraphicObject::mpGlobalMgr = NULL;
      50             : 
      51           0 : struct GrfSimpleCacheObj
      52             : {
      53             :     Graphic     maGraphic;
      54             :     GraphicAttr maAttr;
      55             : 
      56           0 :                 GrfSimpleCacheObj( const Graphic& rGraphic, const GraphicAttr& rAttr ) :
      57           0 :                     maGraphic( rGraphic ), maAttr( rAttr ) {}
      58             : };
      59             : 
      60           0 : TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream );
      61             : 
      62             : // unique increasing ID for being able to detect the GraphicObject with the
      63             : // oldest last data changes
      64             : static sal_uLong aIncrementingTimeOfLastDataChange = 1;
      65             : 
      66        2746 : void GraphicObject::ImplAfterDataChange()
      67             : {
      68             :     // set unique timestamp ID of last data change
      69        2746 :     mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
      70             : 
      71             :     // check memory footprint of all GraphicObjects managed and evtl. take action
      72        2746 :     if (mpMgr)
      73        2746 :         mpMgr->ImplCheckSizeOfSwappedInGraphics();
      74        2746 : }
      75             : 
      76        4398 : GraphicObject::GraphicObject( const GraphicManager* pMgr ) :
      77             :     maLink      (),
      78        4398 :     maUserData  ()
      79             : {
      80        4398 :     ImplConstruct();
      81        4398 :     ImplAssignGraphicData();
      82        4398 :     ImplSetGraphicManager( pMgr );
      83        4398 : }
      84             : 
      85        9178 : GraphicObject::GraphicObject( const Graphic& rGraphic, const GraphicManager* pMgr ) :
      86             :     maGraphic   ( rGraphic ),
      87             :     maLink      (),
      88        9178 :     maUserData  ()
      89             : {
      90        9178 :     ImplConstruct();
      91        9178 :     ImplAssignGraphicData();
      92        9178 :     ImplSetGraphicManager( pMgr );
      93        9178 : }
      94             : 
      95       14697 : GraphicObject::GraphicObject( const GraphicObject& rGraphicObj, const GraphicManager* pMgr ) :
      96             :     SvDataCopyStream(),
      97       14697 :     maGraphic   ( rGraphicObj.GetGraphic() ),
      98             :     maAttr      ( rGraphicObj.maAttr ),
      99             :     maLink      ( rGraphicObj.maLink ),
     100       29394 :     maUserData  ( rGraphicObj.maUserData )
     101             : {
     102       14697 :     ImplConstruct();
     103       14697 :     ImplAssignGraphicData();
     104       14697 :     ImplSetGraphicManager( pMgr, NULL, &rGraphicObj );
     105       14697 : }
     106             : 
     107        2712 : GraphicObject::GraphicObject( const OString& rUniqueID, const GraphicManager* pMgr ) :
     108             :     maLink      (),
     109        2712 :     maUserData  ()
     110             : {
     111        2712 :     ImplConstruct();
     112             : 
     113             :     // assign default properties
     114        2712 :     ImplAssignGraphicData();
     115             : 
     116        2712 :     ImplSetGraphicManager( pMgr, &rUniqueID );
     117             : 
     118             :     // update properties
     119        2712 :     ImplAssignGraphicData();
     120        2712 : }
     121             : 
     122       65754 : GraphicObject::~GraphicObject()
     123             : {
     124       30772 :     if( mpMgr )
     125             :     {
     126       30772 :         mpMgr->ImplUnregisterObj( *this );
     127             : 
     128       30772 :         if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
     129          90 :             delete mpGlobalMgr, mpGlobalMgr = NULL;
     130             :     }
     131             : 
     132       30772 :     delete mpSwapOutTimer;
     133       30772 :     delete mpSwapStreamHdl;
     134       30772 :     delete mpSimpleCache;
     135       34982 : }
     136             : 
     137       30985 : void GraphicObject::ImplConstruct()
     138             : {
     139       30985 :     mpMgr = NULL;
     140       30985 :     mpSwapStreamHdl = NULL;
     141       30985 :     mpSwapOutTimer = NULL;
     142       30985 :     mpSimpleCache = NULL;
     143       30985 :     mnAnimationLoopCount = 0;
     144       30985 :     mbAutoSwapped = false;
     145       30985 :     mbIsInSwapIn = false;
     146       30985 :     mbIsInSwapOut = false;
     147             : 
     148             :     // Init with a unique, increasing ID
     149       30985 :     mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
     150       30985 : }
     151             : 
     152       37977 : void GraphicObject::ImplAssignGraphicData()
     153             : {
     154       37977 :     maPrefSize = maGraphic.GetPrefSize();
     155       37977 :     maPrefMapMode = maGraphic.GetPrefMapMode();
     156       37977 :     mnSizeBytes = maGraphic.GetSizeBytes();
     157       37977 :     meType = maGraphic.GetType();
     158       37977 :     mbTransparent = maGraphic.IsTransparent();
     159       37977 :     mbAlpha = maGraphic.IsAlpha();
     160       37977 :     mbAnimated = maGraphic.IsAnimated();
     161       37977 :     mbEPS = maGraphic.IsEPS();
     162       37977 :     mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
     163       37977 : }
     164             : 
     165       30985 : void GraphicObject::ImplSetGraphicManager( const GraphicManager* pMgr, const OString* pID, const GraphicObject* pCopyObj )
     166             : {
     167       30985 :     if( !mpMgr || ( pMgr != mpMgr ) )
     168             :     {
     169       30985 :         if( !pMgr && mpMgr && ( mpMgr == mpGlobalMgr ) )
     170       30985 :             return;
     171             :         else
     172             :         {
     173       30985 :             if( mpMgr )
     174             :             {
     175           0 :                 mpMgr->ImplUnregisterObj( *this );
     176             : 
     177           0 :                 if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
     178           0 :                     delete mpGlobalMgr, mpGlobalMgr = NULL;
     179             :             }
     180             : 
     181       30985 :             if( !pMgr )
     182             :             {
     183       30985 :                 if( !mpGlobalMgr )
     184             :                 {
     185             :                     mpGlobalMgr = new GraphicManager(
     186             :                         (officecfg::Office::Common::Cache::GraphicManager::
     187         452 :                          TotalCacheSize::get()),
     188             :                         (officecfg::Office::Common::Cache::GraphicManager::
     189         226 :                          ObjectCacheSize::get()));
     190             :                     mpGlobalMgr->SetCacheTimeout(
     191             :                         officecfg::Office::Common::Cache::GraphicManager::
     192         226 :                         ObjectReleaseTime::get());
     193             :                 }
     194             : 
     195       30985 :                 mpMgr = mpGlobalMgr;
     196             :             }
     197             :             else
     198           0 :                 mpMgr = (GraphicManager*) pMgr;
     199             : 
     200       30985 :             mpMgr->ImplRegisterObj( *this, maGraphic, pID, pCopyObj );
     201             :         }
     202             :     }
     203             : }
     204             : 
     205         968 : void GraphicObject::ImplAutoSwapIn()
     206             : {
     207         968 :     if( IsSwappedOut() )
     208             :     {
     209          84 :         if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
     210           0 :             mbAutoSwapped = false;
     211             :         else
     212             :         {
     213          84 :             mbIsInSwapIn = true;
     214             : 
     215          84 :             if( maGraphic.SwapIn() )
     216          24 :                 mbAutoSwapped = false;
     217             :             else
     218             :             {
     219          60 :                 SvStream* pStream = GetSwapStream();
     220             : 
     221          60 :                 if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
     222             :                 {
     223          18 :                     if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
     224             :                     {
     225           0 :                         if( HasLink() )
     226             :                         {
     227           0 :                             OUString aURLStr;
     228             : 
     229           0 :                             if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr ) )
     230             :                             {
     231           0 :                                 boost::scoped_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_READ ));
     232             : 
     233           0 :                                 if( pIStm )
     234             :                                 {
     235           0 :                                     ReadGraphic( *pIStm, maGraphic );
     236           0 :                                     mbAutoSwapped = ( maGraphic.GetType() != GRAPHIC_NONE );
     237           0 :                                 }
     238           0 :                             }
     239             :                         }
     240             :                     }
     241          18 :                     else if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
     242           0 :                         mbAutoSwapped = !maGraphic.SwapIn();
     243          18 :                     else if( GRFMGR_AUTOSWAPSTREAM_LOADED == pStream )
     244          18 :                         mbAutoSwapped = maGraphic.IsSwapOut();
     245             :                     else
     246             :                     {
     247           0 :                         mbAutoSwapped = !maGraphic.SwapIn( pStream );
     248           0 :                         delete pStream;
     249             :                     }
     250             :                 }
     251             :                 else
     252             :                 {
     253             :                     DBG_ASSERT( ( GRAPHIC_NONE == meType ) || ( GRAPHIC_DEFAULT == meType ),
     254             :                                 "GraphicObject::ImplAutoSwapIn: could not get stream to swap in graphic! (=>KA)" );
     255             :                 }
     256             :             }
     257             : 
     258          84 :             mbIsInSwapIn = false;
     259             : 
     260          84 :             if( !mbAutoSwapped && mpMgr )
     261          42 :                 mpMgr->ImplGraphicObjectWasSwappedIn( *this );
     262             :         }
     263             : 
     264             :         // Handle evtl. needed AfterDataChanges
     265          84 :         ImplAfterDataChange();
     266             :     }
     267         968 : }
     268             : 
     269           4 : bool GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
     270             :                                        tools::PolyPolygon& rClipPolyPoly, bool& bRectClipRegion ) const
     271             : {
     272           4 :     bool bRet = false;
     273             : 
     274           4 :     if( GetType() != GRAPHIC_NONE )
     275             :     {
     276           4 :         Polygon         aClipPoly( Rectangle( rPt, rSz ) );
     277           4 :         const sal_uInt16    nRot10 = pAttr->GetRotation() % 3600;
     278           4 :         const Point     aOldOrigin( rPt );
     279           8 :         const MapMode   aMap100( MAP_100TH_MM );
     280           4 :         Size            aSize100;
     281             :         long            nTotalWidth, nTotalHeight;
     282             : 
     283           4 :         if( nRot10 )
     284             :         {
     285           0 :             aClipPoly.Rotate( rPt, nRot10 );
     286           0 :             bRectClipRegion = false;
     287             :         }
     288             :         else
     289           4 :             bRectClipRegion = true;
     290             : 
     291           4 :         rClipPolyPoly = aClipPoly;
     292             : 
     293           4 :         if( maGraphic.GetPrefMapMode() == MAP_PIXEL )
     294           4 :             aSize100 = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), aMap100 );
     295             :         else
     296             :         {
     297           0 :             MapMode m(maGraphic.GetPrefMapMode());
     298           0 :             aSize100 = pOut->LogicToLogic( maGraphic.GetPrefSize(), &m, &aMap100 );
     299             :         }
     300             : 
     301           4 :         nTotalWidth = aSize100.Width() - pAttr->GetLeftCrop() - pAttr->GetRightCrop();
     302           4 :         nTotalHeight = aSize100.Height() - pAttr->GetTopCrop() - pAttr->GetBottomCrop();
     303             : 
     304           4 :         if( aSize100.Width() > 0 && aSize100.Height() > 0 && nTotalWidth > 0 && nTotalHeight > 0 )
     305             :         {
     306           0 :             double fScale = (double) aSize100.Width() / nTotalWidth;
     307           0 :             const long nNewLeft = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_HORZ ) ? pAttr->GetRightCrop() : pAttr->GetLeftCrop() ) * fScale );
     308           0 :             const long nNewRight = nNewLeft + FRound( aSize100.Width() * fScale ) - 1;
     309             : 
     310           0 :             fScale = (double) rSz.Width() / aSize100.Width();
     311           0 :             rPt.X() += FRound( nNewLeft * fScale );
     312           0 :             rSz.Width() = FRound( ( nNewRight - nNewLeft + 1 ) * fScale );
     313             : 
     314           0 :             fScale = (double) aSize100.Height() / nTotalHeight;
     315           0 :             const long nNewTop = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_VERT ) ? pAttr->GetBottomCrop() : pAttr->GetTopCrop() ) * fScale );
     316           0 :             const long nNewBottom = nNewTop + FRound( aSize100.Height() * fScale ) - 1;
     317             : 
     318           0 :             fScale = (double) rSz.Height() / aSize100.Height();
     319           0 :             rPt.Y() += FRound( nNewTop * fScale );
     320           0 :             rSz.Height() = FRound( ( nNewBottom - nNewTop + 1 ) * fScale );
     321             : 
     322           0 :             if( nRot10 )
     323             :             {
     324           0 :                 Polygon aOriginPoly( 1 );
     325             : 
     326           0 :                 aOriginPoly[ 0 ] = rPt;
     327           0 :                 aOriginPoly.Rotate( aOldOrigin, nRot10 );
     328           0 :                 rPt = aOriginPoly[ 0 ];
     329             :             }
     330             : 
     331           0 :             bRet = true;
     332           4 :         }
     333             :     }
     334             : 
     335           4 :     return bRet;
     336             : }
     337             : 
     338        1618 : GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj )
     339             : {
     340        1618 :     if( &rGraphicObj != this )
     341             :     {
     342        1618 :         mpMgr->ImplUnregisterObj( *this );
     343             : 
     344        1618 :         delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
     345        1618 :         delete mpSimpleCache, mpSimpleCache = NULL;
     346             : 
     347        1618 :         maGraphic = rGraphicObj.GetGraphic();
     348        1618 :         maAttr = rGraphicObj.maAttr;
     349        1618 :         maLink = rGraphicObj.maLink;
     350        1618 :         maUserData = rGraphicObj.maUserData;
     351        1618 :         ImplAssignGraphicData();
     352        1618 :         mbAutoSwapped = false;
     353        1618 :         mpMgr = rGraphicObj.mpMgr;
     354             : 
     355        1618 :         mpMgr->ImplRegisterObj( *this, maGraphic, NULL, &rGraphicObj );
     356             :     }
     357             : 
     358        1618 :     return *this;
     359             : }
     360             : 
     361        3663 : bool GraphicObject::operator==( const GraphicObject& rGraphicObj ) const
     362             : {
     363        7234 :     return( ( rGraphicObj.maGraphic == maGraphic ) &&
     364       18039 :             ( rGraphicObj.maAttr == maAttr ) &&
     365       14376 :             ( rGraphicObj.GetLink() == GetLink() ) );
     366             : }
     367             : 
     368           0 : void GraphicObject::Load( SvStream& rIStm )
     369             : {
     370           0 :     ReadGraphicObject( rIStm, *this );
     371           0 : }
     372             : 
     373           0 : void GraphicObject::Save( SvStream& rOStm )
     374             : {
     375           0 :     WriteGraphicObject( rOStm, *this );
     376           0 : }
     377             : 
     378           0 : void GraphicObject::Assign( const SvDataCopyStream& rCopyStream )
     379             : {
     380           0 :     *this = static_cast<const GraphicObject&>(rCopyStream);
     381           0 : }
     382             : 
     383        3598 : OString GraphicObject::GetUniqueID() const
     384             : {
     385        3598 :     if ( !IsInSwapIn() && IsEPS() )
     386           0 :         const_cast<GraphicObject*>(this)->FireSwapInRequest();
     387             : 
     388        3598 :     OString aRet;
     389             : 
     390        3598 :     if( mpMgr )
     391        3598 :         aRet = mpMgr->ImplGetUniqueID( *this );
     392             : 
     393        3598 :     return aRet;
     394             : }
     395             : 
     396         236 : SvStream* GraphicObject::GetSwapStream() const
     397             : {
     398         236 :     if( HasSwapStreamHdl() )
     399         194 :         return reinterpret_cast<SvStream*>( mpSwapStreamHdl->Call( const_cast<void*>(reinterpret_cast<const void*>(this)) ) );
     400             :     else
     401          42 :         return GRFMGR_AUTOSWAPSTREAM_NONE;
     402             : }
     403             : 
     404         122 : void GraphicObject::SetAttr( const GraphicAttr& rAttr )
     405             : {
     406         122 :     maAttr = rAttr;
     407             : 
     408         122 :     if( mpSimpleCache && ( mpSimpleCache->maAttr != rAttr ) )
     409           0 :         delete mpSimpleCache, mpSimpleCache = NULL;
     410         122 : }
     411             : 
     412           0 : void GraphicObject::SetLink()
     413             : {
     414           0 :     maLink = "";
     415           0 : }
     416             : 
     417          16 : void GraphicObject::SetLink( const OUString& rLink )
     418             : {
     419          16 :     maLink = rLink;
     420          16 : }
     421             : 
     422        1670 : void GraphicObject::SetUserData()
     423             : {
     424        1670 :     maUserData = "";
     425        1670 : }
     426             : 
     427         108 : void GraphicObject::SetUserData( const OUString& rUserData )
     428             : {
     429         108 :     maUserData = rUserData;
     430         108 : }
     431             : 
     432           0 : void GraphicObject::SetSwapStreamHdl()
     433             : {
     434           0 :     if( mpSwapStreamHdl )
     435             :     {
     436           0 :         delete mpSwapOutTimer, mpSwapOutTimer = NULL;
     437           0 :         delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
     438             :     }
     439           0 : }
     440             : 
     441             : #define SWAPGRAPHIC_TIMEOUT     5000
     442             : 
     443             : // #i122985# it is not correct to set the swap-timeout to a hard-coded 5000ms
     444             : // as it was before.  Added code and experimented what to do as a good
     445             : // compromise, see description.
     446        3204 : static sal_uInt32 GetCacheTimeInMs()
     447             : {
     448             :     static bool bSetAtAll(true);
     449             : 
     450        3204 :     if (bSetAtAll)
     451             :     {
     452             :         static bool bSetToPreferenceTime(true);
     453             : 
     454        3204 :         if (bSetToPreferenceTime)
     455             :         {
     456             :             const sal_uInt32 nSeconds =
     457             :                 officecfg::Office::Common::Cache::GraphicManager::ObjectReleaseTime::get(
     458        3204 :                     comphelper::getProcessComponentContext());
     459             : 
     460             : 
     461             :             // The default is 10 minutes. The minimum is one minute, thus 60
     462             :             // seconds. When the minimum should match to the former hard-coded
     463             :             // 5 seconds, we have a divisor of 12 to use. For the default of 10
     464             :             // minutes this would mean 50 seconds. Compared to before this is
     465             :             // ten times more (would allow better navigation by switching
     466             :             // through pages) and is controllable by the user by setting the
     467             :             // tools/options/memory/Remove_from_memory_after setting. Seems to
     468             :             // be a good compromise to me.
     469        3204 :             return nSeconds * 1000 / 12;
     470             :         }
     471             :         else
     472             :         {
     473           0 :             return SWAPGRAPHIC_TIMEOUT;
     474             :         }
     475             :     }
     476             : 
     477           0 :     return 0;
     478             : }
     479             : 
     480        3204 : void GraphicObject::SetSwapStreamHdl(const Link& rHdl)
     481             : {
     482        3204 :     delete mpSwapStreamHdl, mpSwapStreamHdl = new Link( rHdl );
     483             : 
     484        3204 :     sal_uInt32 const nSwapOutTimeout(GetCacheTimeInMs());
     485        3204 :     if( nSwapOutTimeout )
     486             :     {
     487        3204 :         if( !mpSwapOutTimer )
     488             :         {
     489        2316 :             mpSwapOutTimer = new Timer;
     490        2316 :             mpSwapOutTimer->SetTimeoutHdl( LINK( this, GraphicObject, ImplAutoSwapOutHdl ) );
     491             :         }
     492             : 
     493        3204 :         mpSwapOutTimer->SetTimeout( nSwapOutTimeout );
     494        3204 :         mpSwapOutTimer->Start();
     495             :     }
     496             :     else
     497           0 :         delete mpSwapOutTimer, mpSwapOutTimer = NULL;
     498        3204 : }
     499             : 
     500         910 : void GraphicObject::FireSwapInRequest()
     501             : {
     502         910 :     ImplAutoSwapIn();
     503         910 : }
     504             : 
     505         204 : void GraphicObject::FireSwapOutRequest()
     506             : {
     507         204 :     ImplAutoSwapOutHdl( NULL );
     508         204 : }
     509             : 
     510           0 : void GraphicObject::GraphicManagerDestroyed()
     511             : {
     512             :     // we're alive, but our manager doesn't live anymore ==> connect to default manager
     513           0 :     mpMgr = NULL;
     514           0 :     ImplSetGraphicManager( NULL );
     515           0 : }
     516             : 
     517           4 : bool GraphicObject::IsCached( OutputDevice* pOut, const Point& rPt, const Size& rSz,
     518             :                               const GraphicAttr* pAttr, sal_uLong nFlags ) const
     519             : {
     520             :     bool bRet;
     521             : 
     522           4 :     if( nFlags & GRFMGR_DRAW_CACHED )
     523             :     {
     524           4 :         Point aPt( rPt );
     525           4 :         Size aSz( rSz );
     526           4 :         if ( pAttr && pAttr->IsCropped() )
     527             :         {
     528           4 :             tools::PolyPolygon aClipPolyPoly;
     529             :             bool        bRectClip;
     530           4 :             ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip );
     531             :         }
     532           4 :         bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
     533             :     }
     534             :     else
     535           0 :         bRet = false;
     536             : 
     537           4 :     return bRet;
     538             : }
     539             : 
     540         162 : void GraphicObject::ReleaseFromCache()
     541             : {
     542             : 
     543         162 :     mpMgr->ReleaseFromCache( *this );
     544         162 : }
     545             : 
     546           0 : bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz,
     547             :                           const GraphicAttr* pAttr, sal_uLong nFlags )
     548             : {
     549           0 :     GraphicAttr         aAttr( pAttr ? *pAttr : GetAttr() );
     550           0 :     Point               aPt( rPt );
     551           0 :     Size                aSz( rSz );
     552           0 :     const sal_uInt32    nOldDrawMode = pOut->GetDrawMode();
     553           0 :     bool                bCropped = aAttr.IsCropped();
     554           0 :     bool                bCached = false;
     555             :     bool bRet;
     556             : 
     557             :     // #i29534# Provide output rects for PDF writer
     558           0 :     Rectangle           aCropRect;
     559             : 
     560           0 :     if( !( GRFMGR_DRAW_USE_DRAWMODE_SETTINGS & nFlags ) )
     561           0 :         pOut->SetDrawMode( nOldDrawMode & ( ~( DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ) ) );
     562             : 
     563             :     // mirrored horizontically
     564           0 :     if( aSz.Width() < 0L )
     565             :     {
     566           0 :         aPt.X() += aSz.Width() + 1;
     567           0 :         aSz.Width() = -aSz.Width();
     568           0 :         aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_HORZ );
     569             :     }
     570             : 
     571             :     // mirrored vertically
     572           0 :     if( aSz.Height() < 0L )
     573             :     {
     574           0 :         aPt.Y() += aSz.Height() + 1;
     575           0 :         aSz.Height() = -aSz.Height();
     576           0 :         aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_VERT );
     577             :     }
     578             : 
     579           0 :     if( bCropped )
     580             :     {
     581           0 :         tools::PolyPolygon aClipPolyPoly;
     582             :         bool        bRectClip;
     583           0 :         const bool  bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
     584             : 
     585           0 :         pOut->Push( PushFlags::CLIPREGION );
     586             : 
     587           0 :         if( bCrop )
     588             :         {
     589           0 :             if( bRectClip )
     590             :             {
     591             :                 // #i29534# Store crop rect for later forwarding to
     592             :                 // PDF writer
     593           0 :                 aCropRect = aClipPolyPoly.GetBoundRect();
     594           0 :                 pOut->IntersectClipRegion( aCropRect );
     595             :             }
     596             :             else
     597             :             {
     598           0 :                 pOut->IntersectClipRegion(vcl::Region(aClipPolyPoly));
     599             :             }
     600           0 :         }
     601             :     }
     602             : 
     603           0 :     bRet = mpMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached );
     604             : 
     605           0 :     if( bCropped )
     606           0 :         pOut->Pop();
     607             : 
     608           0 :     pOut->SetDrawMode( nOldDrawMode );
     609             : 
     610             :     // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins
     611             :     // (code above needs to call GetGraphic twice)
     612           0 :     if( bCached )
     613             :     {
     614           0 :         if( mpSwapOutTimer )
     615           0 :             mpSwapOutTimer->Start();
     616             :         else
     617           0 :             FireSwapOutRequest();
     618             :     }
     619             : 
     620           0 :     return bRet;
     621             : }
     622             : 
     623             : // #i105243#
     624           0 : bool GraphicObject::DrawWithPDFHandling( OutputDevice& rOutDev,
     625             :                                          const Point& rPt, const Size& rSz,
     626             :                                          const GraphicAttr* pGrfAttr,
     627             :                                          const sal_uLong nFlags )
     628             : {
     629           0 :     const GraphicAttr aGrfAttr( pGrfAttr ? *pGrfAttr : GetAttr() );
     630             : 
     631             :     // Notify PDF writer about linked graphic (if any)
     632           0 :     bool bWritingPdfLinkedGraphic( false );
     633           0 :     Point aPt( rPt );
     634           0 :     Size aSz( rSz );
     635           0 :     Rectangle aCropRect;
     636             :     vcl::PDFExtOutDevData* pPDFExtOutDevData =
     637           0 :             dynamic_cast<vcl::PDFExtOutDevData*>(rOutDev.GetExtOutDevData());
     638           0 :     if( pPDFExtOutDevData )
     639             :     {
     640             :         // only delegate image handling to PDF, if no special treatment is necessary
     641           0 :         if( GetGraphic().IsLink() &&
     642           0 :             rSz.Width() > 0L &&
     643           0 :             rSz.Height() > 0L &&
     644           0 :             !aGrfAttr.IsSpecialDrawMode() &&
     645           0 :             !aGrfAttr.IsMirrored() &&
     646           0 :             !aGrfAttr.IsRotated() &&
     647           0 :             !aGrfAttr.IsAdjusted() )
     648             :         {
     649           0 :             bWritingPdfLinkedGraphic = true;
     650             : 
     651           0 :             if( aGrfAttr.IsCropped() )
     652             :             {
     653           0 :                 tools::PolyPolygon aClipPolyPoly;
     654             :                 bool bRectClip;
     655             :                 const bool bCrop = ImplGetCropParams( &rOutDev,
     656             :                                                       aPt, aSz,
     657             :                                                       &aGrfAttr,
     658             :                                                       aClipPolyPoly,
     659           0 :                                                       bRectClip );
     660           0 :                 if ( bCrop && bRectClip )
     661             :                 {
     662           0 :                     aCropRect = aClipPolyPoly.GetBoundRect();
     663           0 :                 }
     664             :             }
     665             : 
     666           0 :             pPDFExtOutDevData->BeginGroup();
     667             :         }
     668             :     }
     669             : 
     670           0 :     bool bRet = Draw( &rOutDev, rPt, rSz, &aGrfAttr, nFlags );
     671             : 
     672             :     // Notify PDF writer about linked graphic (if any)
     673           0 :     if( bWritingPdfLinkedGraphic )
     674             :     {
     675           0 :         pPDFExtOutDevData->EndGroup( const_cast< Graphic& >(GetGraphic()),
     676           0 :                                      aGrfAttr.GetTransparency(),
     677             :                                      Rectangle( aPt, aSz ),
     678           0 :                                      aCropRect );
     679             :     }
     680             : 
     681           0 :     return bRet;
     682             : }
     683             : 
     684           0 : bool GraphicObject::DrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSize,
     685             :                                const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D )
     686             : {
     687           0 :     if( pOut == NULL || rSize.Width() == 0 || rSize.Height() == 0 )
     688           0 :         return false;
     689             : 
     690           0 :     const MapMode   aOutMapMode( pOut->GetMapMode() );
     691           0 :     const MapMode   aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() );
     692             :     // #106258# Clamp size to 1 for zero values. This is okay, since
     693             :     // logical size of zero is handled above already
     694           0 :     const Size      aOutTileSize( ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Width() ),
     695           0 :                                   ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Height() ) );
     696             : 
     697             :     //#i69780 clip final tile size to a sane max size
     698           0 :     while (((sal_Int64)rSize.Width() * nTileCacheSize1D) > SAL_MAX_UINT16)
     699           0 :         nTileCacheSize1D /= 2;
     700           0 :     while (((sal_Int64)rSize.Height() * nTileCacheSize1D) > SAL_MAX_UINT16)
     701           0 :         nTileCacheSize1D /= 2;
     702             : 
     703           0 :     return ImplDrawTiled( pOut, rArea, aOutTileSize, rOffset, pAttr, nFlags, nTileCacheSize1D );
     704             : }
     705             : 
     706           0 : bool GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const Size& rSz,
     707             :                                     long nExtraData, const GraphicAttr* pAttr, sal_uLong /*nFlags*/,
     708             :                                     OutputDevice* pFirstFrameOutDev )
     709             : {
     710           0 :     bool bRet = false;
     711             : 
     712           0 :     GetGraphic();
     713             : 
     714           0 :     if( !IsSwappedOut() )
     715             :     {
     716           0 :         const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
     717             : 
     718           0 :         if( mbAnimated )
     719             :         {
     720           0 :             Point   aPt( rPt );
     721           0 :             Size    aSz( rSz );
     722           0 :             bool    bCropped = aAttr.IsCropped();
     723             : 
     724           0 :             if( bCropped )
     725             :             {
     726           0 :                 tools::PolyPolygon aClipPolyPoly;
     727             :                 bool        bRectClip;
     728           0 :                 const bool  bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
     729             : 
     730           0 :                 pOut->Push( PushFlags::CLIPREGION );
     731             : 
     732           0 :                 if( bCrop )
     733             :                 {
     734           0 :                     if( bRectClip )
     735           0 :                         pOut->IntersectClipRegion( aClipPolyPoly.GetBoundRect() );
     736             :                     else
     737           0 :                         pOut->IntersectClipRegion(vcl::Region(aClipPolyPoly));
     738           0 :                 }
     739             :             }
     740             : 
     741           0 :             if( !mpSimpleCache || ( mpSimpleCache->maAttr != aAttr ) || pFirstFrameOutDev )
     742             :             {
     743           0 :                 if( mpSimpleCache )
     744           0 :                     delete mpSimpleCache;
     745             : 
     746           0 :                 mpSimpleCache = new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr ), aAttr );
     747           0 :                 mpSimpleCache->maGraphic.SetAnimationNotifyHdl( GetAnimationNotifyHdl() );
     748             :             }
     749             : 
     750           0 :             mpSimpleCache->maGraphic.StartAnimation( pOut, aPt, aSz, nExtraData, pFirstFrameOutDev );
     751             : 
     752           0 :             if( bCropped )
     753           0 :                 pOut->Pop();
     754             : 
     755           0 :             bRet = true;
     756             :         }
     757             :         else
     758           0 :             bRet = Draw( pOut, rPt, rSz, &aAttr, GRFMGR_DRAW_STANDARD );
     759             :     }
     760             : 
     761           0 :     return bRet;
     762             : }
     763             : 
     764           0 : void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData )
     765             : {
     766           0 :     if( mpSimpleCache )
     767           0 :         mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData );
     768           0 : }
     769             : 
     770       79461 : const Graphic& GraphicObject::GetGraphic() const
     771             : {
     772       79461 :     GraphicObject *pThis = const_cast<GraphicObject*>(this);
     773             : 
     774       79461 :     if (mbAutoSwapped)
     775          58 :         pThis->ImplAutoSwapIn();
     776             : 
     777             :     //fdo#50697 If we've been asked to provide the graphic, then reset
     778             :     //the cache timeout to start from now and not remain at the
     779             :     //time of creation
     780       79461 :     pThis->restartSwapOutTimer();
     781             : 
     782       79461 :     return maGraphic;
     783             : }
     784             : 
     785        2654 : void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj )
     786             : {
     787        2654 :     mpMgr->ImplUnregisterObj( *this );
     788             : 
     789        2654 :     if( mpSwapOutTimer )
     790        1634 :         mpSwapOutTimer->Stop();
     791             : 
     792        2654 :     maGraphic = rGraphic;
     793        2654 :     mbAutoSwapped = false;
     794        2654 :     ImplAssignGraphicData();
     795        2654 :     maLink = "";
     796        2654 :     delete mpSimpleCache, mpSimpleCache = NULL;
     797             : 
     798        2654 :     mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj);
     799             : 
     800        2654 :     if( mpSwapOutTimer )
     801        1634 :         mpSwapOutTimer->Start();
     802             : 
     803             :     // Handle evtl. needed AfterDataChanges
     804        2654 :     ImplAfterDataChange();
     805        2654 : }
     806             : 
     807          48 : void GraphicObject::SetGraphic( const Graphic& rGraphic, const OUString& rLink )
     808             : {
     809          48 :     SetGraphic( rGraphic );
     810          48 :     maLink = rLink;
     811          48 : }
     812             : 
     813           0 : Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMode& rDestMap, const GraphicAttr& rAttr ) const
     814             : {
     815             :     // #104550# Extracted from svx/source/svdraw/svdograf.cxx
     816           0 :     Graphic             aTransGraphic( maGraphic );
     817           0 :     const GraphicType   eType = GetType();
     818           0 :     const Size          aSrcSize( aTransGraphic.GetPrefSize() );
     819             : 
     820             :     // #104115# Convert the crop margins to graphic object mapmode
     821           0 :     const MapMode aMapGraph( aTransGraphic.GetPrefMapMode() );
     822           0 :     const MapMode aMap100( MAP_100TH_MM );
     823             : 
     824           0 :     Size aCropLeftTop;
     825           0 :     Size aCropRightBottom;
     826             : 
     827           0 :     if( GRAPHIC_GDIMETAFILE == eType )
     828             :     {
     829           0 :         GDIMetaFile aMtf( aTransGraphic.GetGDIMetaFile() );
     830             : 
     831           0 :         if( aMapGraph == MAP_PIXEL )
     832             :         {
     833             :             // crops are in 1/100th mm -> to aMapGraph -> to MAP_PIXEL
     834             :             aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
     835             :                 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
     836           0 :                 aMap100);
     837             :             aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
     838             :                 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
     839           0 :                 aMap100);
     840             :         }
     841             :         else
     842             :         {
     843             :             // crops are in GraphicObject units -> to aMapGraph
     844             :             aCropLeftTop = OutputDevice::LogicToLogic(
     845             :                 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
     846             :                 aMap100,
     847           0 :                 aMapGraph);
     848             :             aCropRightBottom = OutputDevice::LogicToLogic(
     849             :                 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
     850             :                 aMap100,
     851           0 :                 aMapGraph);
     852             :         }
     853             : 
     854             :         // #104115# If the metafile is cropped, give it a special
     855             :         // treatment: clip against the remaining area, scale up such
     856             :         // that this area later fills the desired size, and move the
     857             :         // origin to the upper left edge of that area.
     858           0 :         if( rAttr.IsCropped() )
     859             :         {
     860           0 :             const MapMode aMtfMapMode( aMtf.GetPrefMapMode() );
     861             : 
     862           0 :             Rectangle aClipRect( aMtfMapMode.GetOrigin().X() + aCropLeftTop.Width(),
     863           0 :                                  aMtfMapMode.GetOrigin().Y() + aCropLeftTop.Height(),
     864           0 :                                  aMtfMapMode.GetOrigin().X() + aSrcSize.Width() - aCropRightBottom.Width(),
     865           0 :                                  aMtfMapMode.GetOrigin().Y() + aSrcSize.Height() - aCropRightBottom.Height() );
     866             : 
     867             :             // #104115# To correctly crop rotated metafiles, clip by view rectangle
     868           0 :             aMtf.AddAction( new MetaISectRectClipRegionAction( aClipRect ), 0 );
     869             : 
     870             :             // #104115# To crop the metafile, scale larger than the output rectangle
     871           0 :             aMtf.Scale( (double)rDestSize.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()),
     872           0 :                         (double)rDestSize.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) );
     873             : 
     874             :             // #104115# Adapt the pref size by hand (scale changes it
     875             :             // proportionally, but we want it to be smaller than the
     876             :             // former size, to crop the excess out)
     877           0 :             aMtf.SetPrefSize( Size( (long)((double)rDestSize.Width() *  (1.0 + (aCropLeftTop.Width() + aCropRightBottom.Width()) / aSrcSize.Width())  + .5),
     878           0 :                                     (long)((double)rDestSize.Height() * (1.0 + (aCropLeftTop.Height() + aCropRightBottom.Height()) / aSrcSize.Height()) + .5) ) );
     879             : 
     880             :             // #104115# Adapt the origin of the new mapmode, such that it
     881             :             // is shifted to the place where the cropped output starts
     882           0 :             Point aNewOrigin( (long)((double)aMtfMapMode.GetOrigin().X() + rDestSize.Width() * aCropLeftTop.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()) + .5),
     883           0 :                               (long)((double)aMtfMapMode.GetOrigin().Y() + rDestSize.Height() * aCropLeftTop.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) + .5) );
     884           0 :             MapMode aNewMap( rDestMap );
     885           0 :             aNewMap.SetOrigin( OutputDevice::LogicToLogic(aNewOrigin, aMtfMapMode, rDestMap) );
     886           0 :             aMtf.SetPrefMapMode( aNewMap );
     887             :         }
     888             :         else
     889             :         {
     890           0 :             aMtf.Scale( Fraction( rDestSize.Width(), aSrcSize.Width() ), Fraction( rDestSize.Height(), aSrcSize.Height() ) );
     891           0 :             aMtf.SetPrefMapMode( rDestMap );
     892             :         }
     893             : 
     894           0 :         aTransGraphic = aMtf;
     895             :     }
     896           0 :     else if( GRAPHIC_BITMAP == eType )
     897             :     {
     898           0 :         BitmapEx aBitmapEx( aTransGraphic.GetBitmapEx() );
     899           0 :         Rectangle aCropRect;
     900             : 
     901             :         // convert crops to pixel
     902           0 :         if(rAttr.IsCropped())
     903             :         {
     904           0 :             if( aMapGraph == MAP_PIXEL )
     905             :             {
     906             :                 // crops are in 1/100th mm -> to MAP_PIXEL
     907             :                 aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
     908             :                     Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
     909           0 :                     aMap100);
     910             :                 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
     911             :                     Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
     912           0 :                     aMap100);
     913             :             }
     914             :             else
     915             :             {
     916             :                 // crops are in GraphicObject units -> to MAP_PIXEL
     917             :                 aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
     918             :                     Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
     919           0 :                     aMapGraph);
     920             :                 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
     921             :                     Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
     922           0 :                     aMapGraph);
     923             :             }
     924             : 
     925             :             // convert from prefmapmode to pixel
     926             :             Size aSrcSizePixel(
     927             :                 Application::GetDefaultDevice()->LogicToPixel(
     928             :                     aSrcSize,
     929           0 :                     aMapGraph));
     930             : 
     931           0 :             if(rAttr.IsCropped()
     932           0 :                 && (aSrcSizePixel.Width() != aBitmapEx.GetSizePixel().Width() || aSrcSizePixel.Height() != aBitmapEx.GetSizePixel().Height())
     933           0 :                 && aSrcSizePixel.Width())
     934             :             {
     935             :                 // the size in pixels calculated from Graphic's internal MapMode (aTransGraphic.GetPrefMapMode())
     936             :                 // and it's internal size (aTransGraphic.GetPrefSize()) is different from it's real pixel size.
     937             :                 // This can be interpreted as this values to be set wrong, but needs to be corrected since e.g.
     938             :                 // existing cropping is calculated based on this logic values already.
     939             :                 // aBitmapEx.Scale(aSrcSizePixel);
     940             : 
     941             :                 // another possibility is to adapt the values created so far with a factor; this
     942             :                 // will keep the original Bitmap untouched and thus quality will not change
     943             :                 // caution: convert to double first, else pretty big errors may occur
     944           0 :                 const double fFactorX((double)aBitmapEx.GetSizePixel().Width() / aSrcSizePixel.Width());
     945           0 :                 const double fFactorY((double)aBitmapEx.GetSizePixel().Height() / aSrcSizePixel.Height());
     946             : 
     947           0 :                 aCropLeftTop.Width() = basegfx::fround(aCropLeftTop.Width() * fFactorX);
     948           0 :                 aCropLeftTop.Height() = basegfx::fround(aCropLeftTop.Height() * fFactorY);
     949           0 :                 aCropRightBottom.Width() = basegfx::fround(aCropRightBottom.Width() * fFactorX);
     950           0 :                 aCropRightBottom.Height() = basegfx::fround(aCropRightBottom.Height() * fFactorY);
     951             : 
     952           0 :                 aSrcSizePixel = aBitmapEx.GetSizePixel();
     953             :             }
     954             : 
     955             :             // setup crop rectangle in pixel
     956           0 :             aCropRect = Rectangle( aCropLeftTop.Width(), aCropLeftTop.Height(),
     957           0 :                                  aSrcSizePixel.Width() - aCropRightBottom.Width(),
     958           0 :                                  aSrcSizePixel.Height() - aCropRightBottom.Height() );
     959             :         }
     960             : 
     961             :         // #105641# Also crop animations
     962           0 :         if( aTransGraphic.IsAnimated() )
     963             :         {
     964             :             sal_uInt16 nFrame;
     965           0 :             Animation aAnim( aTransGraphic.GetAnimation() );
     966             : 
     967           0 :             for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
     968             :             {
     969           0 :                 AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
     970             : 
     971           0 :                 if( !aCropRect.IsInside( Rectangle(aAnimBmp.aPosPix, aAnimBmp.aSizePix) ) )
     972             :                 {
     973             :                     // setup actual cropping (relative to frame position)
     974           0 :                     Rectangle aCropRectRel( aCropRect );
     975           0 :                     aCropRectRel.Move( -aAnimBmp.aPosPix.X(),
     976           0 :                                        -aAnimBmp.aPosPix.Y() );
     977             : 
     978             :                     // cropping affects this frame, apply it then
     979             :                     // do _not_ apply enlargement, this is done below
     980             :                     ImplTransformBitmap( aAnimBmp.aBmpEx, rAttr, Size(), Size(),
     981           0 :                                          aCropRectRel, rDestSize, false );
     982             : 
     983           0 :                     aAnim.Replace( aAnimBmp, nFrame );
     984             :                 }
     985             :                 // else: bitmap completely within crop area,
     986             :                 // i.e. nothing is cropped away
     987           0 :             }
     988             : 
     989             :             // now, apply enlargement (if any) through global animation size
     990           0 :             if( aCropLeftTop.Width() < 0 ||
     991           0 :                 aCropLeftTop.Height() < 0 ||
     992           0 :                 aCropRightBottom.Width() < 0 ||
     993           0 :                 aCropRightBottom.Height() < 0 )
     994             :             {
     995           0 :                 Size aNewSize( aAnim.GetDisplaySizePixel() );
     996           0 :                 aNewSize.Width() += aCropRightBottom.Width() < 0 ? -aCropRightBottom.Width() : 0;
     997           0 :                 aNewSize.Width() += aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0;
     998           0 :                 aNewSize.Height() += aCropRightBottom.Height() < 0 ? -aCropRightBottom.Height() : 0;
     999           0 :                 aNewSize.Height() += aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0;
    1000           0 :                 aAnim.SetDisplaySizePixel( aNewSize );
    1001             :             }
    1002             : 
    1003             :             // if topleft has changed, we must move all frames to the
    1004             :             // right and bottom, resp.
    1005           0 :             if( aCropLeftTop.Width() < 0 ||
    1006           0 :                 aCropLeftTop.Height() < 0 )
    1007             :             {
    1008           0 :                 Point aPosOffset( aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0,
    1009           0 :                                   aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0 );
    1010             : 
    1011           0 :                 for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
    1012             :                 {
    1013           0 :                     AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
    1014             : 
    1015           0 :                     aAnimBmp.aPosPix += aPosOffset;
    1016             : 
    1017           0 :                     aAnim.Replace( aAnimBmp, nFrame );
    1018           0 :                 }
    1019             :             }
    1020             : 
    1021           0 :             aTransGraphic = aAnim;
    1022             :         }
    1023             :         else
    1024             :         {
    1025             :             ImplTransformBitmap( aBitmapEx, rAttr, aCropLeftTop, aCropRightBottom,
    1026           0 :                                  aCropRect, rDestSize, true );
    1027             : 
    1028           0 :             aTransGraphic = aBitmapEx;
    1029             :         }
    1030             : 
    1031           0 :         aTransGraphic.SetPrefSize( rDestSize );
    1032           0 :         aTransGraphic.SetPrefMapMode( rDestMap );
    1033             :     }
    1034             : 
    1035           0 :     GraphicObject aGrfObj( aTransGraphic );
    1036           0 :     aTransGraphic = aGrfObj.GetTransformedGraphic( &rAttr );
    1037             : 
    1038           0 :     return aTransGraphic;
    1039             : }
    1040             : 
    1041         300 : Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl
    1042             : {
    1043         300 :     GetGraphic();
    1044             : 
    1045         300 :     Graphic     aGraphic;
    1046         600 :     GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
    1047             : 
    1048         300 :     if( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() )
    1049             :     {
    1050         300 :         if( aAttr.IsSpecialDrawMode() || aAttr.IsAdjusted() || aAttr.IsMirrored() || aAttr.IsRotated() || aAttr.IsTransparent() )
    1051             :         {
    1052           0 :             if( GetType() == GRAPHIC_BITMAP )
    1053             :             {
    1054           0 :                 if( IsAnimated() )
    1055             :                 {
    1056           0 :                     Animation aAnimation( maGraphic.GetAnimation() );
    1057           0 :                     GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL );
    1058           0 :                     aAnimation.SetLoopCount( mnAnimationLoopCount );
    1059           0 :                     aGraphic = aAnimation;
    1060             :                 }
    1061             :                 else
    1062             :                 {
    1063           0 :                     BitmapEx aBmpEx( maGraphic.GetBitmapEx() );
    1064           0 :                     GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL );
    1065           0 :                     aGraphic = aBmpEx;
    1066             :                 }
    1067             :             }
    1068             :             else
    1069             :             {
    1070           0 :                 GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() );
    1071           0 :                 GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL );
    1072           0 :                 aGraphic = aMtf;
    1073             :             }
    1074             :         }
    1075             :         else
    1076             :         {
    1077         300 :             if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() )
    1078             :             {
    1079           0 :                 Animation aAnimation( maGraphic.GetAnimation() );
    1080           0 :                 aAnimation.SetLoopCount( mnAnimationLoopCount );
    1081           0 :                 aGraphic = aAnimation;
    1082             :             }
    1083             :             else
    1084         300 :                 aGraphic = maGraphic;
    1085             :         }
    1086             :     }
    1087             : 
    1088         600 :     return aGraphic;
    1089             : }
    1090             : 
    1091          68 : bool GraphicObject::SwapOut()
    1092             : {
    1093          68 :     const bool bRet = !mbAutoSwapped && maGraphic.SwapOut();
    1094             : 
    1095          68 :     if( bRet && mpMgr )
    1096          68 :         mpMgr->ImplGraphicObjectWasSwappedOut( *this );
    1097             : 
    1098          68 :     return bRet;
    1099             : }
    1100             : 
    1101           4 : bool GraphicObject::SwapOut( SvStream* pOStm )
    1102             : {
    1103           4 :     const bool bRet = !mbAutoSwapped && maGraphic.SwapOut( pOStm );
    1104             : 
    1105           4 :     if( bRet && mpMgr )
    1106           4 :         mpMgr->ImplGraphicObjectWasSwappedOut( *this );
    1107             : 
    1108           4 :     return bRet;
    1109             : }
    1110             : 
    1111           8 : bool GraphicObject::SwapIn()
    1112             : {
    1113           8 :     bool bRet = false;
    1114             : 
    1115           8 :     if( mbAutoSwapped )
    1116             :     {
    1117           0 :         ImplAutoSwapIn();
    1118           0 :         bRet = true;
    1119             :     }
    1120           8 :     else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
    1121             :     {
    1122           2 :         bRet = true;
    1123             :     }
    1124             :     else
    1125             :     {
    1126           6 :         bRet = maGraphic.SwapIn();
    1127             : 
    1128           6 :         if( bRet && mpMgr )
    1129           6 :             mpMgr->ImplGraphicObjectWasSwappedIn( *this );
    1130             :     }
    1131             : 
    1132           8 :     if( bRet )
    1133             :     {
    1134           8 :         ImplAssignGraphicData();
    1135             : 
    1136             :         // Handle evtl. needed AfterDataChanges
    1137           8 :         ImplAfterDataChange();
    1138             :     }
    1139             : 
    1140           8 :     return bRet;
    1141             : }
    1142             : 
    1143         112 : void GraphicObject::SetSwapState()
    1144             : {
    1145         112 :     if( !IsSwappedOut() )
    1146             :     {
    1147         112 :         mbAutoSwapped = true;
    1148             : 
    1149         112 :         if( mpMgr )
    1150         112 :             mpMgr->ImplGraphicObjectWasSwappedOut( *this );
    1151             :     }
    1152         112 : }
    1153             : 
    1154         204 : IMPL_LINK_NOARG(GraphicObject, ImplAutoSwapOutHdl)
    1155             : {
    1156         204 :     if( !IsSwappedOut() )
    1157             :     {
    1158         176 :         mbIsInSwapOut = true;
    1159             : 
    1160         176 :         SvStream* pStream = GetSwapStream();
    1161             : 
    1162         176 :         if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
    1163             :         {
    1164          60 :             if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
    1165           0 :                 mbAutoSwapped = SwapOut( NULL );
    1166             :             else
    1167             :             {
    1168          60 :                 if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
    1169          60 :                     mbAutoSwapped = SwapOut();
    1170             :                 else
    1171             :                 {
    1172           0 :                     mbAutoSwapped = SwapOut( pStream );
    1173           0 :                     delete pStream;
    1174             :                 }
    1175             :             }
    1176             :         }
    1177             : 
    1178         176 :         mbIsInSwapOut = false;
    1179             :     }
    1180             : 
    1181         204 :     if( mpSwapOutTimer )
    1182         204 :         mpSwapOutTimer->Start();
    1183             : 
    1184         204 :     return 0L;
    1185             : }
    1186             : 
    1187           0 : SvStream& ReadGraphicObject( SvStream& rIStm, GraphicObject& rGraphicObj )
    1188             : {
    1189           0 :     VersionCompat   aCompat( rIStm, STREAM_READ );
    1190           0 :     Graphic         aGraphic;
    1191           0 :     GraphicAttr     aAttr;
    1192             :     bool            bLink;
    1193             : 
    1194           0 :     ReadGraphic( rIStm, aGraphic );
    1195           0 :     ReadGraphicAttr( rIStm, aAttr );
    1196           0 :     rIStm.ReadCharAsBool( bLink );
    1197             : 
    1198           0 :     rGraphicObj.SetGraphic( aGraphic );
    1199           0 :     rGraphicObj.SetAttr( aAttr );
    1200             : 
    1201           0 :     if( bLink )
    1202             :     {
    1203           0 :         OUString aLink = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStm, RTL_TEXTENCODING_UTF8);
    1204           0 :         rGraphicObj.SetLink(aLink);
    1205             :     }
    1206             :     else
    1207           0 :         rGraphicObj.SetLink();
    1208             : 
    1209           0 :     rGraphicObj.SetSwapStreamHdl();
    1210             : 
    1211           0 :     return rIStm;
    1212             : }
    1213             : 
    1214           0 : SvStream& WriteGraphicObject( SvStream& rOStm, const GraphicObject& rGraphicObj )
    1215             : {
    1216           0 :     VersionCompat   aCompat( rOStm, STREAM_WRITE, 1 );
    1217           0 :     const bool      bLink =  rGraphicObj.HasLink();
    1218             : 
    1219           0 :     WriteGraphic( rOStm, rGraphicObj.GetGraphic() );
    1220           0 :     WriteGraphicAttr( rOStm, rGraphicObj.GetAttr() );
    1221           0 :     rOStm.WriteUChar( bLink );
    1222             : 
    1223           0 :     if( bLink )
    1224           0 :         write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8);
    1225             : 
    1226           0 :     return rOStm;
    1227             : }
    1228             : 
    1229             : #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
    1230             : 
    1231         736 : GraphicObject GraphicObject::CreateGraphicObjectFromURL( const OUString &rURL )
    1232             : {
    1233        1472 :     const OUString aURL( rURL ), aPrefix( UNO_NAME_GRAPHOBJ_URLPREFIX );
    1234         736 :     if( aURL.startsWith( aPrefix ) )
    1235             :     {
    1236             :         // graphic manager url
    1237         724 :         OString aUniqueID(OUStringToOString(rURL.copy(sizeof(UNO_NAME_GRAPHOBJ_URLPREFIX) - 1), RTL_TEXTENCODING_UTF8));
    1238         724 :         return GraphicObject( aUniqueID );
    1239             :     }
    1240             :     else
    1241             :     {
    1242          12 :         Graphic     aGraphic;
    1243          12 :         if ( !aURL.isEmpty() )
    1244             :         {
    1245          12 :             boost::scoped_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( aURL, STREAM_READ ));
    1246          12 :             if( pStream )
    1247           0 :                 GraphicConverter::Import( *pStream, aGraphic );
    1248             :         }
    1249             : 
    1250          12 :         return GraphicObject( aGraphic );
    1251         736 :     }
    1252             : }
    1253             : 
    1254             : void
    1255           4 : GraphicObject::InspectForGraphicObjectImageURL( const Reference< XInterface >& xIf,  std::vector< OUString >& rvEmbedImgUrls )
    1256             : {
    1257           4 :     static OUString sImageURL( "ImageURL" );
    1258           4 :     Reference< XPropertySet > xProps( xIf, UNO_QUERY );
    1259           4 :     if ( xProps.is() )
    1260             :     {
    1261             : 
    1262           4 :         if ( xProps->getPropertySetInfo()->hasPropertyByName( sImageURL ) )
    1263             :         {
    1264           2 :             OUString sURL;
    1265           2 :             xProps->getPropertyValue( sImageURL ) >>= sURL;
    1266           2 :             if ( !sURL.isEmpty() && sURL.startsWith( UNO_NAME_GRAPHOBJ_URLPREFIX ) )
    1267           0 :                 rvEmbedImgUrls.push_back( sURL );
    1268             :         }
    1269             :     }
    1270           8 :     Reference< XNameContainer > xContainer( xIf, UNO_QUERY );
    1271           4 :     if ( xContainer.is() )
    1272             :     {
    1273           2 :         Sequence< OUString > sNames = xContainer->getElementNames();
    1274           2 :         sal_Int32 nContainees = sNames.getLength();
    1275           4 :         for ( sal_Int32 index = 0; index < nContainees; ++index )
    1276             :         {
    1277           2 :             Reference< XInterface > xCtrl;
    1278           2 :             xContainer->getByName( sNames[ index ] ) >>= xCtrl;
    1279           2 :             InspectForGraphicObjectImageURL( xCtrl, rvEmbedImgUrls );
    1280           4 :         }
    1281           4 :     }
    1282           4 : }
    1283             : 
    1284             : // calculate scalings between real image size and logic object size. This
    1285             : // is necessary since the crop values are relative to original bitmap size
    1286           4 : basegfx::B2DVector GraphicObject::calculateCropScaling(
    1287             :     double fWidth,
    1288             :     double fHeight,
    1289             :     double fLeftCrop,
    1290             :     double fTopCrop,
    1291             :     double fRightCrop,
    1292             :     double fBottomCrop) const
    1293             : {
    1294           4 :     const MapMode aMapMode100thmm(MAP_100TH_MM);
    1295           4 :     Size aBitmapSize(GetPrefSize());
    1296           4 :     double fFactorX(1.0);
    1297           4 :     double fFactorY(1.0);
    1298             : 
    1299           4 :     if(MAP_PIXEL == GetPrefMapMode().GetMapUnit())
    1300             :     {
    1301           2 :         aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm);
    1302             :     }
    1303             :     else
    1304             :     {
    1305           2 :         aBitmapSize = OutputDevice::LogicToLogic(aBitmapSize, GetPrefMapMode(), aMapMode100thmm);
    1306             :     }
    1307             : 
    1308           4 :     const double fDivX(aBitmapSize.Width() - fLeftCrop - fRightCrop);
    1309           4 :     const double fDivY(aBitmapSize.Height() - fTopCrop - fBottomCrop);
    1310             : 
    1311           4 :     if(!basegfx::fTools::equalZero(fDivX))
    1312             :     {
    1313           4 :         fFactorX = fabs(fWidth) / fDivX;
    1314             :     }
    1315             : 
    1316           4 :     if(!basegfx::fTools::equalZero(fDivY))
    1317             :     {
    1318           4 :         fFactorY = fabs(fHeight) / fDivY;
    1319             :     }
    1320             : 
    1321           4 :     return basegfx::B2DVector(fFactorX,fFactorY);
    1322             : }
    1323             : 
    1324             : // restart SwapOut timer
    1325       79461 : void GraphicObject::restartSwapOutTimer() const
    1326             : {
    1327       79461 :     if( mpSwapOutTimer && mpSwapOutTimer->IsActive() )
    1328             :     {
    1329        6528 :         mpSwapOutTimer->Stop();
    1330        6528 :         mpSwapOutTimer->Start();
    1331             :     }
    1332       80688 : }
    1333             : 
    1334             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10