1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
44 #define RELEASE_TIMEOUT 10000
45 #define MAX_BMP_EXTENT 4096
51 static const char aHexData
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
71 GraphicID( const GraphicObject
& rObj
);
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();
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();
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();
129 mnID2
= mnID3
= mnID4
= 0;
134 // -----------------------------------------------------------------------------
136 ByteString
GraphicID::GetIDString() const
139 sal_Char
* pStr
= aHexStr
.AllocBuffer( 32 );
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 ];
157 // ---------------------
158 // - GraphicCacheEntry -
159 // ---------------------
161 class GraphicCacheEntry
165 List maGraphicObjectList
;
170 Animation
* mpAnimation
;
173 BOOL
ImplInit( const GraphicObject
& rObj
);
174 BOOL
ImplMatches( const GraphicObject
& rObj
) const { return( GraphicID( rObj
) == maID
); }
175 void ImplFillSubstitute( Graphic
& rSubstitute
);
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
);
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
) :
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" );
218 // -----------------------------------------------------------------------------
220 BOOL
GraphicCacheEntry::ImplInit( const GraphicObject
& rObj
)
224 if( !rObj
.IsSwappedOut() )
226 const Graphic
& rGraphic
= rObj
.GetGraphic();
229 delete mpBmpEx
, mpBmpEx
= NULL
;
232 delete mpMtf
, mpMtf
= NULL
;
235 delete mpAnimation
, mpAnimation
= NULL
;
237 switch( rGraphic
.GetType() )
239 case( GRAPHIC_BITMAP
):
241 if( rGraphic
.IsAnimated() )
242 mpAnimation
= new Animation( rGraphic
.GetAnimation() );
244 mpBmpEx
= new BitmapEx( rGraphic
.GetBitmapEx() );
248 case( GRAPHIC_GDIMETAFILE
):
250 mpMtf
= new GDIMetaFile( rGraphic
.GetGDIMetaFile() );
255 DBG_ASSERT( GetID().IsEmpty(), "GraphicCacheEntry::ImplInit: Could not initialize graphic! (=>KA)" );
259 if( rGraphic
.IsLink() )
260 maGfxLink
= ( (Graphic
&) rGraphic
).GetLink();
262 maGfxLink
= GfxLink();
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();
289 rSubstitute
= *mpBmpEx
;
290 else if( mpAnimation
)
291 rSubstitute
= *mpAnimation
;
293 rSubstitute
= *mpMtf
;
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
);
309 rSubstitute
.SetDefaultType();
312 // -----------------------------------------------------------------------------
314 void GraphicCacheEntry::AddGraphicObjectReference( const GraphicObject
& rObj
, Graphic
& rSubstitute
)
317 mbSwappedAll
= !ImplInit( rObj
);
319 ImplFillSubstitute( rSubstitute
);
320 maGraphicObjectList
.Insert( (void*) &rObj
, LIST_APPEND
);
323 // -----------------------------------------------------------------------------
325 BOOL
GraphicCacheEntry::ReleaseGraphicObjectReference( const GraphicObject
& rObj
)
329 for( void* pObj
= maGraphicObjectList
.First(); !bRet
&& pObj
; pObj
= maGraphicObjectList
.Next() )
331 if( &rObj
== (GraphicObject
*) pObj
)
333 maGraphicObjectList
.Remove( pObj
);
341 // -----------------------------------------------------------------------------
343 BOOL
GraphicCacheEntry::HasGraphicObjectReference( const GraphicObject
& rObj
)
347 for( void* pObj
= maGraphicObjectList
.First(); !bRet
&& pObj
; pObj
= maGraphicObjectList
.Next() )
348 if( &rObj
== (GraphicObject
*) pObj
)
354 // -----------------------------------------------------------------------------
356 void GraphicCacheEntry::TryToSwapIn()
358 if( mbSwappedAll
&& maGraphicObjectList
.Count() )
359 ( (GraphicObject
*) maGraphicObjectList
.First() )->FireSwapInRequest();
362 // -----------------------------------------------------------------------------
364 void GraphicCacheEntry::GraphicObjectWasSwappedOut( const GraphicObject
& /*rObj*/ )
368 for( void* pObj
= maGraphicObjectList
.First(); mbSwappedAll
&& pObj
; pObj
= maGraphicObjectList
.Next() )
369 if( !( (GraphicObject
*) pObj
)->IsSwappedOut() )
370 mbSwappedAll
= FALSE
;
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
)
386 if( !mbSwappedAll
&& rObj
.IsSwappedOut() )
388 ImplFillSubstitute( rSubstitute
);
397 // -----------------------------------------------------------------------------
399 void GraphicCacheEntry::GraphicObjectWasSwappedIn( const GraphicObject
& rObj
)
402 mbSwappedAll
= !ImplInit( rObj
);
405 // ----------------------------
406 // - GraphicDisplayCacheEntry -
407 // ----------------------------
409 class GraphicDisplayCacheEntry
413 ::vos::TTimeValue maReleaseTime
;
414 const GraphicCacheEntry
* mpRefCacheEntry
;
420 ULONG mnOutDevDrawMode
;
421 USHORT mnOutDevBitCount
;
425 static ULONG
GetNeededSize( OutputDevice
* pOut
, const Point
& rPt
, const Size
& rSz
,
426 const GraphicObject
& rObj
, const GraphicAttr
& rAttr
);
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();
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
;
509 nNeededSize
= aOutSizePix
.Width() * aOutSizePix
.Height() * nBitCount
/ 8;
511 if( rObj
.IsTransparent() || ( rAttr
.GetRotation() % 3600 ) )
512 nNeededSize
+= nNeededSize
/ nBitCount
;
516 DBG_ERROR( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" );
517 nNeededSize
= 256000;
520 else if( GRAPHIC_GDIMETAFILE
== eType
)
521 nNeededSize
= rGraphic
.GetSizeBytes();
528 // -----------------------------------------------------------------------------
530 GraphicDisplayCacheEntry::~GraphicDisplayCacheEntry()
539 // -----------------------------------------------------------------------------
541 void GraphicDisplayCacheEntry::Draw( OutputDevice
* pOut
, const Point
& rPt
, const Size
& rSz
) const
544 GraphicManager::ImplDraw( pOut
, rPt
, rSz
, *mpMtf
, maAttr
);
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
);
556 pOut
->DrawBitmapEx( rPt
, rSz
, *mpBmpEx
);
560 // -----------------------
562 // -----------------------
564 GraphicCache::GraphicCache( GraphicManager
& rMgr
, ULONG nDisplayCacheSize
, ULONG nMaxObjDisplayCacheSize
) :
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
) ) )
596 GraphicCacheEntry
* pEntry
= static_cast< GraphicCacheEntry
* >( maGraphicCache
.First() );
598 while( !bInserted
&& pEntry
)
600 if( pEntry
->HasGraphicObjectReference( *pCopyObj
) )
602 pEntry
->AddGraphicObjectReference( rObj
, rSubstitute
);
607 pEntry
= static_cast< GraphicCacheEntry
* >( maGraphicCache
.Next() );
614 GraphicCacheEntry
* pEntry
= static_cast< GraphicCacheEntry
* >( maGraphicCache
.First() );
615 const GraphicID
aID( rObj
);
617 while( !bInserted
&& pEntry
)
619 const GraphicID
& rEntryID
= pEntry
->GetID();
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
);
645 maGraphicCache
.Insert( new GraphicCacheEntry( rObj
), LIST_APPEND
);
650 else if( rEntryID
== aID
)
652 pEntry
->AddGraphicObjectReference( rObj
, rSubstitute
);
657 pEntry
= static_cast< GraphicCacheEntry
* >( maGraphicCache
.Next() );
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
);
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();
696 pDisplayEntry
= (GraphicDisplayCacheEntry
*) maDisplayCache
.Next();
699 // delete graphic cache entry
700 maGraphicCache
.Remove( (void*) pEntry
);
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
717 GraphicCacheEntry
* pEntry
= ImplGetCacheEntry( rObj
);
720 pEntry
->GraphicObjectWasSwappedOut( rObj
);
723 // -----------------------------------------------------------------------------
725 BOOL
GraphicCache::FillSwappedGraphicObject( const GraphicObject
& rObj
, Graphic
& rSubstitute
)
727 GraphicCacheEntry
* pEntry
= ImplGetCacheEntry( rObj
);
732 return pEntry
->FillSwappedGraphicObject( rObj
, rSubstitute
);
735 // -----------------------------------------------------------------------------
737 void GraphicCache::GraphicObjectWasSwappedIn( const GraphicObject
& rObj
)
739 GraphicCacheEntry
* pEntry
= ImplGetCacheEntry( rObj
);
743 if( pEntry
->GetID().IsEmpty() )
745 ReleaseGraphicObject( rObj
);
746 AddGraphicObject( rObj
, (Graphic
&) rObj
.GetGraphic(), NULL
, NULL
);
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
);
773 GraphicDisplayCacheEntry
* pCacheObj
= (GraphicDisplayCacheEntry
*) maDisplayCache
.First();
777 if( pCacheObj
->GetCacheSize() > mnMaxObjDisplaySize
)
779 mnUsedDisplaySize
-= pCacheObj
->GetCacheSize();
780 maDisplayCache
.Remove( pCacheObj
);
782 pCacheObj
= (GraphicDisplayCacheEntry
*) maDisplayCache
.GetCurObject();
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 ....
846 for( long i
= 0, nCount
= maDisplayCache
.Count(); !bFound
&& ( i
< nCount
); i
++ )
847 if( ( (GraphicDisplayCacheEntry
*) maDisplayCache
.GetObject( i
) )->Matches( pOut
, aPtPixel
, aSzPixel
, pCacheEntry
, rAttr
) )
854 // -----------------------------------------------------------------------------
856 ByteString
GraphicCache::GetUniqueID( const GraphicObject
& rObj
) const
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
);
869 aRet
= pEntry
->GetID().GetIDString();
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
);
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();
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
);
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();
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();
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
);
972 pDisplayCacheEntry
= (GraphicDisplayCacheEntry
*) maDisplayCache
.Next();
976 pDisplayCacheEntry
->Draw( pOut
, rPt
, rSz
);
981 // -----------------------------------------------------------------------------
983 BOOL
GraphicCache::ImplFreeDisplayCacheSpace( ULONG nSizeToFree
)
985 ULONG nFreedSize
= 0UL;
989 void* pObj
= maDisplayCache
.First();
991 if( nSizeToFree
> mnUsedDisplaySize
)
992 nSizeToFree
= mnUsedDisplaySize
;
996 GraphicDisplayCacheEntry
* pCacheObj
= (GraphicDisplayCacheEntry
*) pObj
;
998 nFreedSize
+= pCacheObj
->GetCacheSize();
999 mnUsedDisplaySize
-= pCacheObj
->GetCacheSize();
1000 maDisplayCache
.Remove( pObj
);
1003 if( nFreedSize
>= nSizeToFree
)
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
;
1026 // -----------------------------------------------------------------------------
1028 IMPL_LINK( GraphicCache
, ReleaseTimeoutHdl
, Timer
*, pTimer
)
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();
1049 pDisplayEntry
= (GraphicDisplayCacheEntry
*) maDisplayCache
.Next();