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

Generated by: LCOV version 1.11