LCOV - code coverage report
Current view: top level - svtools/source/graphic - grfcache.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 273 537 50.8 %
Date: 2014-11-03 Functions: 33 52 63.5 %
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 <cstdlib>
      23             : 
      24             : #include <salhelper/timer.hxx>
      25             : #include <svtools/grfmgr.hxx>
      26             : #include <tools/debug.hxx>
      27             : #include <vcl/metaact.hxx>
      28             : #include <vcl/outdev.hxx>
      29             : #include <tools/poly.hxx>
      30             : #include <rtl/strbuf.hxx>
      31             : #include "grfcache.hxx"
      32             : #include <rtl/crc.h>
      33             : #include <boost/scoped_ptr.hpp>
      34             : 
      35             : #define RELEASE_TIMEOUT 10000
      36             : #define MAX_BMP_EXTENT  4096
      37             : 
      38             : static const char aHexData[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
      39             : 
      40             : class GraphicID
      41             : {
      42             : private:
      43             : 
      44             :     sal_uInt32  mnID1;
      45             :     sal_uInt32  mnID2;
      46             :     sal_uInt32  mnID3;
      47             :     sal_uInt32  mnID4;
      48             : 
      49             : public:
      50             : 
      51             : 
      52             :                 GraphicID( const GraphicObject& rObj );
      53       28008 :                 ~GraphicID() {}
      54             : 
      55       26212 :     bool        operator==( const GraphicID& rID ) const
      56             :                 {
      57       34438 :                     return( rID.mnID1 == mnID1 && rID.mnID2 == mnID2 &&
      58       32526 :                             rID.mnID3 == mnID3 && rID.mnID4 == mnID4 );
      59             :                 }
      60             : 
      61             :     OString GetIDString() const;
      62        3646 :     bool        IsEmpty() const { return( 0 == mnID4 ); }
      63             : };
      64             : 
      65       28201 : GraphicID::GraphicID( const GraphicObject& rObj )
      66             : {
      67       28201 :     const Graphic& rGraphic = rObj.GetGraphic();
      68             : 
      69       28201 :     mnID1 = ( (sal_uLong) rGraphic.GetType() ) << 28;
      70             : 
      71       28201 :     switch( rGraphic.GetType() )
      72             :     {
      73             :         case( GRAPHIC_BITMAP ):
      74             :         {
      75        4293 :             if(rGraphic.getSvgData().get())
      76             :             {
      77          14 :                 const SvgDataPtr& rSvgDataPtr = rGraphic.getSvgData();
      78          14 :                 const basegfx::B2DRange& rRange = rSvgDataPtr->getRange();
      79             : 
      80          14 :                 mnID1 |= rSvgDataPtr->getSvgDataArrayLength();
      81          14 :                 mnID2 = basegfx::fround(rRange.getWidth());
      82          14 :                 mnID3 = basegfx::fround(rRange.getHeight());
      83          14 :                 mnID4 = rtl_crc32(0, rSvgDataPtr->getSvgDataArray().get(), rSvgDataPtr->getSvgDataArrayLength());
      84             :             }
      85        4279 :             else if( rGraphic.IsAnimated() )
      86             :             {
      87           0 :                 const Animation aAnimation( rGraphic.GetAnimation() );
      88             : 
      89           0 :                 mnID1 |= ( aAnimation.Count() & 0x0fffffff );
      90           0 :                 mnID2 = aAnimation.GetDisplaySizePixel().Width();
      91           0 :                 mnID3 = aAnimation.GetDisplaySizePixel().Height();
      92           0 :                 mnID4 = rGraphic.GetChecksum();
      93             :             }
      94             :             else
      95             :             {
      96        4279 :                 const BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
      97             : 
      98        4279 :                 mnID1 |= ( ( ( (sal_uLong) aBmpEx.GetTransparentType() << 8 ) | ( aBmpEx.IsAlpha() ? 1 : 0 ) ) & 0x0fffffff );
      99        4279 :                 mnID2 = aBmpEx.GetSizePixel().Width();
     100        4279 :                 mnID3 = aBmpEx.GetSizePixel().Height();
     101        4279 :                 mnID4 = rGraphic.GetChecksum();
     102             :             }
     103             :         }
     104        4293 :         break;
     105             : 
     106             :         case( GRAPHIC_GDIMETAFILE ):
     107             :         {
     108        1654 :             const GDIMetaFile& rMtf = rGraphic.GetGDIMetaFile();
     109             : 
     110        1654 :             mnID1 |= ( rMtf.GetActionSize() & 0x0fffffff );
     111        1654 :             mnID2 = rMtf.GetPrefSize().Width();
     112        1654 :             mnID3 = rMtf.GetPrefSize().Height();
     113        1654 :             mnID4 = rGraphic.GetChecksum();
     114             :         }
     115        1654 :         break;
     116             : 
     117             :         default:
     118       22254 :             mnID2 = mnID3 = mnID4 = 0;
     119       22254 :         break;
     120             :     }
     121       28201 : }
     122             : 
     123       46496 : OString GraphicID::GetIDString() const
     124             : {
     125       46496 :     OStringBuffer aHexStr;
     126       46496 :     sal_Int32 nShift, nIndex = 0;
     127       46496 :     aHexStr.setLength(32);
     128             : 
     129      418464 :     for( nShift = 28; nShift >= 0; nShift -= 4 )
     130      371968 :         aHexStr[nIndex++] = aHexData[ ( mnID1 >> (sal_uInt32) nShift ) & 0xf ];
     131             : 
     132      418464 :     for( nShift = 28; nShift >= 0; nShift -= 4 )
     133      371968 :         aHexStr[nIndex++] = aHexData[ ( mnID2 >> (sal_uInt32) nShift ) & 0xf ];
     134             : 
     135      418464 :     for( nShift = 28; nShift >= 0; nShift -= 4 )
     136      371968 :         aHexStr[nIndex++] = aHexData[ ( mnID3 >> (sal_uInt32) nShift ) & 0xf ];
     137             : 
     138      418464 :     for( nShift = 28; nShift >= 0; nShift -= 4 )
     139      371968 :         aHexStr[nIndex++] = aHexData[ ( mnID4 >> (sal_uInt32) nShift ) & 0xf ];
     140             : 
     141       46496 :     return aHexStr.makeStringAndClear();
     142             : }
     143             : 
     144             : class GraphicCacheEntry
     145             : {
     146             : private:
     147             : 
     148             :     GraphicObjectList_impl  maGraphicObjectList;
     149             : 
     150             :     GraphicID           maID;
     151             :     GfxLink             maGfxLink;
     152             :     BitmapEx*           mpBmpEx;
     153             :     GDIMetaFile*        mpMtf;
     154             :     Animation*          mpAnimation;
     155             :     bool                mbSwappedAll;
     156             : 
     157             :     // SvgData support
     158             :     SvgDataPtr          maSvgData;
     159             : 
     160             :     bool                ImplInit( const GraphicObject& rObj );
     161             :     void                ImplFillSubstitute( Graphic& rSubstitute );
     162             : 
     163             : public:
     164             : 
     165             :                         GraphicCacheEntry( const GraphicObject& rObj );
     166             :                         ~GraphicCacheEntry();
     167             : 
     168       76354 :     const GraphicID&    GetID() const { return maID; }
     169             : 
     170             :     void                AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute );
     171             :     bool                ReleaseGraphicObjectReference( const GraphicObject& rObj );
     172       35044 :     size_t              GetGraphicObjectReferenceCount() { return maGraphicObjectList.size(); }
     173             :     bool                HasGraphicObjectReference( const GraphicObject& rObj );
     174             : 
     175             :     void                TryToSwapIn();
     176             :     void                GraphicObjectWasSwappedOut( const GraphicObject& rObj );
     177             :     bool                FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute );
     178             :     void                GraphicObjectWasSwappedIn( const GraphicObject& rObj );
     179             : };
     180             : 
     181       24367 : GraphicCacheEntry::GraphicCacheEntry( const GraphicObject& rObj ) :
     182             :     maID            ( rObj ),
     183             :     mpBmpEx         ( NULL ),
     184             :     mpMtf           ( NULL ),
     185             :     mpAnimation     ( NULL ),
     186       24367 :     mbSwappedAll    ( true )
     187             : {
     188       24367 :     mbSwappedAll = !ImplInit( rObj );
     189       24367 :     maGraphicObjectList.push_back( (GraphicObject*)&rObj );
     190       24367 : }
     191             : 
     192       48348 : GraphicCacheEntry::~GraphicCacheEntry()
     193             : {
     194             :     DBG_ASSERT(
     195             :         maGraphicObjectList.empty(),
     196             :         "GraphicCacheEntry::~GraphicCacheEntry(): Not all GraphicObjects are removed from this entry"
     197             :     );
     198             : 
     199       24174 :     delete mpBmpEx;
     200       24174 :     delete mpMtf;
     201       24174 :     delete mpAnimation;
     202       24174 : }
     203             : 
     204       24397 : bool GraphicCacheEntry::ImplInit( const GraphicObject& rObj )
     205             : {
     206       24397 :     bool bRet = false;
     207             : 
     208       24397 :     if( !rObj.IsSwappedOut() )
     209             :     {
     210       24397 :         const Graphic& rGraphic = rObj.GetGraphic();
     211             : 
     212       24397 :         if( mpBmpEx )
     213           0 :             delete mpBmpEx, mpBmpEx = NULL;
     214             : 
     215       24397 :         if( mpMtf )
     216           0 :             delete mpMtf, mpMtf = NULL;
     217             : 
     218       24397 :         if( mpAnimation )
     219           0 :             delete mpAnimation, mpAnimation = NULL;
     220             : 
     221       24397 :         switch( rGraphic.GetType() )
     222             :         {
     223             :             case( GRAPHIC_BITMAP ):
     224             :             {
     225        1459 :                 if(rGraphic.getSvgData().get())
     226             :                 {
     227           6 :                     maSvgData = rGraphic.getSvgData();
     228             :                 }
     229        1453 :                 else if( rGraphic.IsAnimated() )
     230             :                 {
     231           0 :                     mpAnimation = new Animation( rGraphic.GetAnimation() );
     232             :                 }
     233             :                 else
     234             :                 {
     235        1453 :                     mpBmpEx = new BitmapEx( rGraphic.GetBitmapEx() );
     236             :                 }
     237             :             }
     238        1459 :             break;
     239             : 
     240             :             case( GRAPHIC_GDIMETAFILE ):
     241             :             {
     242         724 :                 mpMtf = new GDIMetaFile( rGraphic.GetGDIMetaFile() );
     243             :             }
     244         724 :             break;
     245             : 
     246             :             default:
     247             :                 DBG_ASSERT( GetID().IsEmpty(), "GraphicCacheEntry::ImplInit: Could not initialize graphic! (=>KA)" );
     248       22214 :             break;
     249             :         }
     250             : 
     251       24397 :         if( rGraphic.IsLink() )
     252        1594 :             maGfxLink = ( (Graphic&) rGraphic ).GetLink();
     253             :         else
     254       22803 :             maGfxLink = GfxLink();
     255             : 
     256       24397 :         bRet = true;
     257             :     }
     258             : 
     259       24397 :     return bRet;
     260             : }
     261             : 
     262       10892 : void GraphicCacheEntry::ImplFillSubstitute( Graphic& rSubstitute )
     263             : {
     264             :     // create substitute for graphic;
     265       10892 :     const Size          aPrefSize( rSubstitute.GetPrefSize() );
     266       10892 :     const MapMode       aPrefMapMode( rSubstitute.GetPrefMapMode() );
     267       10892 :     const Link          aAnimationNotifyHdl( rSubstitute.GetAnimationNotifyHdl() );
     268       21784 :     const OUString      aDocFileName( rSubstitute.GetDocFileName() );
     269       10892 :     const sal_uLong     nDocFilePos = rSubstitute.GetDocFilePos();
     270       10892 :     const GraphicType   eOldType = rSubstitute.GetType();
     271       10892 :     const bool          bDefaultType = ( rSubstitute.GetType() == GRAPHIC_DEFAULT );
     272             : 
     273       10892 :     if( rSubstitute.IsLink() && ( GFX_LINK_TYPE_NONE == maGfxLink.GetType() ) )
     274           2 :         maGfxLink = rSubstitute.GetLink();
     275             : 
     276       10892 :     if(maSvgData.get())
     277             :     {
     278           4 :         rSubstitute = maSvgData;
     279             :     }
     280       10888 :     else if( mpBmpEx )
     281             :     {
     282        8438 :         rSubstitute = *mpBmpEx;
     283             :     }
     284        2450 :     else if( mpAnimation )
     285             :     {
     286           0 :         rSubstitute = *mpAnimation;
     287             :     }
     288        2450 :     else if( mpMtf )
     289             :     {
     290        2420 :         rSubstitute = *mpMtf;
     291             :     }
     292             :     else
     293             :     {
     294          30 :         rSubstitute.Clear();
     295             :     }
     296             : 
     297       10892 :     if( eOldType != GRAPHIC_NONE )
     298             :     {
     299        8180 :         rSubstitute.SetPrefSize( aPrefSize );
     300        8180 :         rSubstitute.SetPrefMapMode( aPrefMapMode );
     301        8180 :         rSubstitute.SetAnimationNotifyHdl( aAnimationNotifyHdl );
     302        8180 :         rSubstitute.SetDocFileName( aDocFileName, nDocFilePos );
     303             :     }
     304             : 
     305       10892 :     if( GFX_LINK_TYPE_NONE != maGfxLink.GetType() )
     306             :     {
     307        8444 :         rSubstitute.SetLink( maGfxLink );
     308             :     }
     309             : 
     310       10892 :     if( bDefaultType )
     311             :     {
     312           6 :         rSubstitute.SetDefaultType();
     313       10892 :     }
     314       10892 : }
     315             : 
     316       10890 : void GraphicCacheEntry::AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute )
     317             : {
     318       10890 :     if( mbSwappedAll )
     319           0 :         mbSwappedAll = !ImplInit( rObj );
     320             : 
     321       10890 :     ImplFillSubstitute( rSubstitute );
     322       10890 :     maGraphicObjectList.push_back( (GraphicObject*) &rObj );
     323       10890 : }
     324             : 
     325      187860 : bool GraphicCacheEntry::ReleaseGraphicObjectReference( const GraphicObject& rObj )
     326             : {
     327     1242132 :     for(
     328      187860 :         GraphicObjectList_impl::iterator it = maGraphicObjectList.begin();
     329      828088 :         it != maGraphicObjectList.end();
     330             :         ++it
     331             :     ) {
     332      261228 :         if( &rObj == *it )
     333             :         {
     334       35044 :             maGraphicObjectList.erase( it );
     335       35044 :             return true;
     336             :         }
     337             :     }
     338             : 
     339      152816 :     return false;
     340             : }
     341             : 
     342      102304 : bool GraphicCacheEntry::HasGraphicObjectReference( const GraphicObject& rObj )
     343             : {
     344      102304 :     bool bRet = false;
     345             : 
     346      263983 :     for( size_t i = 0, n = maGraphicObjectList.size(); ( i < n ) && !bRet; ++i )
     347      161679 :         if( &rObj == maGraphicObjectList[ i ] )
     348       14055 :             bRet = true;
     349             : 
     350      102304 :     return bRet;
     351             : }
     352             : 
     353        3094 : void GraphicCacheEntry::TryToSwapIn()
     354             : {
     355        3094 :     if( mbSwappedAll && !maGraphicObjectList.empty() )
     356           4 :         maGraphicObjectList.front()->FireSwapInRequest();
     357        3094 : }
     358             : 
     359         184 : void GraphicCacheEntry::GraphicObjectWasSwappedOut( const GraphicObject& /*rObj*/ )
     360             : {
     361         184 :     mbSwappedAll = true;
     362             : 
     363         372 :     for( size_t i = 0, n = maGraphicObjectList.size(); ( i < n ) && mbSwappedAll; ++i )
     364         188 :         if( !maGraphicObjectList[ i ]->IsSwappedOut() )
     365          32 :             mbSwappedAll = false;
     366             : 
     367         184 :     if( mbSwappedAll )
     368             :     {
     369         152 :         delete mpBmpEx, mpBmpEx = NULL;
     370         152 :         delete mpMtf, mpMtf = NULL;
     371         152 :         delete mpAnimation, mpAnimation = NULL;
     372             : 
     373             :         // #119176# also reset SvgData
     374         152 :         maSvgData.reset();
     375             :     }
     376         184 : }
     377             : 
     378          92 : bool GraphicCacheEntry::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
     379             : {
     380          92 :     bool bRet = false;
     381             : 
     382          92 :     if( !mbSwappedAll && rObj.IsSwappedOut() )
     383             :     {
     384           2 :         ImplFillSubstitute( rSubstitute );
     385           2 :         bRet = true;
     386             :     }
     387             : 
     388          92 :     return bRet;
     389             : }
     390             : 
     391          48 : void GraphicCacheEntry::GraphicObjectWasSwappedIn( const GraphicObject& rObj )
     392             : {
     393          48 :     if( mbSwappedAll )
     394          30 :         mbSwappedAll = !ImplInit( rObj );
     395          48 : }
     396             : 
     397             : class GraphicDisplayCacheEntry
     398             : {
     399             : private:
     400             : 
     401             :     ::salhelper::TTimeValue     maReleaseTime;
     402             :     const GraphicCacheEntry*    mpRefCacheEntry;
     403             :     GDIMetaFile*                mpMtf;
     404             :     BitmapEx*                   mpBmpEx;
     405             :     GraphicAttr                 maAttr;
     406             :     Size                        maOutSizePix;
     407             :     sal_uLong                       mnCacheSize;
     408             :     sal_uLong                       mnOutDevDrawMode;
     409             :     sal_uInt16                      mnOutDevBitCount;
     410             : 
     411             :     static bool IsCacheableAsBitmap( const GDIMetaFile& rMtf, OutputDevice* pOut, const Size& rSz );
     412             : 
     413             : public:
     414             : 
     415             :     static sal_uLong                GetNeededSize( OutputDevice* pOut, const Point& rPt, const Size& rSz,
     416             :                                                const GraphicObject& rObj, const GraphicAttr& rAttr );
     417             : 
     418             : public:
     419             : 
     420           0 :                                 GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry,
     421             :                                                           OutputDevice* pOut, const Point& rPt, const Size& rSz,
     422             :                                                           const GraphicObject& rObj, const GraphicAttr& rAttr,
     423             :                                                           const BitmapEx& rBmpEx ) :
     424             :                                     mpRefCacheEntry( pRefCacheEntry ),
     425           0 :                                     mpMtf( NULL ), mpBmpEx( new BitmapEx( rBmpEx ) ),
     426             :                                     maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ),
     427           0 :                                     mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ),
     428           0 :                                     mnOutDevDrawMode( pOut->GetDrawMode() ),
     429           0 :                                     mnOutDevBitCount( pOut->GetBitCount() )
     430             :                                     {
     431           0 :                                     }
     432             : 
     433           0 :                                 GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry,
     434             :                                                           OutputDevice* pOut, const Point& rPt, const Size& rSz,
     435             :                                                           const GraphicObject& rObj, const GraphicAttr& rAttr,
     436             :                                                           const GDIMetaFile& rMtf ) :
     437             :                                     mpRefCacheEntry( pRefCacheEntry ),
     438           0 :                                     mpMtf( new GDIMetaFile( rMtf ) ), mpBmpEx( NULL ),
     439             :                                     maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ),
     440           0 :                                     mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ),
     441           0 :                                     mnOutDevDrawMode( pOut->GetDrawMode() ),
     442           0 :                                     mnOutDevBitCount( pOut->GetBitCount() )
     443             :                                     {
     444           0 :                                     }
     445             : 
     446             : 
     447             :                                 ~GraphicDisplayCacheEntry();
     448             : 
     449           0 :     sal_uLong                   GetCacheSize() const { return mnCacheSize; }
     450           0 :     const GraphicCacheEntry*    GetReferencedCacheEntry() const { return mpRefCacheEntry; }
     451             : 
     452           0 :     void                        SetReleaseTime( const ::salhelper::TTimeValue& rReleaseTime ) { maReleaseTime = rReleaseTime; }
     453           0 :     const ::salhelper::TTimeValue&    GetReleaseTime() const { return maReleaseTime; }
     454             : 
     455           0 :     bool                        Matches( OutputDevice* pOut, const Point& /*rPtPixel*/, const Size& rSzPixel,
     456             :                                          const GraphicCacheEntry* pCacheEntry, const GraphicAttr& rAttr ) const
     457             :                                 {
     458             :                                     // #i46805# Additional match
     459             :                                     // criteria: outdev draw mode and
     460             :                                     // bit count. One cannot reuse
     461             :                                     // this cache object, if it's
     462             :                                     // e.g. generated for
     463             :                                     // DRAWMODE_GRAYBITMAP.
     464           0 :                                     return( ( pCacheEntry == mpRefCacheEntry ) &&
     465           0 :                                             ( maAttr == rAttr ) &&
     466           0 :                                             ( ( maOutSizePix == rSzPixel ) || ( !maOutSizePix.Width() && !maOutSizePix.Height() ) ) &&
     467           0 :                                             ( pOut->GetBitCount() == mnOutDevBitCount ) &&
     468           0 :                                             ( pOut->GetDrawMode() == mnOutDevDrawMode ) );
     469             :                                 }
     470             : 
     471             :     void                        Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const;
     472             : };
     473             : 
     474             : // This whole function is based on checkMetadataBitmap() from grfmgr2.cxx, see that one for details.
     475             : // If you do changes here, change the original function too.
     476           0 : static void checkMetadataBitmap( const BitmapEx& rBmpEx,
     477             :                                  Point    /*rSrcPoint*/,
     478             :                                  Size     rSrcSize,
     479             :                                  const Point&    rDestPoint,
     480             :                                  const Size&     rDestSize,
     481             :                                  const Size&     rRefSize,
     482             :                                  bool&           o_rbNonBitmapActionEncountered )
     483             : {
     484           0 :     if( rSrcSize == Size())
     485           0 :         rSrcSize = rBmpEx.GetSizePixel();
     486             : 
     487           0 :     if( rDestPoint != Point( 0, 0 ))
     488             :     {
     489           0 :         o_rbNonBitmapActionEncountered = true;
     490           0 :         return;
     491             :     }
     492           0 :     if( rDestSize != rRefSize )
     493           0 :     {    if( rBmpEx.GetSizePixel().Width() > 100 && rBmpEx.GetSizePixel().Height() > 100
     494           0 :              && std::abs( rDestSize.Width() - rRefSize.Width()) < 5
     495           0 :              && std::abs( rDestSize.Height() - rRefSize.Height()) < 5 )
     496             :             ; // ok, assume it's close enough
     497             :         else
     498             :         {  // fall back to mtf rendering
     499           0 :             o_rbNonBitmapActionEncountered = true;
     500           0 :             return;
     501             :         }
     502             :     }
     503             : }
     504             : 
     505             : // This function is based on GraphicManager::ImplCreateOutput(), in fact it mostly copies
     506             : // it, the difference is that this one does not create anything, it only checks if
     507             : // ImplCreateOutput() would use the optimization of using the single bitmap.
     508             : // If you do changes here, change the original function too.
     509           0 : bool GraphicDisplayCacheEntry::IsCacheableAsBitmap( const GDIMetaFile& rMtf,
     510             :     OutputDevice* pOut, const Size& rSz )
     511             : {
     512           0 :     const Size aNewSize( rMtf.GetPrefSize() );
     513           0 :     GDIMetaFile rOutMtf = rMtf;
     514             : 
     515             :     // Count bitmap actions, and flag actions that paint, but
     516             :     // are no bitmaps.
     517           0 :     sal_Int32   nNumBitmaps(0);
     518           0 :     bool        bNonBitmapActionEncountered(false);
     519           0 :     if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() )
     520             :     {
     521           0 :         const MapMode rPrefMapMode( rMtf.GetPrefMapMode() );
     522           0 :         const Size rSizePix( pOut->LogicToPixel( aNewSize, rPrefMapMode ) );
     523             : 
     524             :         sal_uInt32  nCurPos;
     525             :         MetaAction* pAct;
     526           0 :         for( nCurPos = 0, pAct = (MetaAction*)rOutMtf.FirstAction(); pAct;
     527             :              pAct = (MetaAction*)rOutMtf.NextAction(), nCurPos++ )
     528             :         {
     529           0 :             switch( pAct->GetType() )
     530             :             {
     531             :                 case META_FONT_ACTION:
     532             :                     // FALLTHROUGH intended
     533             :                 case META_NULL_ACTION:
     534             :                     // FALLTHROUGH intended
     535             : 
     536             :                     // OutDev state changes (which don't affect bitmap
     537             :                     // output)
     538             :                 case META_LINECOLOR_ACTION:
     539             :                     // FALLTHROUGH intended
     540             :                 case META_FILLCOLOR_ACTION:
     541             :                     // FALLTHROUGH intended
     542             :                 case META_TEXTCOLOR_ACTION:
     543             :                     // FALLTHROUGH intended
     544             :                 case META_TEXTFILLCOLOR_ACTION:
     545             :                     // FALLTHROUGH intended
     546             :                 case META_TEXTALIGN_ACTION:
     547             :                     // FALLTHROUGH intended
     548             :                 case META_TEXTLINECOLOR_ACTION:
     549             :                     // FALLTHROUGH intended
     550             :                 case META_TEXTLINE_ACTION:
     551             :                     // FALLTHROUGH intended
     552             :                 case META_PUSH_ACTION:
     553             :                     // FALLTHROUGH intended
     554             :                 case META_POP_ACTION:
     555             :                     // FALLTHROUGH intended
     556             :                 case META_LAYOUTMODE_ACTION:
     557             :                     // FALLTHROUGH intended
     558             :                 case META_TEXTLANGUAGE_ACTION:
     559             :                     // FALLTHROUGH intended
     560             :                 case META_COMMENT_ACTION:
     561           0 :                     break;
     562             : 
     563             :                     // bitmap output methods
     564             :                 case META_BMP_ACTION:
     565           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
     566             :                     {
     567           0 :                         MetaBmpAction* pAction = static_cast<MetaBmpAction*>(pAct);
     568             : 
     569             :                         checkMetadataBitmap(
     570           0 :                             BitmapEx( pAction->GetBitmap()),
     571             :                             Point(), Size(),
     572           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
     573             :                                                 rPrefMapMode ),
     574           0 :                             pAction->GetBitmap().GetSizePixel(),
     575             :                             rSizePix,
     576           0 :                             bNonBitmapActionEncountered );
     577             :                     }
     578           0 :                     ++nNumBitmaps;
     579           0 :                     break;
     580             : 
     581             :                 case META_BMPSCALE_ACTION:
     582           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
     583             :                     {
     584           0 :                         MetaBmpScaleAction* pAction = static_cast<MetaBmpScaleAction*>(pAct);
     585             : 
     586             :                         checkMetadataBitmap(
     587           0 :                             BitmapEx( pAction->GetBitmap()),
     588             :                             Point(), Size(),
     589           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
     590             :                                                 rPrefMapMode ),
     591           0 :                             pOut->LogicToPixel( pAction->GetSize(),
     592             :                                                 rPrefMapMode ),
     593             :                             rSizePix,
     594           0 :                             bNonBitmapActionEncountered );
     595             :                     }
     596           0 :                     ++nNumBitmaps;
     597           0 :                     break;
     598             : 
     599             :                 case META_BMPSCALEPART_ACTION:
     600           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
     601             :                     {
     602           0 :                         MetaBmpScalePartAction* pAction = static_cast<MetaBmpScalePartAction*>(pAct);
     603             : 
     604           0 :                         checkMetadataBitmap(        BitmapEx( pAction->GetBitmap() ),
     605           0 :                                                     pAction->GetSrcPoint(),
     606           0 :                                                     pAction->GetSrcSize(),
     607           0 :                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
     608             :                                                                         rPrefMapMode ),
     609           0 :                                                     pOut->LogicToPixel( pAction->GetDestSize(),
     610             :                                                                         rPrefMapMode ),
     611             :                                                     rSizePix,
     612           0 :                                                     bNonBitmapActionEncountered );
     613             :                     }
     614           0 :                     ++nNumBitmaps;
     615           0 :                     break;
     616             : 
     617             :                 case META_BMPEX_ACTION:
     618           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
     619             :                     {
     620           0 :                         MetaBmpExAction* pAction = static_cast<MetaBmpExAction*>(pAct);
     621             : 
     622             :                         checkMetadataBitmap(
     623           0 :                             pAction->GetBitmapEx(),
     624             :                             Point(), Size(),
     625           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
     626             :                                                 rPrefMapMode ),
     627           0 :                             pAction->GetBitmapEx().GetSizePixel(),
     628             :                             rSizePix,
     629           0 :                             bNonBitmapActionEncountered );
     630             :                     }
     631           0 :                     ++nNumBitmaps;
     632           0 :                     break;
     633             : 
     634             :                 case META_BMPEXSCALE_ACTION:
     635           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
     636             :                     {
     637           0 :                         MetaBmpExScaleAction* pAction = static_cast<MetaBmpExScaleAction*>(pAct);
     638             : 
     639             :                         checkMetadataBitmap(
     640           0 :                             pAction->GetBitmapEx(),
     641             :                             Point(), Size(),
     642           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
     643             :                                                 rPrefMapMode ),
     644           0 :                             pOut->LogicToPixel( pAction->GetSize(),
     645             :                                                 rPrefMapMode ),
     646             :                             rSizePix,
     647           0 :                             bNonBitmapActionEncountered );
     648             :                     }
     649           0 :                     ++nNumBitmaps;
     650           0 :                     break;
     651             : 
     652             :                 case META_BMPEXSCALEPART_ACTION:
     653           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
     654             :                     {
     655           0 :                         MetaBmpExScalePartAction* pAction = static_cast<MetaBmpExScalePartAction*>(pAct);
     656             : 
     657           0 :                         checkMetadataBitmap( pAction->GetBitmapEx(),
     658           0 :                                                     pAction->GetSrcPoint(),
     659           0 :                                                     pAction->GetSrcSize(),
     660           0 :                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
     661             :                                                                         rPrefMapMode ),
     662           0 :                                                     pOut->LogicToPixel( pAction->GetDestSize(),
     663             :                                                                         rPrefMapMode ),
     664             :                                                     rSizePix,
     665           0 :                                                     bNonBitmapActionEncountered );
     666             :                     }
     667           0 :                     ++nNumBitmaps;
     668           0 :                     break;
     669             : 
     670             :                     // these actions actually output something (that's
     671             :                     // different from a bitmap)
     672             :                 case META_RASTEROP_ACTION:
     673           0 :                     if( static_cast<MetaRasterOpAction*>(pAct)->GetRasterOp() == ROP_OVERPAINT )
     674           0 :                         break;
     675             :                     // FALLTHROUGH intended
     676             :                 case META_PIXEL_ACTION:
     677             :                     // FALLTHROUGH intended
     678             :                 case META_POINT_ACTION:
     679             :                     // FALLTHROUGH intended
     680             :                 case META_LINE_ACTION:
     681             :                     // FALLTHROUGH intended
     682             :                 case META_RECT_ACTION:
     683             :                     // FALLTHROUGH intended
     684             :                 case META_ROUNDRECT_ACTION:
     685             :                     // FALLTHROUGH intended
     686             :                 case META_ELLIPSE_ACTION:
     687             :                     // FALLTHROUGH intended
     688             :                 case META_ARC_ACTION:
     689             :                     // FALLTHROUGH intended
     690             :                 case META_PIE_ACTION:
     691             :                     // FALLTHROUGH intended
     692             :                 case META_CHORD_ACTION:
     693             :                     // FALLTHROUGH intended
     694             :                 case META_POLYLINE_ACTION:
     695             :                     // FALLTHROUGH intended
     696             :                 case META_POLYGON_ACTION:
     697             :                     // FALLTHROUGH intended
     698             :                 case META_POLYPOLYGON_ACTION:
     699             :                     // FALLTHROUGH intended
     700             : 
     701             :                 case META_TEXT_ACTION:
     702             :                     // FALLTHROUGH intended
     703             :                 case META_TEXTARRAY_ACTION:
     704             :                     // FALLTHROUGH intended
     705             :                 case META_STRETCHTEXT_ACTION:
     706             :                     // FALLTHROUGH intended
     707             :                 case META_TEXTRECT_ACTION:
     708             :                     // FALLTHROUGH intended
     709             : 
     710             :                 case META_MASK_ACTION:
     711             :                     // FALLTHROUGH intended
     712             :                 case META_MASKSCALE_ACTION:
     713             :                     // FALLTHROUGH intended
     714             :                 case META_MASKSCALEPART_ACTION:
     715             :                     // FALLTHROUGH intended
     716             : 
     717             :                 case META_GRADIENT_ACTION:
     718             :                     // FALLTHROUGH intended
     719             :                 case META_HATCH_ACTION:
     720             :                     // FALLTHROUGH intended
     721             :                 case META_WALLPAPER_ACTION:
     722             :                     // FALLTHROUGH intended
     723             : 
     724             :                 case META_TRANSPARENT_ACTION:
     725             :                     // FALLTHROUGH intended
     726             :                 case META_EPS_ACTION:
     727             :                     // FALLTHROUGH intended
     728             :                 case META_FLOATTRANSPARENT_ACTION:
     729             :                     // FALLTHROUGH intended
     730             :                 case META_GRADIENTEX_ACTION:
     731             :                     // FALLTHROUGH intended
     732             : 
     733             :                     // OutDev state changes that _do_ affect bitmap
     734             :                     // output
     735             :                 case META_CLIPREGION_ACTION:
     736             :                     // FALLTHROUGH intended
     737             :                 case META_ISECTRECTCLIPREGION_ACTION:
     738             :                     // FALLTHROUGH intended
     739             :                 case META_ISECTREGIONCLIPREGION_ACTION:
     740             :                     // FALLTHROUGH intended
     741             :                 case META_MOVECLIPREGION_ACTION:
     742             :                     // FALLTHROUGH intended
     743             : 
     744             :                 case META_MAPMODE_ACTION:
     745             :                     // FALLTHROUGH intended
     746             :                 case META_REFPOINT_ACTION:
     747             :                     // FALLTHROUGH intended
     748             :                 default:
     749           0 :                     bNonBitmapActionEncountered = true;
     750           0 :                     break;
     751             :             }
     752           0 :         }
     753             :     }
     754           0 :     return nNumBitmaps == 1 && !bNonBitmapActionEncountered;
     755             : }
     756             : 
     757           0 : sal_uLong GraphicDisplayCacheEntry::GetNeededSize( OutputDevice* pOut, const Point& /*rPt*/, const Size& rSz,
     758             :                                                const GraphicObject& rObj, const GraphicAttr& rAttr )
     759             : {
     760           0 :     const Graphic&      rGraphic = rObj.GetGraphic();
     761           0 :     const GraphicType   eType = rGraphic.GetType();
     762             : 
     763           0 :     bool canCacheAsBitmap = false;
     764           0 :     if( GRAPHIC_BITMAP == eType )
     765           0 :         canCacheAsBitmap = true;
     766           0 :     else if( GRAPHIC_GDIMETAFILE == eType )
     767           0 :         canCacheAsBitmap = IsCacheableAsBitmap( rGraphic.GetGDIMetaFile(), pOut, rSz );
     768             :     else
     769           0 :         return 0;
     770           0 :     if( canCacheAsBitmap )
     771             :     {
     772           0 :         const Size aOutSizePix( pOut->LogicToPixel( rSz ) );
     773           0 :         const long nBitCount = pOut->GetBitCount();
     774             : 
     775           0 :         if( ( aOutSizePix.Width() > MAX_BMP_EXTENT ) ||
     776           0 :             ( aOutSizePix.Height() > MAX_BMP_EXTENT ) )
     777             :         {
     778           0 :             return ULONG_MAX;
     779             :         }
     780           0 :         else if( nBitCount )
     781             :         {
     782           0 :             sal_uLong nNeededSize = aOutSizePix.Width() * aOutSizePix.Height() * nBitCount / 8;
     783           0 :             if( rObj.IsTransparent() || ( rAttr.GetRotation() % 3600 ) )
     784           0 :                 nNeededSize += nNeededSize / nBitCount;
     785           0 :             return nNeededSize;
     786             :         }
     787             :         else
     788             :         {
     789             :             OSL_FAIL( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" );
     790           0 :             return 256000;
     791             :         }
     792             :     }
     793             :     else
     794           0 :         return rGraphic.GetSizeBytes();
     795             : }
     796             : 
     797           0 : GraphicDisplayCacheEntry::~GraphicDisplayCacheEntry()
     798             : {
     799           0 :     if( mpMtf )
     800           0 :         delete mpMtf;
     801             : 
     802           0 :     if( mpBmpEx )
     803           0 :         delete mpBmpEx;
     804           0 : }
     805             : 
     806           0 : void GraphicDisplayCacheEntry::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const
     807             : {
     808           0 :     if( mpMtf )
     809           0 :         GraphicManager::ImplDraw( pOut, rPt, rSz, *mpMtf, maAttr );
     810           0 :     else if( mpBmpEx )
     811             :     {
     812           0 :         if( maAttr.IsRotated() )
     813             :         {
     814           0 :             Polygon aPoly( Rectangle( rPt, rSz ) );
     815             : 
     816           0 :             aPoly.Rotate( rPt, maAttr.GetRotation() % 3600 );
     817           0 :             const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
     818           0 :             pOut->DrawBitmapEx( aRotBoundRect.TopLeft(), aRotBoundRect.GetSize(), *mpBmpEx );
     819             :         }
     820             :         else
     821           0 :             pOut->DrawBitmapEx( rPt, rSz, *mpBmpEx );
     822             :     }
     823           0 : }
     824             : 
     825         226 : GraphicCache::GraphicCache( sal_uLong nDisplayCacheSize, sal_uLong nMaxObjDisplayCacheSize ) :
     826             :     mnReleaseTimeoutSeconds ( 0UL ),
     827             :     mnMaxDisplaySize        ( nDisplayCacheSize ),
     828             :     mnMaxObjDisplaySize     ( nMaxObjDisplayCacheSize ),
     829         226 :     mnUsedDisplaySize       ( 0UL )
     830             : {
     831         226 :     maReleaseTimer.SetTimeoutHdl( LINK( this, GraphicCache, ReleaseTimeoutHdl ) );
     832         226 :     maReleaseTimer.SetTimeout( RELEASE_TIMEOUT );
     833         226 :     maReleaseTimer.Start();
     834         226 : }
     835             : 
     836          90 : GraphicCache::~GraphicCache()
     837             : {
     838             :     DBG_ASSERT( !maGraphicCache.size(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in cache" );
     839             :     DBG_ASSERT( maDisplayCache.empty(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in display cache" );
     840          90 : }
     841             : 
     842       35257 : void GraphicCache::AddGraphicObject(
     843             :     const GraphicObject& rObj,
     844             :     Graphic& rSubstitute,
     845             :     const OString* pID,
     846             :     const GraphicObject* pCopyObj
     847             : )
     848             : {
     849       35257 :     bool bInserted = false;
     850             : 
     851       70514 :     if(  !rObj.IsSwappedOut()
     852       48334 :       && (  pID
     853       32545 :          || (    pCopyObj
     854       16373 :             && ( pCopyObj->GetType() != GRAPHIC_NONE )
     855             :             )
     856       26014 :          || ( rObj.GetType() != GRAPHIC_NONE )
     857             :          )
     858             :       )
     859             :     {
     860       13077 :         if( pCopyObj
     861       13077 :           && !maGraphicCache.empty()
     862             :         )
     863             :         {
     864        6531 :             GraphicCacheEntryList::iterator it = maGraphicCache.begin();
     865      179781 :             while(  !bInserted
     866      215761 :                  && ( it != maGraphicCache.end() )
     867             :                  )
     868             :             {
     869       49042 :                 if( (*it)->HasGraphicObjectReference( *pCopyObj ) )
     870             :                 {
     871        6531 :                     (*it)->AddGraphicObjectReference( rObj, rSubstitute );
     872        6531 :                     bInserted = true;
     873             :                 }
     874             :                 else
     875             :                 {
     876       42511 :                     ++it;
     877             :                 }
     878             :             }
     879             :         }
     880             : 
     881       13077 :         if( !bInserted )
     882             :         {
     883        6546 :             GraphicCacheEntryList::iterator it = maGraphicCache.begin();
     884        6546 :             boost::scoped_ptr< GraphicID > apID;
     885             : 
     886        6546 :             if( !pID )
     887             :             {
     888        3834 :                 apID.reset( new GraphicID( rObj ) );
     889             :             }
     890             : 
     891      173526 :             while(  !bInserted
     892      212469 :                  && ( it != maGraphicCache.end() )
     893             :                  )
     894             :             {
     895       47661 :                 const GraphicID& rEntryID = (*it)->GetID();
     896             : 
     897       47661 :                 if( pID )
     898             :                 {
     899       21449 :                     if( rEntryID.GetIDString() == *pID )
     900             :                     {
     901        2712 :                         (*it)->TryToSwapIn();
     902             : 
     903             :                         // since pEntry->TryToSwapIn can modify our current list, we have to
     904             :                         // iterate from beginning to add a reference to the appropriate
     905             :                         // CacheEntry object; after this, quickly jump out of the outer iteration
     906       75195 :                         for( GraphicCacheEntryList::iterator jt = maGraphicCache.begin();
     907       69771 :                              !bInserted && jt != maGraphicCache.end();
     908             :                              ++jt
     909             :                         )
     910             :                         {
     911       21449 :                             const GraphicID& rID = (*jt)->GetID();
     912             : 
     913       21449 :                             if( rID.GetIDString() == *pID )
     914             :                             {
     915        2712 :                                 (*jt)->AddGraphicObjectReference( rObj, rSubstitute );
     916        2712 :                                 bInserted = true;
     917             :                             }
     918             :                         }
     919             : 
     920        2712 :                         if( !bInserted )
     921             :                         {
     922           0 :                             maGraphicCache.push_back( new GraphicCacheEntry( rObj ) );
     923           0 :                             bInserted = true;
     924             :                         }
     925             :                     }
     926             :                 }
     927             :                 else
     928             :                 {
     929       26212 :                     if( rEntryID == *apID )
     930             :                     {
     931        1647 :                         (*it)->AddGraphicObjectReference( rObj, rSubstitute );
     932        1647 :                         bInserted = true;
     933             :                     }
     934             :                 }
     935             : 
     936       47661 :                 if( !bInserted )
     937       43302 :                     ++it;
     938        6546 :             }
     939             :         }
     940             :     }
     941             : 
     942       35257 :     if( !bInserted )
     943       24367 :         maGraphicCache.push_back( new GraphicCacheEntry( rObj ) );
     944       35257 : }
     945             : 
     946       35044 : void GraphicCache::ReleaseGraphicObject( const GraphicObject& rObj )
     947             : {
     948             :     // Release cached object
     949       35044 :     bool    bRemoved = false;
     950       35044 :     GraphicCacheEntryList::iterator it = maGraphicCache.begin();
     951      257948 :     while (!bRemoved && it != maGraphicCache.end())
     952             :     {
     953      187860 :         bRemoved = (*it)->ReleaseGraphicObjectReference( rObj );
     954             : 
     955      187860 :         if( bRemoved && (0 == (*it)->GetGraphicObjectReferenceCount()) )
     956             :         {
     957             :             // if graphic cache entry has no more references,
     958             :             // the corresponding display cache object can be removed
     959       24174 :             GraphicDisplayCacheEntryList::iterator it2 = maDisplayCache.begin();
     960       48348 :             while( it2 != maDisplayCache.end() )
     961             :             {
     962           0 :                 GraphicDisplayCacheEntry* pDisplayEntry = *it2;
     963           0 :                 if( pDisplayEntry->GetReferencedCacheEntry() == *it )
     964             :                 {
     965           0 :                     mnUsedDisplaySize -= pDisplayEntry->GetCacheSize();
     966           0 :                     it2 = maDisplayCache.erase( it2 );
     967           0 :                     delete pDisplayEntry;
     968             :                 }
     969             :                 else
     970           0 :                     ++it2;
     971             :             }
     972             : 
     973             :             // delete graphic cache entry
     974       24174 :             delete *it;
     975       24174 :             it = maGraphicCache.erase( it );
     976             :         }
     977             :         else
     978      163686 :             ++it;
     979             :     }
     980             : 
     981             :     DBG_ASSERT( bRemoved, "GraphicCache::ReleaseGraphicObject(...): GraphicObject not found in cache" );
     982       35044 : }
     983             : 
     984         184 : void GraphicCache::GraphicObjectWasSwappedOut( const GraphicObject& rObj )
     985             : {
     986             :     // notify cache that rObj is swapped out (and can thus be pruned
     987             :     // from the cache)
     988         184 :     GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
     989             : 
     990         184 :     if( pEntry )
     991         184 :         pEntry->GraphicObjectWasSwappedOut( rObj );
     992         184 : }
     993             : 
     994          92 : bool GraphicCache::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
     995             : {
     996          92 :     GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
     997             : 
     998          92 :     if( !pEntry )
     999           0 :         return false;
    1000             : 
    1001          92 :     return pEntry->FillSwappedGraphicObject( rObj, rSubstitute );
    1002             : }
    1003             : 
    1004          48 : void GraphicCache::GraphicObjectWasSwappedIn( const GraphicObject& rObj )
    1005             : {
    1006          48 :     GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
    1007             : 
    1008          48 :     if( pEntry )
    1009             :     {
    1010          48 :         if( pEntry->GetID().IsEmpty() )
    1011             :         {
    1012           0 :             ReleaseGraphicObject( rObj );
    1013           0 :             AddGraphicObject( rObj, (Graphic&) rObj.GetGraphic(), NULL, NULL );
    1014             :         }
    1015             :         else
    1016          48 :             pEntry->GraphicObjectWasSwappedIn( rObj );
    1017             :     }
    1018          48 : }
    1019             : 
    1020           0 : void GraphicCache::SetMaxDisplayCacheSize( sal_uLong nNewCacheSize )
    1021             : {
    1022           0 :     mnMaxDisplaySize = nNewCacheSize;
    1023             : 
    1024           0 :     if( GetMaxDisplayCacheSize() < GetUsedDisplayCacheSize() )
    1025           0 :         ImplFreeDisplayCacheSpace( GetUsedDisplayCacheSize() - GetMaxDisplayCacheSize() );
    1026           0 : }
    1027             : 
    1028           0 : void GraphicCache::SetMaxObjDisplayCacheSize( sal_uLong nNewMaxObjSize, bool bDestroyGreaterCached )
    1029             : {
    1030           0 :     const bool bDestroy = ( bDestroyGreaterCached && ( nNewMaxObjSize < mnMaxObjDisplaySize ) );
    1031             : 
    1032           0 :     mnMaxObjDisplaySize = std::min( nNewMaxObjSize, mnMaxDisplaySize );
    1033             : 
    1034           0 :     if( bDestroy )
    1035             :     {
    1036           0 :         GraphicDisplayCacheEntryList::iterator it = maDisplayCache.begin();
    1037           0 :         while( it != maDisplayCache.end() )
    1038             :         {
    1039           0 :             GraphicDisplayCacheEntry* pCacheObj = *it;
    1040           0 :             if( pCacheObj->GetCacheSize() > mnMaxObjDisplaySize )
    1041             :             {
    1042           0 :                 mnUsedDisplaySize -= pCacheObj->GetCacheSize();
    1043           0 :                 it = maDisplayCache.erase( it );
    1044           0 :                 delete pCacheObj;
    1045             :             }
    1046             :             else
    1047           0 :                 ++it;
    1048             :         }
    1049             :     }
    1050           0 : }
    1051             : 
    1052         226 : void GraphicCache::SetCacheTimeout( sal_uLong nTimeoutSeconds )
    1053             : {
    1054         226 :     if( mnReleaseTimeoutSeconds != nTimeoutSeconds )
    1055             :     {
    1056         226 :         ::salhelper::TTimeValue           aReleaseTime;
    1057             : 
    1058         226 :         if( ( mnReleaseTimeoutSeconds = nTimeoutSeconds ) != 0 )
    1059             :         {
    1060         226 :             osl_getSystemTime( &aReleaseTime );
    1061         226 :             aReleaseTime.addTime( ::salhelper::TTimeValue( nTimeoutSeconds, 0 ) );
    1062             :         }
    1063             : 
    1064         678 :         for( GraphicDisplayCacheEntryList::const_iterator it = maDisplayCache.begin();
    1065         452 :              it != maDisplayCache.end(); ++it )
    1066             :         {
    1067           0 :             (*it)->SetReleaseTime( aReleaseTime );
    1068             :         }
    1069             :     }
    1070         226 : }
    1071             : 
    1072           0 : bool GraphicCache::IsDisplayCacheable( OutputDevice* pOut, const Point& rPt, const Size& rSz,
    1073             :                                        const GraphicObject& rObj, const GraphicAttr& rAttr ) const
    1074             : {
    1075           0 :     return( GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) <=
    1076           0 :             GetMaxObjDisplayCacheSize() );
    1077             : }
    1078             : 
    1079           4 : bool GraphicCache::IsInDisplayCache( OutputDevice* pOut, const Point& rPt, const Size& rSz,
    1080             :                                      const GraphicObject& rObj, const GraphicAttr& rAttr ) const
    1081             : {
    1082           4 :     const Point                 aPtPixel( pOut->LogicToPixel( rPt ) );
    1083           4 :     const Size                  aSzPixel( pOut->LogicToPixel( rSz ) );
    1084           4 :     const GraphicCacheEntry*    pCacheEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
    1085           4 :     bool                        bFound = false;
    1086             : 
    1087           4 :     if( pCacheEntry )
    1088             :     {
    1089          12 :         for( GraphicDisplayCacheEntryList::const_iterator it = maDisplayCache.begin();
    1090          12 :              !bFound && ( it != maDisplayCache.end() ); ++it )
    1091             :         {
    1092           0 :             if( (*it)->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) )
    1093           0 :                 bFound = true;
    1094             :         }
    1095             :     }
    1096             : 
    1097           4 :     return bFound;
    1098             : }
    1099             : 
    1100        3598 : OString GraphicCache::GetUniqueID( const GraphicObject& rObj ) const
    1101             : {
    1102        3598 :     OString aRet;
    1103        3598 :     GraphicCacheEntry*  pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
    1104             : 
    1105             :     // ensure that the entry is correctly initialized (it has to be read at least once)
    1106        3598 :     if( pEntry && pEntry->GetID().IsEmpty() )
    1107         382 :         pEntry->TryToSwapIn();
    1108             : 
    1109             :     // do another call to ImplGetCacheEntry in case of modified entry list
    1110        3598 :     pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
    1111             : 
    1112        3598 :     if( pEntry )
    1113        3598 :         aRet = pEntry->GetID().GetIDString();
    1114             : 
    1115        3598 :     return aRet;
    1116             : }
    1117             : 
    1118           0 : bool GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
    1119             :                                           const GraphicObject& rObj, const GraphicAttr& rAttr,
    1120             :                                           const BitmapEx& rBmpEx )
    1121             : {
    1122           0 :     const sal_uLong nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr );
    1123           0 :     bool        bRet = false;
    1124             : 
    1125           0 :     if( nNeededSize <= GetMaxObjDisplayCacheSize() )
    1126             :     {
    1127           0 :         if( nNeededSize > GetFreeDisplayCacheSize() )
    1128           0 :             ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() );
    1129             : 
    1130             :         GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ),
    1131           0 :                                                                             pOut, rPt, rSz, rObj, rAttr, rBmpEx );
    1132             : 
    1133           0 :         if( GetCacheTimeout() )
    1134             :         {
    1135           0 :             ::salhelper::TTimeValue aReleaseTime;
    1136             : 
    1137           0 :             osl_getSystemTime( &aReleaseTime );
    1138           0 :             aReleaseTime.addTime( ::salhelper::TTimeValue( GetCacheTimeout(), 0 ) );
    1139           0 :             pNewEntry->SetReleaseTime( aReleaseTime );
    1140             :         }
    1141             : 
    1142           0 :         maDisplayCache.push_back( pNewEntry );
    1143           0 :         mnUsedDisplaySize += pNewEntry->GetCacheSize();
    1144           0 :         bRet = true;
    1145             :     }
    1146             : 
    1147           0 :     return bRet;
    1148             : }
    1149             : 
    1150           0 : bool GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
    1151             :                                           const GraphicObject& rObj, const GraphicAttr& rAttr,
    1152             :                                           const GDIMetaFile& rMtf )
    1153             : {
    1154           0 :     const sal_uLong nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr );
    1155           0 :     bool        bRet = false;
    1156             : 
    1157           0 :     if( nNeededSize <= GetMaxObjDisplayCacheSize() )
    1158             :     {
    1159           0 :         if( nNeededSize > GetFreeDisplayCacheSize() )
    1160           0 :             ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() );
    1161             : 
    1162             :         GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ),
    1163           0 :                                                                             pOut, rPt, rSz, rObj, rAttr, rMtf );
    1164             : 
    1165           0 :         if( GetCacheTimeout() )
    1166             :         {
    1167           0 :             ::salhelper::TTimeValue aReleaseTime;
    1168             : 
    1169           0 :             osl_getSystemTime( &aReleaseTime );
    1170           0 :             aReleaseTime.addTime( ::salhelper::TTimeValue( GetCacheTimeout(), 0 ) );
    1171           0 :             pNewEntry->SetReleaseTime( aReleaseTime );
    1172             :         }
    1173             : 
    1174           0 :         maDisplayCache.push_back( pNewEntry );
    1175           0 :         mnUsedDisplaySize += pNewEntry->GetCacheSize();
    1176           0 :         bRet = true;
    1177             :     }
    1178             : 
    1179           0 :     return bRet;
    1180             : }
    1181             : 
    1182           0 : bool GraphicCache::DrawDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
    1183             :                                         const GraphicObject& rObj, const GraphicAttr& rAttr )
    1184             : {
    1185           0 :     const Point                 aPtPixel( pOut->LogicToPixel( rPt ) );
    1186           0 :     const Size                  aSzPixel( pOut->LogicToPixel( rSz ) );
    1187           0 :     const GraphicCacheEntry*    pCacheEntry = ImplGetCacheEntry( rObj );
    1188           0 :     GraphicDisplayCacheEntry*   pDisplayCacheEntry = NULL;
    1189           0 :     GraphicDisplayCacheEntryList::iterator it = maDisplayCache.begin();
    1190           0 :     bool                    bRet = false;
    1191             : 
    1192           0 :     while( !bRet && it != maDisplayCache.end() )
    1193             :     {
    1194           0 :         pDisplayCacheEntry = *it;
    1195           0 :         if( pDisplayCacheEntry->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) )
    1196             :         {
    1197           0 :             ::salhelper::TTimeValue aReleaseTime;
    1198             : 
    1199             :             // put found object at last used position
    1200           0 :             it = maDisplayCache.erase( it );
    1201           0 :             maDisplayCache.push_back( pDisplayCacheEntry );
    1202             : 
    1203           0 :             if( GetCacheTimeout() )
    1204             :             {
    1205           0 :                 osl_getSystemTime( &aReleaseTime );
    1206           0 :                 aReleaseTime.addTime( ::salhelper::TTimeValue( GetCacheTimeout(), 0 ) );
    1207             :             }
    1208             : 
    1209           0 :             pDisplayCacheEntry->SetReleaseTime( aReleaseTime );
    1210           0 :             bRet = true;
    1211             :         }
    1212             :         else
    1213           0 :             ++it;
    1214             :     }
    1215             : 
    1216           0 :     if( bRet )
    1217           0 :         pDisplayCacheEntry->Draw( pOut, rPt, rSz );
    1218             : 
    1219           0 :     return bRet;
    1220             : }
    1221             : 
    1222           0 : bool GraphicCache::ImplFreeDisplayCacheSpace( sal_uLong nSizeToFree )
    1223             : {
    1224           0 :     sal_uLong nFreedSize = 0UL;
    1225             : 
    1226           0 :     if( nSizeToFree )
    1227             :     {
    1228           0 :         GraphicDisplayCacheEntryList::iterator it = maDisplayCache.begin();
    1229             : 
    1230           0 :         if( nSizeToFree > mnUsedDisplaySize )
    1231           0 :             nSizeToFree = mnUsedDisplaySize;
    1232             : 
    1233           0 :         while( it != maDisplayCache.end() )
    1234             :         {
    1235           0 :             GraphicDisplayCacheEntry* pCacheObj = *it;
    1236             : 
    1237           0 :             nFreedSize += pCacheObj->GetCacheSize();
    1238           0 :             mnUsedDisplaySize -= pCacheObj->GetCacheSize();
    1239           0 :             it = maDisplayCache.erase( it );
    1240           0 :             delete pCacheObj;
    1241             : 
    1242           0 :             if( nFreedSize >= nSizeToFree )
    1243           0 :                 break;
    1244             :         }
    1245             :     }
    1246             : 
    1247           0 :     return( nFreedSize >= nSizeToFree );
    1248             : }
    1249             : 
    1250        7524 : GraphicCacheEntry* GraphicCache::ImplGetCacheEntry( const GraphicObject& rObj )
    1251             : {
    1252        7524 :     GraphicCacheEntry* pRet = NULL;
    1253             : 
    1254      189882 :     for(
    1255        7524 :         GraphicCacheEntryList::iterator it = maGraphicCache.begin();
    1256      174834 :         !pRet && it != maGraphicCache.end();
    1257             :         ++it
    1258             :     ) {
    1259       53262 :         if( (*it)->HasGraphicObjectReference( rObj ) ) {
    1260        7524 :             pRet = *it;
    1261             :         }
    1262             :     }
    1263             : 
    1264        7524 :     return pRet;
    1265             : }
    1266             : 
    1267         782 : IMPL_LINK( GraphicCache, ReleaseTimeoutHdl, Timer*, pTimer )
    1268             : {
    1269         391 :     pTimer->Stop();
    1270             : 
    1271         391 :     ::salhelper::TTimeValue           aCurTime;
    1272         391 :     GraphicDisplayCacheEntryList::iterator it = maDisplayCache.begin();
    1273             : 
    1274         391 :     osl_getSystemTime( &aCurTime );
    1275             : 
    1276         782 :     while( it != maDisplayCache.end() )
    1277             :     {
    1278           0 :         GraphicDisplayCacheEntry*   pDisplayEntry = *it;
    1279           0 :         const ::salhelper::TTimeValue& rReleaseTime = pDisplayEntry->GetReleaseTime();
    1280             : 
    1281           0 :         if( !rReleaseTime.isEmpty() && ( rReleaseTime < aCurTime ) )
    1282             :         {
    1283           0 :             mnUsedDisplaySize -= pDisplayEntry->GetCacheSize();
    1284           0 :             it = maDisplayCache.erase( it );
    1285           0 :             delete pDisplayEntry;
    1286             :         }
    1287             :         else
    1288           0 :             ++it;
    1289             :     }
    1290             : 
    1291         391 :     pTimer->Start();
    1292             : 
    1293         391 :     return 0;
    1294        1227 : }
    1295             : 
    1296             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10