merge the formfield patch from ooo-build
[ooovba.git] / goodies / source / graphic / grfcache.cxx
blobae89292d205b7d9b2a6ed7e9594eb1ba58d49b0d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: grfcache.cxx,v $
10 * $Revision: 1.23.38.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_goodies.hxx"
34 #include <vos/timer.hxx>
35 #include <tools/debug.hxx>
36 #include <vcl/outdev.hxx>
37 #include <tools/poly.hxx>
38 #include "grfcache.hxx"
40 // -----------
41 // - Defines -
42 // -----------
44 #define RELEASE_TIMEOUT 10000
45 #define MAX_BMP_EXTENT 4096
47 // -----------
48 // - statics -
49 // -----------
51 static const char aHexData[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
53 // -------------
54 // - GraphicID -
55 // -------------
57 class GraphicID
59 private:
61 sal_uInt32 mnID1;
62 sal_uInt32 mnID2;
63 sal_uInt32 mnID3;
64 sal_uInt32 mnID4;
66 GraphicID();
68 public:
71 GraphicID( const GraphicObject& rObj );
72 ~GraphicID() {}
74 BOOL operator==( const GraphicID& rID ) const
76 return( rID.mnID1 == mnID1 && rID.mnID2 == mnID2 &&
77 rID.mnID3 == mnID3 && rID.mnID4 == mnID4 );
80 ByteString GetIDString() const;
81 BOOL IsEmpty() const { return( 0 == mnID4 ); }
84 // -----------------------------------------------------------------------------
86 GraphicID::GraphicID( const GraphicObject& rObj )
88 const Graphic& rGraphic = rObj.GetGraphic();
90 mnID1 = ( (ULONG) rGraphic.GetType() ) << 28;
92 switch( rGraphic.GetType() )
94 case( GRAPHIC_BITMAP ):
96 if( rGraphic.IsAnimated() )
98 const Animation aAnimation( rGraphic.GetAnimation() );
100 mnID1 |= ( aAnimation.Count() & 0x0fffffff );
101 mnID2 = aAnimation.GetDisplaySizePixel().Width();
102 mnID3 = aAnimation.GetDisplaySizePixel().Height();
103 mnID4 = rGraphic.GetChecksum();
105 else
107 const BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
109 mnID1 |= ( ( ( (ULONG) aBmpEx.GetTransparentType() << 8 ) | ( aBmpEx.IsAlpha() ? 1 : 0 ) ) & 0x0fffffff );
110 mnID2 = aBmpEx.GetSizePixel().Width();
111 mnID3 = aBmpEx.GetSizePixel().Height();
112 mnID4 = rGraphic.GetChecksum();
115 break;
117 case( GRAPHIC_GDIMETAFILE ):
119 const GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
121 mnID1 |= ( aMtf.GetActionCount() & 0x0fffffff );
122 mnID2 = aMtf.GetPrefSize().Width();
123 mnID3 = aMtf.GetPrefSize().Height();
124 mnID4 = rGraphic.GetChecksum();
126 break;
128 default:
129 mnID2 = mnID3 = mnID4 = 0;
130 break;
134 // -----------------------------------------------------------------------------
136 ByteString GraphicID::GetIDString() const
138 ByteString aHexStr;
139 sal_Char* pStr = aHexStr.AllocBuffer( 32 );
140 sal_Int32 nShift;
142 for( nShift = 28; nShift >= 0; nShift -= 4 )
143 *pStr++ = aHexData[ ( mnID1 >> (sal_uInt32) nShift ) & 0xf ];
145 for( nShift = 28; nShift >= 0; nShift -= 4 )
146 *pStr++ = aHexData[ ( mnID2 >> (sal_uInt32) nShift ) & 0xf ];
148 for( nShift = 28; nShift >= 0; nShift -= 4 )
149 *pStr++ = aHexData[ ( mnID3 >> (sal_uInt32) nShift ) & 0xf ];
151 for( nShift = 28; nShift >= 0; nShift -= 4 )
152 *pStr++ = aHexData[ ( mnID4 >> (sal_uInt32) nShift ) & 0xf ];
154 return aHexStr;
157 // ---------------------
158 // - GraphicCacheEntry -
159 // ---------------------
161 class GraphicCacheEntry
163 private:
165 List maGraphicObjectList;
166 GraphicID maID;
167 GfxLink maGfxLink;
168 BitmapEx* mpBmpEx;
169 GDIMetaFile* mpMtf;
170 Animation* mpAnimation;
171 BOOL mbSwappedAll;
173 BOOL ImplInit( const GraphicObject& rObj );
174 BOOL ImplMatches( const GraphicObject& rObj ) const { return( GraphicID( rObj ) == maID ); }
175 void ImplFillSubstitute( Graphic& rSubstitute );
177 public:
179 GraphicCacheEntry( const GraphicObject& rObj );
180 ~GraphicCacheEntry();
182 const GraphicID& GetID() const { return maID; }
184 void AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute );
185 BOOL ReleaseGraphicObjectReference( const GraphicObject& rObj );
186 ULONG GetGraphicObjectReferenceCount() { return maGraphicObjectList.Count(); }
187 BOOL HasGraphicObjectReference( const GraphicObject& rObj );
189 void TryToSwapIn();
190 void GraphicObjectWasSwappedOut( const GraphicObject& rObj );
191 BOOL FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute );
192 void GraphicObjectWasSwappedIn( const GraphicObject& rObj );
195 // -----------------------------------------------------------------------------
197 GraphicCacheEntry::GraphicCacheEntry( const GraphicObject& rObj ) :
198 maID ( rObj ),
199 mpBmpEx ( NULL ),
200 mpMtf ( NULL ),
201 mpAnimation ( NULL ),
202 mbSwappedAll ( !ImplInit( rObj ) )
204 maGraphicObjectList.Insert( (void*) &rObj, LIST_APPEND );
207 // -----------------------------------------------------------------------------
209 GraphicCacheEntry::~GraphicCacheEntry()
211 DBG_ASSERT( !maGraphicObjectList.Count(), "GraphicCacheEntry::~GraphicCacheEntry(): Not all GraphicObjects are removed from this entry" );
213 delete mpBmpEx;
214 delete mpMtf;
215 delete mpAnimation;
218 // -----------------------------------------------------------------------------
220 BOOL GraphicCacheEntry::ImplInit( const GraphicObject& rObj )
222 BOOL bRet;
224 if( !rObj.IsSwappedOut() )
226 const Graphic& rGraphic = rObj.GetGraphic();
228 if( mpBmpEx )
229 delete mpBmpEx, mpBmpEx = NULL;
231 if( mpMtf )
232 delete mpMtf, mpMtf = NULL;
234 if( mpAnimation )
235 delete mpAnimation, mpAnimation = NULL;
237 switch( rGraphic.GetType() )
239 case( GRAPHIC_BITMAP ):
241 if( rGraphic.IsAnimated() )
242 mpAnimation = new Animation( rGraphic.GetAnimation() );
243 else
244 mpBmpEx = new BitmapEx( rGraphic.GetBitmapEx() );
246 break;
248 case( GRAPHIC_GDIMETAFILE ):
250 mpMtf = new GDIMetaFile( rGraphic.GetGDIMetaFile() );
252 break;
254 default:
255 DBG_ASSERT( GetID().IsEmpty(), "GraphicCacheEntry::ImplInit: Could not initialize graphic! (=>KA)" );
256 break;
259 if( rGraphic.IsLink() )
260 maGfxLink = ( (Graphic&) rGraphic ).GetLink();
261 else
262 maGfxLink = GfxLink();
264 bRet = TRUE;
266 else
267 bRet = FALSE;
269 return bRet;
272 // -----------------------------------------------------------------------------
274 void GraphicCacheEntry::ImplFillSubstitute( Graphic& rSubstitute )
276 // create substitute for graphic;
277 const Size aPrefSize( rSubstitute.GetPrefSize() );
278 const MapMode aPrefMapMode( rSubstitute.GetPrefMapMode() );
279 const Link aAnimationNotifyHdl( rSubstitute.GetAnimationNotifyHdl() );
280 const String aDocFileName( rSubstitute.GetDocFileName() );
281 const ULONG nDocFilePos = rSubstitute.GetDocFilePos();
282 const GraphicType eOldType = rSubstitute.GetType();
283 const BOOL bDefaultType = ( rSubstitute.GetType() == GRAPHIC_DEFAULT );
285 if( rSubstitute.IsLink() && ( GFX_LINK_TYPE_NONE == maGfxLink.GetType() ) )
286 maGfxLink = rSubstitute.GetLink();
288 if( mpBmpEx )
289 rSubstitute = *mpBmpEx;
290 else if( mpAnimation )
291 rSubstitute = *mpAnimation;
292 else if( mpMtf )
293 rSubstitute = *mpMtf;
294 else
295 rSubstitute.Clear();
297 if( eOldType != GRAPHIC_NONE )
299 rSubstitute.SetPrefSize( aPrefSize );
300 rSubstitute.SetPrefMapMode( aPrefMapMode );
301 rSubstitute.SetAnimationNotifyHdl( aAnimationNotifyHdl );
302 rSubstitute.SetDocFileName( aDocFileName, nDocFilePos );
305 if( GFX_LINK_TYPE_NONE != maGfxLink.GetType() )
306 rSubstitute.SetLink( maGfxLink );
308 if( bDefaultType )
309 rSubstitute.SetDefaultType();
312 // -----------------------------------------------------------------------------
314 void GraphicCacheEntry::AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute )
316 if( mbSwappedAll )
317 mbSwappedAll = !ImplInit( rObj );
319 ImplFillSubstitute( rSubstitute );
320 maGraphicObjectList.Insert( (void*) &rObj, LIST_APPEND );
323 // -----------------------------------------------------------------------------
325 BOOL GraphicCacheEntry::ReleaseGraphicObjectReference( const GraphicObject& rObj )
327 BOOL bRet = FALSE;
329 for( void* pObj = maGraphicObjectList.First(); !bRet && pObj; pObj = maGraphicObjectList.Next() )
331 if( &rObj == (GraphicObject*) pObj )
333 maGraphicObjectList.Remove( pObj );
334 bRet = TRUE;
338 return bRet;
341 // -----------------------------------------------------------------------------
343 BOOL GraphicCacheEntry::HasGraphicObjectReference( const GraphicObject& rObj )
345 BOOL bRet = FALSE;
347 for( void* pObj = maGraphicObjectList.First(); !bRet && pObj; pObj = maGraphicObjectList.Next() )
348 if( &rObj == (GraphicObject*) pObj )
349 bRet = TRUE;
351 return bRet;
354 // -----------------------------------------------------------------------------
356 void GraphicCacheEntry::TryToSwapIn()
358 if( mbSwappedAll && maGraphicObjectList.Count() )
359 ( (GraphicObject*) maGraphicObjectList.First() )->FireSwapInRequest();
362 // -----------------------------------------------------------------------------
364 void GraphicCacheEntry::GraphicObjectWasSwappedOut( const GraphicObject& /*rObj*/ )
366 mbSwappedAll = TRUE;
368 for( void* pObj = maGraphicObjectList.First(); mbSwappedAll && pObj; pObj = maGraphicObjectList.Next() )
369 if( !( (GraphicObject*) pObj )->IsSwappedOut() )
370 mbSwappedAll = FALSE;
372 if( mbSwappedAll )
374 delete mpBmpEx, mpBmpEx = NULL;
375 delete mpMtf, mpMtf = NULL;
376 delete mpAnimation, mpAnimation = NULL;
380 // -----------------------------------------------------------------------------
382 BOOL GraphicCacheEntry::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
384 BOOL bRet;
386 if( !mbSwappedAll && rObj.IsSwappedOut() )
388 ImplFillSubstitute( rSubstitute );
389 bRet = TRUE;
391 else
392 bRet = FALSE;
394 return bRet;
397 // -----------------------------------------------------------------------------
399 void GraphicCacheEntry::GraphicObjectWasSwappedIn( const GraphicObject& rObj )
401 if( mbSwappedAll )
402 mbSwappedAll = !ImplInit( rObj );
405 // ----------------------------
406 // - GraphicDisplayCacheEntry -
407 // ----------------------------
409 class GraphicDisplayCacheEntry
411 private:
413 ::vos::TTimeValue maReleaseTime;
414 const GraphicCacheEntry* mpRefCacheEntry;
415 GDIMetaFile* mpMtf;
416 BitmapEx* mpBmpEx;
417 GraphicAttr maAttr;
418 Size maOutSizePix;
419 ULONG mnCacheSize;
420 ULONG mnOutDevDrawMode;
421 USHORT mnOutDevBitCount;
423 public:
425 static ULONG GetNeededSize( OutputDevice* pOut, const Point& rPt, const Size& rSz,
426 const GraphicObject& rObj, const GraphicAttr& rAttr );
428 public:
430 GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry,
431 OutputDevice* pOut, const Point& rPt, const Size& rSz,
432 const GraphicObject& rObj, const GraphicAttr& rAttr,
433 const BitmapEx& rBmpEx ) :
434 mpRefCacheEntry( pRefCacheEntry ),
435 mpMtf( NULL ), mpBmpEx( new BitmapEx( rBmpEx ) ),
436 maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ),
437 mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ),
438 mnOutDevDrawMode( pOut->GetDrawMode() ),
439 mnOutDevBitCount( pOut->GetBitCount() )
443 GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry,
444 OutputDevice* pOut, const Point& rPt, const Size& rSz,
445 const GraphicObject& rObj, const GraphicAttr& rAttr,
446 const GDIMetaFile& rMtf ) :
447 mpRefCacheEntry( pRefCacheEntry ),
448 mpMtf( new GDIMetaFile( rMtf ) ), mpBmpEx( NULL ),
449 maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ),
450 mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ),
451 mnOutDevDrawMode( pOut->GetDrawMode() ),
452 mnOutDevBitCount( pOut->GetBitCount() )
457 ~GraphicDisplayCacheEntry();
459 const GraphicAttr& GetAttr() const { return maAttr; }
460 const Size& GetOutputSizePixel() const { return maOutSizePix; }
461 ULONG GetCacheSize() const { return mnCacheSize; }
462 const GraphicCacheEntry* GetReferencedCacheEntry() const { return mpRefCacheEntry; }
463 ULONG GetOutDevDrawMode() const { return mnOutDevDrawMode; }
464 USHORT GetOutDevBitCount() const { return mnOutDevBitCount; }
466 void SetReleaseTime( const ::vos::TTimeValue& rReleaseTime ) { maReleaseTime = rReleaseTime; }
467 const ::vos::TTimeValue& GetReleaseTime() const { return maReleaseTime; }
469 BOOL Matches( OutputDevice* pOut, const Point& /*rPtPixel*/, const Size& rSzPixel,
470 const GraphicCacheEntry* pCacheEntry, const GraphicAttr& rAttr ) const
472 // #i46805# Additional match
473 // criteria: outdev draw mode and
474 // bit count. One cannot reuse
475 // this cache object, if it's
476 // e.g. generated for
477 // DRAWMODE_GRAYBITMAP.
478 return( ( pCacheEntry == mpRefCacheEntry ) &&
479 ( maAttr == rAttr ) &&
480 ( ( maOutSizePix == rSzPixel ) || ( !maOutSizePix.Width() && !maOutSizePix.Height() ) ) &&
481 ( pOut->GetBitCount() == mnOutDevBitCount ) &&
482 ( pOut->GetDrawMode() == mnOutDevDrawMode ) );
485 void Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const;
488 // -----------------------------------------------------------------------------
490 ULONG GraphicDisplayCacheEntry::GetNeededSize( OutputDevice* pOut, const Point& /*rPt*/, const Size& rSz,
491 const GraphicObject& rObj, const GraphicAttr& rAttr )
493 const Graphic& rGraphic = rObj.GetGraphic();
494 const GraphicType eType = rGraphic.GetType();
495 ULONG nNeededSize;
497 if( GRAPHIC_BITMAP == eType )
499 const Size aOutSizePix( pOut->LogicToPixel( rSz ) );
500 const long nBitCount = pOut->GetBitCount();
502 if( ( aOutSizePix.Width() > MAX_BMP_EXTENT ) ||
503 ( aOutSizePix.Height() > MAX_BMP_EXTENT ) )
505 nNeededSize = ULONG_MAX;
507 else if( nBitCount )
509 nNeededSize = aOutSizePix.Width() * aOutSizePix.Height() * nBitCount / 8;
511 if( rObj.IsTransparent() || ( rAttr.GetRotation() % 3600 ) )
512 nNeededSize += nNeededSize / nBitCount;
514 else
516 DBG_ERROR( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" );
517 nNeededSize = 256000;
520 else if( GRAPHIC_GDIMETAFILE == eType )
521 nNeededSize = rGraphic.GetSizeBytes();
522 else
523 nNeededSize = 0;
525 return nNeededSize;
528 // -----------------------------------------------------------------------------
530 GraphicDisplayCacheEntry::~GraphicDisplayCacheEntry()
532 if( mpMtf )
533 delete mpMtf;
535 if( mpBmpEx )
536 delete mpBmpEx;
539 // -----------------------------------------------------------------------------
541 void GraphicDisplayCacheEntry::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const
543 if( mpMtf )
544 GraphicManager::ImplDraw( pOut, rPt, rSz, *mpMtf, maAttr );
545 else if( mpBmpEx )
547 if( maAttr.IsRotated() )
549 Polygon aPoly( Rectangle( rPt, rSz ) );
551 aPoly.Rotate( rPt, maAttr.GetRotation() % 3600 );
552 const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
553 pOut->DrawBitmapEx( aRotBoundRect.TopLeft(), aRotBoundRect.GetSize(), *mpBmpEx );
555 else
556 pOut->DrawBitmapEx( rPt, rSz, *mpBmpEx );
560 // -----------------------
561 // - GraphicCache -
562 // -----------------------
564 GraphicCache::GraphicCache( GraphicManager& rMgr, ULONG nDisplayCacheSize, ULONG nMaxObjDisplayCacheSize ) :
565 mrMgr ( rMgr ),
566 mnReleaseTimeoutSeconds ( 0UL ),
567 mnMaxDisplaySize ( nDisplayCacheSize ),
568 mnMaxObjDisplaySize ( nMaxObjDisplayCacheSize ),
569 mnUsedDisplaySize ( 0UL )
571 maReleaseTimer.SetTimeoutHdl( LINK( this, GraphicCache, ReleaseTimeoutHdl ) );
572 maReleaseTimer.SetTimeout( RELEASE_TIMEOUT );
573 maReleaseTimer.Start();
576 // -----------------------------------------------------------------------------
578 GraphicCache::~GraphicCache()
580 DBG_ASSERT( !maGraphicCache.Count(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in cache" );
581 DBG_ASSERT( !maDisplayCache.Count(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in display cache" );
584 // -----------------------------------------------------------------------------
586 void GraphicCache::AddGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute,
587 const ByteString* pID, const GraphicObject* pCopyObj )
589 BOOL bInserted = FALSE;
591 if( !rObj.IsSwappedOut() &&
592 ( pID || ( pCopyObj && ( pCopyObj->GetType() != GRAPHIC_NONE ) ) || ( rObj.GetType() != GRAPHIC_NONE ) ) )
594 if( pCopyObj )
596 GraphicCacheEntry* pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() );
598 while( !bInserted && pEntry )
600 if( pEntry->HasGraphicObjectReference( *pCopyObj ) )
602 pEntry->AddGraphicObjectReference( rObj, rSubstitute );
603 bInserted = TRUE;
605 else
607 pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() );
612 if( !bInserted )
614 GraphicCacheEntry* pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() );
615 const GraphicID aID( rObj );
617 while( !bInserted && pEntry )
619 const GraphicID& rEntryID = pEntry->GetID();
621 if( pID )
623 if( rEntryID.GetIDString() == *pID )
625 pEntry->TryToSwapIn();
627 // since pEntry->TryToSwapIn can modify our current list, we have to
628 // iterate from beginning to add a reference to the appropriate
629 // CacheEntry object; after this, quickly jump out of the outer iteration
630 for( pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() );
631 !bInserted && pEntry;
632 pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() ) )
634 const GraphicID& rID = pEntry->GetID();
636 if( rID.GetIDString() == *pID )
638 pEntry->AddGraphicObjectReference( rObj, rSubstitute );
639 bInserted = TRUE;
643 if( !bInserted )
645 maGraphicCache.Insert( new GraphicCacheEntry( rObj ), LIST_APPEND );
646 bInserted = TRUE;
650 else if( rEntryID == aID )
652 pEntry->AddGraphicObjectReference( rObj, rSubstitute );
653 bInserted = TRUE;
656 if( !bInserted )
657 pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() );
662 if( !bInserted )
663 maGraphicCache.Insert( new GraphicCacheEntry( rObj ), LIST_APPEND );
666 // -----------------------------------------------------------------------------
668 void GraphicCache::ReleaseGraphicObject( const GraphicObject& rObj )
670 // Release cached object
671 GraphicCacheEntry* pEntry = (GraphicCacheEntry*) maGraphicCache.First();
672 BOOL bRemoved = FALSE;
674 while( !bRemoved && pEntry )
676 bRemoved = pEntry->ReleaseGraphicObjectReference( rObj );
678 if( bRemoved )
680 if( 0 == pEntry->GetGraphicObjectReferenceCount() )
682 // if graphic cache entry has no more references,
683 // the corresponding display cache object can be removed
684 GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
686 while( pDisplayEntry )
688 if( pDisplayEntry->GetReferencedCacheEntry() == pEntry )
690 mnUsedDisplaySize -= pDisplayEntry->GetCacheSize();
691 maDisplayCache.Remove( pDisplayEntry );
692 delete pDisplayEntry;
693 pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject();
695 else
696 pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
699 // delete graphic cache entry
700 maGraphicCache.Remove( (void*) pEntry );
701 delete pEntry;
704 else
705 pEntry = (GraphicCacheEntry*) maGraphicCache.Next();
708 DBG_ASSERT( bRemoved, "GraphicCache::ReleaseGraphicObject(...): GraphicObject not found in cache" );
711 // -----------------------------------------------------------------------------
713 void GraphicCache::GraphicObjectWasSwappedOut( const GraphicObject& rObj )
715 // notify cache that rObj is swapped out (and can thus be pruned
716 // from the cache)
717 GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
719 if( pEntry )
720 pEntry->GraphicObjectWasSwappedOut( rObj );
723 // -----------------------------------------------------------------------------
725 BOOL GraphicCache::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
727 GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
729 if( !pEntry )
730 return FALSE;
732 return pEntry->FillSwappedGraphicObject( rObj, rSubstitute );
735 // -----------------------------------------------------------------------------
737 void GraphicCache::GraphicObjectWasSwappedIn( const GraphicObject& rObj )
739 GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
741 if( pEntry )
743 if( pEntry->GetID().IsEmpty() )
745 ReleaseGraphicObject( rObj );
746 AddGraphicObject( rObj, (Graphic&) rObj.GetGraphic(), NULL, NULL );
748 else
749 pEntry->GraphicObjectWasSwappedIn( rObj );
753 // -----------------------------------------------------------------------------
755 void GraphicCache::SetMaxDisplayCacheSize( ULONG nNewCacheSize )
757 mnMaxDisplaySize = nNewCacheSize;
759 if( GetMaxDisplayCacheSize() < GetUsedDisplayCacheSize() )
760 ImplFreeDisplayCacheSpace( GetUsedDisplayCacheSize() - GetMaxDisplayCacheSize() );
763 // -----------------------------------------------------------------------------
765 void GraphicCache::SetMaxObjDisplayCacheSize( ULONG nNewMaxObjSize, BOOL bDestroyGreaterCached )
767 const BOOL bDestroy = ( bDestroyGreaterCached && ( nNewMaxObjSize < mnMaxObjDisplaySize ) );
769 mnMaxObjDisplaySize = Min( nNewMaxObjSize, mnMaxDisplaySize );
771 if( bDestroy )
773 GraphicDisplayCacheEntry* pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.First();
775 while( pCacheObj )
777 if( pCacheObj->GetCacheSize() > mnMaxObjDisplaySize )
779 mnUsedDisplaySize -= pCacheObj->GetCacheSize();
780 maDisplayCache.Remove( pCacheObj );
781 delete pCacheObj;
782 pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject();
784 else
785 pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
790 // -----------------------------------------------------------------------------
792 void GraphicCache::SetCacheTimeout( ULONG nTimeoutSeconds )
794 if( mnReleaseTimeoutSeconds != nTimeoutSeconds )
796 GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
797 ::vos::TTimeValue aReleaseTime;
799 if( ( mnReleaseTimeoutSeconds = nTimeoutSeconds ) != 0 )
801 osl_getSystemTime( &aReleaseTime );
802 aReleaseTime.addTime( ::vos::TTimeValue( nTimeoutSeconds, 0 ) );
805 while( pDisplayEntry )
807 pDisplayEntry->SetReleaseTime( aReleaseTime );
808 pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
813 // -----------------------------------------------------------------------------
815 void GraphicCache::ClearDisplayCache()
817 for( void* pObj = maDisplayCache.First(); pObj; pObj = maDisplayCache.Next() )
818 delete (GraphicDisplayCacheEntry*) pObj;
820 maDisplayCache.Clear();
821 mnUsedDisplaySize = 0UL;
824 // -----------------------------------------------------------------------------
826 BOOL GraphicCache::IsDisplayCacheable( OutputDevice* pOut, const Point& rPt, const Size& rSz,
827 const GraphicObject& rObj, const GraphicAttr& rAttr ) const
829 return( GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) <=
830 GetMaxObjDisplayCacheSize() );
833 // -----------------------------------------------------------------------------
835 BOOL GraphicCache::IsInDisplayCache( OutputDevice* pOut, const Point& rPt, const Size& rSz,
836 const GraphicObject& rObj, const GraphicAttr& rAttr ) const
838 const Point aPtPixel( pOut->LogicToPixel( rPt ) );
839 const Size aSzPixel( pOut->LogicToPixel( rSz ) );
840 const GraphicCacheEntry* pCacheEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
841 //GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) ( (GraphicCache*) this )->maDisplayCache.First(); // -Wall removed ....
842 BOOL bFound = FALSE;
844 if( pCacheEntry )
846 for( long i = 0, nCount = maDisplayCache.Count(); !bFound && ( i < nCount ); i++ )
847 if( ( (GraphicDisplayCacheEntry*) maDisplayCache.GetObject( i ) )->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) )
848 bFound = TRUE;
851 return bFound;
854 // -----------------------------------------------------------------------------
856 ByteString GraphicCache::GetUniqueID( const GraphicObject& rObj ) const
858 ByteString aRet;
859 GraphicCacheEntry* pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
861 // ensure that the entry is correctly initialized (it has to be read at least once)
862 if( pEntry && pEntry->GetID().IsEmpty() )
863 pEntry->TryToSwapIn();
865 // do another call to ImplGetCacheEntry in case of modified entry list
866 pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
868 if( pEntry )
869 aRet = pEntry->GetID().GetIDString();
871 return aRet;
874 // -----------------------------------------------------------------------------
876 BOOL GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
877 const GraphicObject& rObj, const GraphicAttr& rAttr,
878 const BitmapEx& rBmpEx )
880 const ULONG nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr );
881 BOOL bRet = FALSE;
883 if( nNeededSize <= GetMaxObjDisplayCacheSize() )
885 if( nNeededSize > GetFreeDisplayCacheSize() )
886 ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() );
888 GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ),
889 pOut, rPt, rSz, rObj, rAttr, rBmpEx );
891 if( GetCacheTimeout() )
893 ::vos::TTimeValue aReleaseTime;
895 osl_getSystemTime( &aReleaseTime );
896 aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) );
897 pNewEntry->SetReleaseTime( aReleaseTime );
900 maDisplayCache.Insert( pNewEntry, LIST_APPEND );
901 mnUsedDisplaySize += pNewEntry->GetCacheSize();
902 bRet = TRUE;
905 return bRet;
908 // -----------------------------------------------------------------------------
910 BOOL GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
911 const GraphicObject& rObj, const GraphicAttr& rAttr,
912 const GDIMetaFile& rMtf )
914 const ULONG nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr );
915 BOOL bRet = FALSE;
917 if( nNeededSize <= GetMaxObjDisplayCacheSize() )
919 if( nNeededSize > GetFreeDisplayCacheSize() )
920 ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() );
922 GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ),
923 pOut, rPt, rSz, rObj, rAttr, rMtf );
925 if( GetCacheTimeout() )
927 ::vos::TTimeValue aReleaseTime;
929 osl_getSystemTime( &aReleaseTime );
930 aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) );
931 pNewEntry->SetReleaseTime( aReleaseTime );
934 maDisplayCache.Insert( pNewEntry, LIST_APPEND );
935 mnUsedDisplaySize += pNewEntry->GetCacheSize();
936 bRet = TRUE;
939 return bRet;
942 // -----------------------------------------------------------------------------
944 BOOL GraphicCache::DrawDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
945 const GraphicObject& rObj, const GraphicAttr& rAttr )
947 const Point aPtPixel( pOut->LogicToPixel( rPt ) );
948 const Size aSzPixel( pOut->LogicToPixel( rSz ) );
949 const GraphicCacheEntry* pCacheEntry = ImplGetCacheEntry( rObj );
950 GraphicDisplayCacheEntry* pDisplayCacheEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
951 BOOL bRet = FALSE;
953 while( !bRet && pDisplayCacheEntry )
955 if( pDisplayCacheEntry->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) )
957 ::vos::TTimeValue aReleaseTime;
959 // put found object at last used position
960 maDisplayCache.Insert( maDisplayCache.Remove( pDisplayCacheEntry ), LIST_APPEND );
962 if( GetCacheTimeout() )
964 osl_getSystemTime( &aReleaseTime );
965 aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) );
968 pDisplayCacheEntry->SetReleaseTime( aReleaseTime );
969 bRet = TRUE;
971 else
972 pDisplayCacheEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
975 if( bRet )
976 pDisplayCacheEntry->Draw( pOut, rPt, rSz );
978 return bRet;
981 // -----------------------------------------------------------------------------
983 BOOL GraphicCache::ImplFreeDisplayCacheSpace( ULONG nSizeToFree )
985 ULONG nFreedSize = 0UL;
987 if( nSizeToFree )
989 void* pObj = maDisplayCache.First();
991 if( nSizeToFree > mnUsedDisplaySize )
992 nSizeToFree = mnUsedDisplaySize;
994 while( pObj )
996 GraphicDisplayCacheEntry* pCacheObj = (GraphicDisplayCacheEntry*) pObj;
998 nFreedSize += pCacheObj->GetCacheSize();
999 mnUsedDisplaySize -= pCacheObj->GetCacheSize();
1000 maDisplayCache.Remove( pObj );
1001 delete pCacheObj;
1003 if( nFreedSize >= nSizeToFree )
1004 break;
1005 else
1006 pObj = maDisplayCache.GetCurObject();
1010 return( nFreedSize >= nSizeToFree );
1013 // -----------------------------------------------------------------------------
1015 GraphicCacheEntry* GraphicCache::ImplGetCacheEntry( const GraphicObject& rObj )
1017 GraphicCacheEntry* pRet = NULL;
1019 for( void* pObj = maGraphicCache.First(); !pRet && pObj; pObj = maGraphicCache.Next() )
1020 if( ( (GraphicCacheEntry*) pObj )->HasGraphicObjectReference( rObj ) )
1021 pRet = (GraphicCacheEntry*) pObj;
1023 return pRet;
1026 // -----------------------------------------------------------------------------
1028 IMPL_LINK( GraphicCache, ReleaseTimeoutHdl, Timer*, pTimer )
1030 pTimer->Stop();
1032 ::vos::TTimeValue aCurTime;
1033 GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
1035 osl_getSystemTime( &aCurTime );
1037 while( pDisplayEntry )
1039 const ::vos::TTimeValue& rReleaseTime = pDisplayEntry->GetReleaseTime();
1041 if( !rReleaseTime.isEmpty() && ( rReleaseTime < aCurTime ) )
1043 mnUsedDisplaySize -= pDisplayEntry->GetCacheSize();
1044 maDisplayCache.Remove( pDisplayEntry );
1045 delete pDisplayEntry;
1046 pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject();
1048 else
1049 pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
1052 pTimer->Start();
1054 return 0;