1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_svtools.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <vos/timer.hxx>
32*cdf0e10cSrcweir #include <tools/debug.hxx>
33*cdf0e10cSrcweir #include <vcl/outdev.hxx>
34*cdf0e10cSrcweir #include <tools/poly.hxx>
35*cdf0e10cSrcweir #include "grfcache.hxx"
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include <memory>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir // -----------
40*cdf0e10cSrcweir // - Defines -
41*cdf0e10cSrcweir // -----------
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #define RELEASE_TIMEOUT 10000
44*cdf0e10cSrcweir #define MAX_BMP_EXTENT	4096
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir // -----------
47*cdf0e10cSrcweir // - statics -
48*cdf0e10cSrcweir // -----------
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir static const char aHexData[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir // -------------
53*cdf0e10cSrcweir // - GraphicID -
54*cdf0e10cSrcweir // -------------
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir class GraphicID
57*cdf0e10cSrcweir {
58*cdf0e10cSrcweir private:
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir 	sal_uInt32	mnID1;
61*cdf0e10cSrcweir 	sal_uInt32	mnID2;
62*cdf0e10cSrcweir 	sal_uInt32	mnID3;
63*cdf0e10cSrcweir 	sal_uInt32	mnID4;
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir 				GraphicID();
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir public:
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir 				GraphicID( const GraphicObject& rObj );
71*cdf0e10cSrcweir 				~GraphicID() {}
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir 	sal_Bool		operator==( const GraphicID& rID ) const
74*cdf0e10cSrcweir 				{
75*cdf0e10cSrcweir 					return( rID.mnID1 == mnID1 && rID.mnID2 == mnID2 &&
76*cdf0e10cSrcweir 							rID.mnID3 == mnID3 && rID.mnID4 == mnID4 );
77*cdf0e10cSrcweir 				}
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir 	ByteString	GetIDString() const;
80*cdf0e10cSrcweir     sal_Bool        IsEmpty() const { return( 0 == mnID4 ); }
81*cdf0e10cSrcweir };
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir // -----------------------------------------------------------------------------
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir GraphicID::GraphicID( const GraphicObject& rObj )
86*cdf0e10cSrcweir {
87*cdf0e10cSrcweir 	const Graphic& rGraphic = rObj.GetGraphic();
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir 	mnID1 = ( (sal_uLong) rGraphic.GetType() ) << 28;
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir 	switch( rGraphic.GetType() )
92*cdf0e10cSrcweir 	{
93*cdf0e10cSrcweir 		case( GRAPHIC_BITMAP ):
94*cdf0e10cSrcweir 		{
95*cdf0e10cSrcweir 			if( rGraphic.IsAnimated() )
96*cdf0e10cSrcweir 			{
97*cdf0e10cSrcweir 				const Animation aAnimation( rGraphic.GetAnimation() );
98*cdf0e10cSrcweir 
99*cdf0e10cSrcweir 				mnID1 |= ( aAnimation.Count() & 0x0fffffff );
100*cdf0e10cSrcweir 				mnID2 = aAnimation.GetDisplaySizePixel().Width();
101*cdf0e10cSrcweir 				mnID3 = aAnimation.GetDisplaySizePixel().Height();
102*cdf0e10cSrcweir 				mnID4 = rGraphic.GetChecksum();
103*cdf0e10cSrcweir 			}
104*cdf0e10cSrcweir 			else
105*cdf0e10cSrcweir 			{
106*cdf0e10cSrcweir 				const BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir 				mnID1 |= ( ( ( (sal_uLong) aBmpEx.GetTransparentType() << 8 ) | ( aBmpEx.IsAlpha() ? 1 : 0 ) ) & 0x0fffffff );
109*cdf0e10cSrcweir 				mnID2 = aBmpEx.GetSizePixel().Width();
110*cdf0e10cSrcweir 				mnID3 = aBmpEx.GetSizePixel().Height();
111*cdf0e10cSrcweir 				mnID4 = rGraphic.GetChecksum();
112*cdf0e10cSrcweir 			}
113*cdf0e10cSrcweir 		}
114*cdf0e10cSrcweir 		break;
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir 		case( GRAPHIC_GDIMETAFILE ):
117*cdf0e10cSrcweir 		{
118*cdf0e10cSrcweir 			const GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir 			mnID1 |= ( aMtf.GetActionCount() & 0x0fffffff );
121*cdf0e10cSrcweir 			mnID2 = aMtf.GetPrefSize().Width();
122*cdf0e10cSrcweir 			mnID3 = aMtf.GetPrefSize().Height();
123*cdf0e10cSrcweir 			mnID4 = rGraphic.GetChecksum();
124*cdf0e10cSrcweir 		}
125*cdf0e10cSrcweir 		break;
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir 		default:
128*cdf0e10cSrcweir 			mnID2 = mnID3 = mnID4 = 0;
129*cdf0e10cSrcweir 		break;
130*cdf0e10cSrcweir 	}
131*cdf0e10cSrcweir }
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir // -----------------------------------------------------------------------------
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir ByteString GraphicID::GetIDString() const
136*cdf0e10cSrcweir {
137*cdf0e10cSrcweir 	ByteString	aHexStr;
138*cdf0e10cSrcweir 	sal_Char*	pStr = aHexStr.AllocBuffer( 32 );
139*cdf0e10cSrcweir 	sal_Int32	nShift;
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir 	for( nShift = 28; nShift >= 0; nShift -= 4 )
142*cdf0e10cSrcweir 		*pStr++ = aHexData[ ( mnID1 >> (sal_uInt32) nShift ) & 0xf ];
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir 	for( nShift = 28; nShift >= 0; nShift -= 4 )
145*cdf0e10cSrcweir 		*pStr++ = aHexData[ ( mnID2 >> (sal_uInt32) nShift ) & 0xf ];
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir 	for( nShift = 28; nShift >= 0; nShift -= 4 )
148*cdf0e10cSrcweir 		*pStr++ = aHexData[ ( mnID3 >> (sal_uInt32) nShift ) & 0xf ];
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir 	for( nShift = 28; nShift >= 0; nShift -= 4 )
151*cdf0e10cSrcweir 		*pStr++ = aHexData[ ( mnID4 >> (sal_uInt32) nShift ) & 0xf ];
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir 	return aHexStr;
154*cdf0e10cSrcweir }
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir // ---------------------
157*cdf0e10cSrcweir // - GraphicCacheEntry -
158*cdf0e10cSrcweir // ---------------------
159*cdf0e10cSrcweir 
160*cdf0e10cSrcweir class GraphicCacheEntry
161*cdf0e10cSrcweir {
162*cdf0e10cSrcweir private:
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir 	List				maGraphicObjectList;
165*cdf0e10cSrcweir 	GraphicID			maID;
166*cdf0e10cSrcweir 	GfxLink				maGfxLink;
167*cdf0e10cSrcweir 	BitmapEx*			mpBmpEx;
168*cdf0e10cSrcweir 	GDIMetaFile*		mpMtf;
169*cdf0e10cSrcweir 	Animation*			mpAnimation;
170*cdf0e10cSrcweir 	sal_Bool				mbSwappedAll;
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir 	sal_Bool				ImplInit( const GraphicObject& rObj );
173*cdf0e10cSrcweir 	sal_Bool				ImplMatches( const GraphicObject& rObj ) const { return( GraphicID( rObj ) == maID ); }
174*cdf0e10cSrcweir 	void				ImplFillSubstitute( Graphic& rSubstitute );
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir public:
177*cdf0e10cSrcweir 
178*cdf0e10cSrcweir 						GraphicCacheEntry( const GraphicObject& rObj );
179*cdf0e10cSrcweir 						~GraphicCacheEntry();
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir 	const GraphicID&	GetID() const { return maID; }
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir 	void				AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute );
184*cdf0e10cSrcweir 	sal_Bool				ReleaseGraphicObjectReference( const GraphicObject& rObj );
185*cdf0e10cSrcweir 	sal_uLong				GetGraphicObjectReferenceCount() { return maGraphicObjectList.Count(); }
186*cdf0e10cSrcweir 	sal_Bool				HasGraphicObjectReference( const GraphicObject& rObj );
187*cdf0e10cSrcweir 
188*cdf0e10cSrcweir 	void				TryToSwapIn();
189*cdf0e10cSrcweir 	void				GraphicObjectWasSwappedOut( const GraphicObject& rObj );
190*cdf0e10cSrcweir 	sal_Bool				FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute );
191*cdf0e10cSrcweir 	void				GraphicObjectWasSwappedIn( const GraphicObject& rObj );
192*cdf0e10cSrcweir };
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir // -----------------------------------------------------------------------------
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir GraphicCacheEntry::GraphicCacheEntry( const GraphicObject& rObj ) :
197*cdf0e10cSrcweir 	maID			( rObj ),
198*cdf0e10cSrcweir 	mpBmpEx			( NULL ),
199*cdf0e10cSrcweir 	mpMtf			( NULL ),
200*cdf0e10cSrcweir 	mpAnimation		( NULL ),
201*cdf0e10cSrcweir 	mbSwappedAll    ( !ImplInit( rObj ) )
202*cdf0e10cSrcweir {
203*cdf0e10cSrcweir 	maGraphicObjectList.Insert( (void*) &rObj, LIST_APPEND );
204*cdf0e10cSrcweir }
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir // -----------------------------------------------------------------------------
207*cdf0e10cSrcweir 
208*cdf0e10cSrcweir GraphicCacheEntry::~GraphicCacheEntry()
209*cdf0e10cSrcweir {
210*cdf0e10cSrcweir 	DBG_ASSERT( !maGraphicObjectList.Count(), "GraphicCacheEntry::~GraphicCacheEntry(): Not all GraphicObjects are removed from this entry" );
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir 	delete mpBmpEx;
213*cdf0e10cSrcweir 	delete mpMtf;
214*cdf0e10cSrcweir 	delete mpAnimation;
215*cdf0e10cSrcweir }
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir // -----------------------------------------------------------------------------
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir sal_Bool GraphicCacheEntry::ImplInit( const GraphicObject& rObj )
220*cdf0e10cSrcweir {
221*cdf0e10cSrcweir 	sal_Bool bRet;
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir 	if( !rObj.IsSwappedOut() )
224*cdf0e10cSrcweir 	{
225*cdf0e10cSrcweir 		const Graphic& rGraphic = rObj.GetGraphic();
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir 		if( mpBmpEx )
228*cdf0e10cSrcweir 			delete mpBmpEx, mpBmpEx = NULL;
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir 		if( mpMtf )
231*cdf0e10cSrcweir 			delete mpMtf, mpMtf = NULL;
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir 		if( mpAnimation )
234*cdf0e10cSrcweir 			delete mpAnimation, mpAnimation = NULL;
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir 		switch( rGraphic.GetType() )
237*cdf0e10cSrcweir 		{
238*cdf0e10cSrcweir 			case( GRAPHIC_BITMAP ):
239*cdf0e10cSrcweir 			{
240*cdf0e10cSrcweir 				if( rGraphic.IsAnimated() )
241*cdf0e10cSrcweir 					mpAnimation = new Animation( rGraphic.GetAnimation() );
242*cdf0e10cSrcweir 				else
243*cdf0e10cSrcweir 					mpBmpEx = new BitmapEx( rGraphic.GetBitmapEx() );
244*cdf0e10cSrcweir 			}
245*cdf0e10cSrcweir 			break;
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir 			case( GRAPHIC_GDIMETAFILE ):
248*cdf0e10cSrcweir 			{
249*cdf0e10cSrcweir 				mpMtf = new GDIMetaFile( rGraphic.GetGDIMetaFile() );
250*cdf0e10cSrcweir 			}
251*cdf0e10cSrcweir 			break;
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 			default:
254*cdf0e10cSrcweir 				DBG_ASSERT( GetID().IsEmpty(), "GraphicCacheEntry::ImplInit: Could not initialize graphic! (=>KA)" );
255*cdf0e10cSrcweir 			break;
256*cdf0e10cSrcweir 		}
257*cdf0e10cSrcweir 
258*cdf0e10cSrcweir 		if( rGraphic.IsLink() )
259*cdf0e10cSrcweir 			maGfxLink = ( (Graphic&) rGraphic ).GetLink();
260*cdf0e10cSrcweir 		else
261*cdf0e10cSrcweir 			maGfxLink = GfxLink();
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir 		bRet = sal_True;
264*cdf0e10cSrcweir 	}
265*cdf0e10cSrcweir 	else
266*cdf0e10cSrcweir 		bRet = sal_False;
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir 	return bRet;
269*cdf0e10cSrcweir }
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir // -----------------------------------------------------------------------------
272*cdf0e10cSrcweir 
273*cdf0e10cSrcweir void GraphicCacheEntry::ImplFillSubstitute( Graphic& rSubstitute )
274*cdf0e10cSrcweir {
275*cdf0e10cSrcweir 	// create substitute for graphic;
276*cdf0e10cSrcweir 	const Size			aPrefSize( rSubstitute.GetPrefSize() );
277*cdf0e10cSrcweir 	const MapMode		aPrefMapMode( rSubstitute.GetPrefMapMode() );
278*cdf0e10cSrcweir 	const Link			aAnimationNotifyHdl( rSubstitute.GetAnimationNotifyHdl() );
279*cdf0e10cSrcweir 	const String		aDocFileName( rSubstitute.GetDocFileName() );
280*cdf0e10cSrcweir 	const sal_uLong			nDocFilePos = rSubstitute.GetDocFilePos();
281*cdf0e10cSrcweir 	const GraphicType	eOldType = rSubstitute.GetType();
282*cdf0e10cSrcweir 	const sal_Bool			bDefaultType = ( rSubstitute.GetType() == GRAPHIC_DEFAULT );
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir 	if( rSubstitute.IsLink() && ( GFX_LINK_TYPE_NONE == maGfxLink.GetType() ) )
285*cdf0e10cSrcweir 		maGfxLink = rSubstitute.GetLink();
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir 	if( mpBmpEx )
288*cdf0e10cSrcweir 		rSubstitute = *mpBmpEx;
289*cdf0e10cSrcweir 	else if( mpAnimation )
290*cdf0e10cSrcweir 		rSubstitute = *mpAnimation;
291*cdf0e10cSrcweir 	else if( mpMtf )
292*cdf0e10cSrcweir 		rSubstitute = *mpMtf;
293*cdf0e10cSrcweir 	else
294*cdf0e10cSrcweir 		rSubstitute.Clear();
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir 	if( eOldType != GRAPHIC_NONE )
297*cdf0e10cSrcweir 	{
298*cdf0e10cSrcweir 		rSubstitute.SetPrefSize( aPrefSize );
299*cdf0e10cSrcweir 		rSubstitute.SetPrefMapMode( aPrefMapMode );
300*cdf0e10cSrcweir 		rSubstitute.SetAnimationNotifyHdl( aAnimationNotifyHdl );
301*cdf0e10cSrcweir 		rSubstitute.SetDocFileName( aDocFileName, nDocFilePos );
302*cdf0e10cSrcweir 	}
303*cdf0e10cSrcweir 
304*cdf0e10cSrcweir 	if( GFX_LINK_TYPE_NONE != maGfxLink.GetType() )
305*cdf0e10cSrcweir 		rSubstitute.SetLink( maGfxLink );
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir 	if( bDefaultType )
308*cdf0e10cSrcweir 		rSubstitute.SetDefaultType();
309*cdf0e10cSrcweir }
310*cdf0e10cSrcweir 
311*cdf0e10cSrcweir // -----------------------------------------------------------------------------
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir void GraphicCacheEntry::AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute )
314*cdf0e10cSrcweir {
315*cdf0e10cSrcweir 	if( mbSwappedAll )
316*cdf0e10cSrcweir 		mbSwappedAll = !ImplInit( rObj );
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir 	ImplFillSubstitute( rSubstitute );
319*cdf0e10cSrcweir 	maGraphicObjectList.Insert( (void*) &rObj, LIST_APPEND );
320*cdf0e10cSrcweir }
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir // -----------------------------------------------------------------------------
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir sal_Bool GraphicCacheEntry::ReleaseGraphicObjectReference( const GraphicObject& rObj )
325*cdf0e10cSrcweir {
326*cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
327*cdf0e10cSrcweir 
328*cdf0e10cSrcweir 	for( void* pObj = maGraphicObjectList.First(); !bRet && pObj; pObj = maGraphicObjectList.Next() )
329*cdf0e10cSrcweir 	{
330*cdf0e10cSrcweir 		if( &rObj == (GraphicObject*) pObj )
331*cdf0e10cSrcweir 		{
332*cdf0e10cSrcweir 			maGraphicObjectList.Remove( pObj );
333*cdf0e10cSrcweir 			bRet = sal_True;
334*cdf0e10cSrcweir 		}
335*cdf0e10cSrcweir 	}
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir 	return bRet;
338*cdf0e10cSrcweir }
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir // -----------------------------------------------------------------------------
341*cdf0e10cSrcweir 
342*cdf0e10cSrcweir sal_Bool GraphicCacheEntry::HasGraphicObjectReference( const GraphicObject& rObj )
343*cdf0e10cSrcweir {
344*cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
345*cdf0e10cSrcweir 
346*cdf0e10cSrcweir 	for( void* pObj = maGraphicObjectList.First(); !bRet && pObj; pObj = maGraphicObjectList.Next() )
347*cdf0e10cSrcweir 		if( &rObj == (GraphicObject*) pObj )
348*cdf0e10cSrcweir 			bRet = sal_True;
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir 	return bRet;
351*cdf0e10cSrcweir }
352*cdf0e10cSrcweir 
353*cdf0e10cSrcweir // -----------------------------------------------------------------------------
354*cdf0e10cSrcweir 
355*cdf0e10cSrcweir void GraphicCacheEntry::TryToSwapIn()
356*cdf0e10cSrcweir {
357*cdf0e10cSrcweir 	if( mbSwappedAll && maGraphicObjectList.Count() )
358*cdf0e10cSrcweir 		( (GraphicObject*) maGraphicObjectList.First() )->FireSwapInRequest();
359*cdf0e10cSrcweir }
360*cdf0e10cSrcweir 
361*cdf0e10cSrcweir // -----------------------------------------------------------------------------
362*cdf0e10cSrcweir 
363*cdf0e10cSrcweir void GraphicCacheEntry::GraphicObjectWasSwappedOut( const GraphicObject& /*rObj*/ )
364*cdf0e10cSrcweir {
365*cdf0e10cSrcweir 	mbSwappedAll = sal_True;
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir 	for( void* pObj = maGraphicObjectList.First(); mbSwappedAll && pObj; pObj = maGraphicObjectList.Next() )
368*cdf0e10cSrcweir 		if( !( (GraphicObject*) pObj )->IsSwappedOut() )
369*cdf0e10cSrcweir 			mbSwappedAll = sal_False;
370*cdf0e10cSrcweir 
371*cdf0e10cSrcweir 	if( mbSwappedAll )
372*cdf0e10cSrcweir 	{
373*cdf0e10cSrcweir 		delete mpBmpEx, mpBmpEx = NULL;
374*cdf0e10cSrcweir 		delete mpMtf, mpMtf = NULL;
375*cdf0e10cSrcweir 		delete mpAnimation, mpAnimation = NULL;
376*cdf0e10cSrcweir 	}
377*cdf0e10cSrcweir }
378*cdf0e10cSrcweir 
379*cdf0e10cSrcweir // -----------------------------------------------------------------------------
380*cdf0e10cSrcweir 
381*cdf0e10cSrcweir sal_Bool GraphicCacheEntry::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
382*cdf0e10cSrcweir {
383*cdf0e10cSrcweir 	sal_Bool bRet;
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir 	if( !mbSwappedAll && rObj.IsSwappedOut() )
386*cdf0e10cSrcweir 	{
387*cdf0e10cSrcweir 		ImplFillSubstitute( rSubstitute );
388*cdf0e10cSrcweir 		bRet = sal_True;
389*cdf0e10cSrcweir 	}
390*cdf0e10cSrcweir 	else
391*cdf0e10cSrcweir 		bRet = sal_False;
392*cdf0e10cSrcweir 
393*cdf0e10cSrcweir 	return bRet;
394*cdf0e10cSrcweir }
395*cdf0e10cSrcweir 
396*cdf0e10cSrcweir // -----------------------------------------------------------------------------
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir void GraphicCacheEntry::GraphicObjectWasSwappedIn( const GraphicObject& rObj )
399*cdf0e10cSrcweir {
400*cdf0e10cSrcweir 	if( mbSwappedAll )
401*cdf0e10cSrcweir 		mbSwappedAll = !ImplInit( rObj );
402*cdf0e10cSrcweir }
403*cdf0e10cSrcweir 
404*cdf0e10cSrcweir // ----------------------------
405*cdf0e10cSrcweir // - GraphicDisplayCacheEntry -
406*cdf0e10cSrcweir // ----------------------------
407*cdf0e10cSrcweir 
408*cdf0e10cSrcweir class GraphicDisplayCacheEntry
409*cdf0e10cSrcweir {
410*cdf0e10cSrcweir private:
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir 	::vos::TTimeValue           maReleaseTime;
413*cdf0e10cSrcweir     const GraphicCacheEntry*	mpRefCacheEntry;
414*cdf0e10cSrcweir 	GDIMetaFile*				mpMtf;
415*cdf0e10cSrcweir 	BitmapEx*					mpBmpEx;
416*cdf0e10cSrcweir 	GraphicAttr					maAttr;
417*cdf0e10cSrcweir 	Size						maOutSizePix;
418*cdf0e10cSrcweir 	sal_uLong						mnCacheSize;
419*cdf0e10cSrcweir     sal_uLong						mnOutDevDrawMode;
420*cdf0e10cSrcweir     sal_uInt16						mnOutDevBitCount;
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir public:
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir 	static sal_uLong				GetNeededSize( OutputDevice* pOut, const Point& rPt, const Size& rSz,
425*cdf0e10cSrcweir 											   const GraphicObject& rObj, const GraphicAttr& rAttr );
426*cdf0e10cSrcweir 
427*cdf0e10cSrcweir public:
428*cdf0e10cSrcweir 
429*cdf0e10cSrcweir 								GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry,
430*cdf0e10cSrcweir 														  OutputDevice* pOut, const Point& rPt, const Size& rSz,
431*cdf0e10cSrcweir 														  const GraphicObject& rObj, const GraphicAttr& rAttr,
432*cdf0e10cSrcweir 														  const BitmapEx& rBmpEx ) :
433*cdf0e10cSrcweir 									mpRefCacheEntry( pRefCacheEntry ),
434*cdf0e10cSrcweir 									mpMtf( NULL ), mpBmpEx( new BitmapEx( rBmpEx ) ),
435*cdf0e10cSrcweir 									maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ),
436*cdf0e10cSrcweir 									mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ),
437*cdf0e10cSrcweir                                     mnOutDevDrawMode( pOut->GetDrawMode() ),
438*cdf0e10cSrcweir                                     mnOutDevBitCount( pOut->GetBitCount() )
439*cdf0e10cSrcweir                                     {
440*cdf0e10cSrcweir                                     }
441*cdf0e10cSrcweir 
442*cdf0e10cSrcweir 								GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry,
443*cdf0e10cSrcweir 														  OutputDevice* pOut, const Point& rPt, const Size& rSz,
444*cdf0e10cSrcweir 														  const GraphicObject& rObj, const GraphicAttr& rAttr,
445*cdf0e10cSrcweir 														  const GDIMetaFile& rMtf ) :
446*cdf0e10cSrcweir 									mpRefCacheEntry( pRefCacheEntry ),
447*cdf0e10cSrcweir 									mpMtf( new GDIMetaFile( rMtf ) ), mpBmpEx( NULL ),
448*cdf0e10cSrcweir 									maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ),
449*cdf0e10cSrcweir 									mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ),
450*cdf0e10cSrcweir                                     mnOutDevDrawMode( pOut->GetDrawMode() ),
451*cdf0e10cSrcweir                                     mnOutDevBitCount( pOut->GetBitCount() )
452*cdf0e10cSrcweir                                     {
453*cdf0e10cSrcweir                                     }
454*cdf0e10cSrcweir 
455*cdf0e10cSrcweir 
456*cdf0e10cSrcweir 								~GraphicDisplayCacheEntry();
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir 	const GraphicAttr&			GetAttr() const { return maAttr; }
459*cdf0e10cSrcweir 	const Size&					GetOutputSizePixel() const { return maOutSizePix; }
460*cdf0e10cSrcweir 	sal_uLong					GetCacheSize() const { return mnCacheSize; }
461*cdf0e10cSrcweir 	const GraphicCacheEntry*	GetReferencedCacheEntry() const { return mpRefCacheEntry; }
462*cdf0e10cSrcweir     sal_uLong					GetOutDevDrawMode() const { return mnOutDevDrawMode; }
463*cdf0e10cSrcweir     sal_uInt16				GetOutDevBitCount()	const { return mnOutDevBitCount; }
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir     void                        SetReleaseTime( const ::vos::TTimeValue& rReleaseTime ) { maReleaseTime = rReleaseTime; }
466*cdf0e10cSrcweir     const ::vos::TTimeValue&    GetReleaseTime() const { return maReleaseTime; }
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir 	sal_Bool						Matches( OutputDevice* pOut, const Point& /*rPtPixel*/, const Size& rSzPixel,
469*cdf0e10cSrcweir 										 const GraphicCacheEntry* pCacheEntry, const GraphicAttr& rAttr ) const
470*cdf0e10cSrcweir 								{
471*cdf0e10cSrcweir                                     // #i46805# Additional match
472*cdf0e10cSrcweir                                     // criteria: outdev draw mode and
473*cdf0e10cSrcweir                                     // bit count. One cannot reuse
474*cdf0e10cSrcweir                                     // this cache object, if it's
475*cdf0e10cSrcweir                                     // e.g. generated for
476*cdf0e10cSrcweir                                     // DRAWMODE_GRAYBITMAP.
477*cdf0e10cSrcweir 									return( ( pCacheEntry == mpRefCacheEntry ) &&
478*cdf0e10cSrcweir 											( maAttr == rAttr ) &&
479*cdf0e10cSrcweir 											( ( maOutSizePix == rSzPixel ) || ( !maOutSizePix.Width() && !maOutSizePix.Height() ) ) &&
480*cdf0e10cSrcweir                                             ( pOut->GetBitCount() == mnOutDevBitCount ) &&
481*cdf0e10cSrcweir                                             ( pOut->GetDrawMode() == mnOutDevDrawMode ) );
482*cdf0e10cSrcweir 								}
483*cdf0e10cSrcweir 
484*cdf0e10cSrcweir 	void						Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const;
485*cdf0e10cSrcweir };
486*cdf0e10cSrcweir 
487*cdf0e10cSrcweir // -----------------------------------------------------------------------------
488*cdf0e10cSrcweir 
489*cdf0e10cSrcweir sal_uLong GraphicDisplayCacheEntry::GetNeededSize( OutputDevice* pOut, const Point& /*rPt*/, const Size& rSz,
490*cdf0e10cSrcweir 											   const GraphicObject& rObj, const GraphicAttr& rAttr )
491*cdf0e10cSrcweir {
492*cdf0e10cSrcweir     const Graphic&      rGraphic = rObj.GetGraphic();
493*cdf0e10cSrcweir     const GraphicType	eType = rGraphic.GetType();
494*cdf0e10cSrcweir 	sal_uLong				nNeededSize;
495*cdf0e10cSrcweir 
496*cdf0e10cSrcweir 	if( GRAPHIC_BITMAP == eType )
497*cdf0e10cSrcweir 	{
498*cdf0e10cSrcweir 		const Size aOutSizePix( pOut->LogicToPixel( rSz ) );
499*cdf0e10cSrcweir 		const long nBitCount = pOut->GetBitCount();
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir 		if( ( aOutSizePix.Width() > MAX_BMP_EXTENT ) ||
502*cdf0e10cSrcweir             ( aOutSizePix.Height() > MAX_BMP_EXTENT ) )
503*cdf0e10cSrcweir         {
504*cdf0e10cSrcweir 		    nNeededSize = ULONG_MAX;
505*cdf0e10cSrcweir         }
506*cdf0e10cSrcweir 		else if( nBitCount )
507*cdf0e10cSrcweir 		{
508*cdf0e10cSrcweir 		    nNeededSize = aOutSizePix.Width() * aOutSizePix.Height() * nBitCount / 8;
509*cdf0e10cSrcweir 
510*cdf0e10cSrcweir     		if( rObj.IsTransparent() || ( rAttr.GetRotation() % 3600 ) )
511*cdf0e10cSrcweir 	    		nNeededSize += nNeededSize / nBitCount;
512*cdf0e10cSrcweir 		}
513*cdf0e10cSrcweir 		else
514*cdf0e10cSrcweir 	    {
515*cdf0e10cSrcweir      		DBG_ERROR( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" );
516*cdf0e10cSrcweir 		    nNeededSize = 256000;
517*cdf0e10cSrcweir         }
518*cdf0e10cSrcweir 	}
519*cdf0e10cSrcweir 	else if( GRAPHIC_GDIMETAFILE == eType )
520*cdf0e10cSrcweir 		nNeededSize = rGraphic.GetSizeBytes();
521*cdf0e10cSrcweir 	else
522*cdf0e10cSrcweir 		nNeededSize = 0;
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir 	return nNeededSize;
525*cdf0e10cSrcweir }
526*cdf0e10cSrcweir 
527*cdf0e10cSrcweir // -----------------------------------------------------------------------------
528*cdf0e10cSrcweir 
529*cdf0e10cSrcweir GraphicDisplayCacheEntry::~GraphicDisplayCacheEntry()
530*cdf0e10cSrcweir {
531*cdf0e10cSrcweir 	if( mpMtf )
532*cdf0e10cSrcweir 		delete mpMtf;
533*cdf0e10cSrcweir 
534*cdf0e10cSrcweir 	if( mpBmpEx )
535*cdf0e10cSrcweir 		delete mpBmpEx;
536*cdf0e10cSrcweir }
537*cdf0e10cSrcweir 
538*cdf0e10cSrcweir // -----------------------------------------------------------------------------
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir void GraphicDisplayCacheEntry::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const
541*cdf0e10cSrcweir {
542*cdf0e10cSrcweir 	if( mpMtf )
543*cdf0e10cSrcweir 		GraphicManager::ImplDraw( pOut, rPt, rSz, *mpMtf, maAttr );
544*cdf0e10cSrcweir 	else if( mpBmpEx )
545*cdf0e10cSrcweir 	{
546*cdf0e10cSrcweir 		if( maAttr.IsRotated() )
547*cdf0e10cSrcweir 		{
548*cdf0e10cSrcweir 			Polygon aPoly( Rectangle( rPt, rSz ) );
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir 			aPoly.Rotate( rPt, maAttr.GetRotation() % 3600 );
551*cdf0e10cSrcweir 			const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
552*cdf0e10cSrcweir 			pOut->DrawBitmapEx( aRotBoundRect.TopLeft(), aRotBoundRect.GetSize(), *mpBmpEx );
553*cdf0e10cSrcweir 		}
554*cdf0e10cSrcweir 		else
555*cdf0e10cSrcweir 			pOut->DrawBitmapEx( rPt, rSz, *mpBmpEx );
556*cdf0e10cSrcweir 	}
557*cdf0e10cSrcweir }
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir // -----------------------
560*cdf0e10cSrcweir // - GraphicCache -
561*cdf0e10cSrcweir // -----------------------
562*cdf0e10cSrcweir 
563*cdf0e10cSrcweir GraphicCache::GraphicCache( GraphicManager& rMgr, sal_uLong nDisplayCacheSize, sal_uLong nMaxObjDisplayCacheSize ) :
564*cdf0e10cSrcweir 	mrMgr				    ( rMgr ),
565*cdf0e10cSrcweir     mnReleaseTimeoutSeconds ( 0UL ),
566*cdf0e10cSrcweir 	mnMaxDisplaySize	    ( nDisplayCacheSize ),
567*cdf0e10cSrcweir 	mnMaxObjDisplaySize	    ( nMaxObjDisplayCacheSize ),
568*cdf0e10cSrcweir 	mnUsedDisplaySize	    ( 0UL )
569*cdf0e10cSrcweir {
570*cdf0e10cSrcweir     maReleaseTimer.SetTimeoutHdl( LINK( this, GraphicCache, ReleaseTimeoutHdl ) );
571*cdf0e10cSrcweir     maReleaseTimer.SetTimeout( RELEASE_TIMEOUT );
572*cdf0e10cSrcweir     maReleaseTimer.Start();
573*cdf0e10cSrcweir }
574*cdf0e10cSrcweir 
575*cdf0e10cSrcweir // -----------------------------------------------------------------------------
576*cdf0e10cSrcweir 
577*cdf0e10cSrcweir GraphicCache::~GraphicCache()
578*cdf0e10cSrcweir {
579*cdf0e10cSrcweir 	DBG_ASSERT( !maGraphicCache.Count(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in cache" );
580*cdf0e10cSrcweir 	DBG_ASSERT( !maDisplayCache.Count(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in display cache" );
581*cdf0e10cSrcweir }
582*cdf0e10cSrcweir 
583*cdf0e10cSrcweir // -----------------------------------------------------------------------------
584*cdf0e10cSrcweir 
585*cdf0e10cSrcweir void GraphicCache::AddGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute,
586*cdf0e10cSrcweir                                      const ByteString* pID, const GraphicObject* pCopyObj )
587*cdf0e10cSrcweir {
588*cdf0e10cSrcweir 	sal_Bool bInserted = sal_False;
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir 	if( !rObj.IsSwappedOut() &&
591*cdf0e10cSrcweir         ( pID || ( pCopyObj && ( pCopyObj->GetType() != GRAPHIC_NONE ) ) || ( rObj.GetType() != GRAPHIC_NONE ) ) )
592*cdf0e10cSrcweir 	{
593*cdf0e10cSrcweir         if( pCopyObj )
594*cdf0e10cSrcweir         {
595*cdf0e10cSrcweir             GraphicCacheEntry* pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() );
596*cdf0e10cSrcweir 
597*cdf0e10cSrcweir             while( !bInserted && pEntry )
598*cdf0e10cSrcweir             {
599*cdf0e10cSrcweir                 if( pEntry->HasGraphicObjectReference( *pCopyObj ) )
600*cdf0e10cSrcweir                 {
601*cdf0e10cSrcweir                     pEntry->AddGraphicObjectReference( rObj, rSubstitute );
602*cdf0e10cSrcweir                     bInserted = sal_True;
603*cdf0e10cSrcweir                 }
604*cdf0e10cSrcweir                 else
605*cdf0e10cSrcweir                 {
606*cdf0e10cSrcweir                     pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() );
607*cdf0e10cSrcweir                 }
608*cdf0e10cSrcweir             }
609*cdf0e10cSrcweir         }
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir         if( !bInserted )
612*cdf0e10cSrcweir         {
613*cdf0e10cSrcweir             GraphicCacheEntry* pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() );
614*cdf0e10cSrcweir             ::std::auto_ptr< GraphicID > apID;
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir             if( !pID )
617*cdf0e10cSrcweir             {
618*cdf0e10cSrcweir                 apID.reset( new GraphicID( rObj ) );
619*cdf0e10cSrcweir             }
620*cdf0e10cSrcweir 
621*cdf0e10cSrcweir             while( !bInserted && pEntry )
622*cdf0e10cSrcweir             {
623*cdf0e10cSrcweir                 const GraphicID& rEntryID = pEntry->GetID();
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir                 if( pID )
626*cdf0e10cSrcweir                 {
627*cdf0e10cSrcweir                     if( rEntryID.GetIDString() == *pID )
628*cdf0e10cSrcweir                     {
629*cdf0e10cSrcweir                         pEntry->TryToSwapIn();
630*cdf0e10cSrcweir 
631*cdf0e10cSrcweir                         // since pEntry->TryToSwapIn can modify our current list, we have to
632*cdf0e10cSrcweir                         // iterate from beginning to add a reference to the appropriate
633*cdf0e10cSrcweir                         // CacheEntry object; after this, quickly jump out of the outer iteration
634*cdf0e10cSrcweir                         for( pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() );
635*cdf0e10cSrcweir                              !bInserted && pEntry;
636*cdf0e10cSrcweir                              pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() ) )
637*cdf0e10cSrcweir                         {
638*cdf0e10cSrcweir                             const GraphicID& rID = pEntry->GetID();
639*cdf0e10cSrcweir 
640*cdf0e10cSrcweir                             if( rID.GetIDString() == *pID )
641*cdf0e10cSrcweir                             {
642*cdf0e10cSrcweir                                 pEntry->AddGraphicObjectReference( rObj, rSubstitute );
643*cdf0e10cSrcweir                                 bInserted = sal_True;
644*cdf0e10cSrcweir                             }
645*cdf0e10cSrcweir                         }
646*cdf0e10cSrcweir 
647*cdf0e10cSrcweir                         if( !bInserted )
648*cdf0e10cSrcweir                         {
649*cdf0e10cSrcweir                             maGraphicCache.Insert( new GraphicCacheEntry( rObj ), LIST_APPEND );
650*cdf0e10cSrcweir                             bInserted = sal_True;
651*cdf0e10cSrcweir                         }
652*cdf0e10cSrcweir                     }
653*cdf0e10cSrcweir                 }
654*cdf0e10cSrcweir                 else
655*cdf0e10cSrcweir                 {
656*cdf0e10cSrcweir                     if( rEntryID == *apID )
657*cdf0e10cSrcweir                     {
658*cdf0e10cSrcweir                         pEntry->AddGraphicObjectReference( rObj, rSubstitute );
659*cdf0e10cSrcweir                         bInserted = sal_True;
660*cdf0e10cSrcweir                     }
661*cdf0e10cSrcweir                 }
662*cdf0e10cSrcweir 
663*cdf0e10cSrcweir                 if( !bInserted )
664*cdf0e10cSrcweir                     pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() );
665*cdf0e10cSrcweir             }
666*cdf0e10cSrcweir         }
667*cdf0e10cSrcweir 	}
668*cdf0e10cSrcweir 
669*cdf0e10cSrcweir 	if( !bInserted )
670*cdf0e10cSrcweir 		maGraphicCache.Insert( new GraphicCacheEntry( rObj ), LIST_APPEND );
671*cdf0e10cSrcweir }
672*cdf0e10cSrcweir 
673*cdf0e10cSrcweir // -----------------------------------------------------------------------------
674*cdf0e10cSrcweir 
675*cdf0e10cSrcweir void GraphicCache::ReleaseGraphicObject( const GraphicObject& rObj )
676*cdf0e10cSrcweir {
677*cdf0e10cSrcweir 	// Release cached object
678*cdf0e10cSrcweir 	GraphicCacheEntry*	pEntry = (GraphicCacheEntry*) maGraphicCache.First();
679*cdf0e10cSrcweir 	sal_Bool				bRemoved = sal_False;
680*cdf0e10cSrcweir 
681*cdf0e10cSrcweir 	while( !bRemoved && pEntry )
682*cdf0e10cSrcweir 	{
683*cdf0e10cSrcweir 		bRemoved = pEntry->ReleaseGraphicObjectReference( rObj );
684*cdf0e10cSrcweir 
685*cdf0e10cSrcweir 		if( bRemoved )
686*cdf0e10cSrcweir 		{
687*cdf0e10cSrcweir 			if( 0 == pEntry->GetGraphicObjectReferenceCount() )
688*cdf0e10cSrcweir 			{
689*cdf0e10cSrcweir 				// if graphic cache entry has no more references,
690*cdf0e10cSrcweir 				// the corresponding display cache object can be removed
691*cdf0e10cSrcweir 				GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
692*cdf0e10cSrcweir 
693*cdf0e10cSrcweir 				while( pDisplayEntry )
694*cdf0e10cSrcweir 				{
695*cdf0e10cSrcweir 					if( pDisplayEntry->GetReferencedCacheEntry() == pEntry )
696*cdf0e10cSrcweir 					{
697*cdf0e10cSrcweir 						mnUsedDisplaySize -= pDisplayEntry->GetCacheSize();
698*cdf0e10cSrcweir 						maDisplayCache.Remove( pDisplayEntry );
699*cdf0e10cSrcweir 						delete pDisplayEntry;
700*cdf0e10cSrcweir 						pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject();
701*cdf0e10cSrcweir 					}
702*cdf0e10cSrcweir 					else
703*cdf0e10cSrcweir 						pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
704*cdf0e10cSrcweir 				}
705*cdf0e10cSrcweir 
706*cdf0e10cSrcweir 				// delete graphic cache entry
707*cdf0e10cSrcweir 				maGraphicCache.Remove( (void*) pEntry );
708*cdf0e10cSrcweir 				delete pEntry;
709*cdf0e10cSrcweir 			}
710*cdf0e10cSrcweir 		}
711*cdf0e10cSrcweir 		else
712*cdf0e10cSrcweir 			pEntry = (GraphicCacheEntry*) maGraphicCache.Next();
713*cdf0e10cSrcweir 	}
714*cdf0e10cSrcweir 
715*cdf0e10cSrcweir 	DBG_ASSERT( bRemoved, "GraphicCache::ReleaseGraphicObject(...): GraphicObject not found in cache" );
716*cdf0e10cSrcweir }
717*cdf0e10cSrcweir 
718*cdf0e10cSrcweir // -----------------------------------------------------------------------------
719*cdf0e10cSrcweir 
720*cdf0e10cSrcweir void GraphicCache::GraphicObjectWasSwappedOut( const GraphicObject& rObj )
721*cdf0e10cSrcweir {
722*cdf0e10cSrcweir     // notify cache that rObj is swapped out (and can thus be pruned
723*cdf0e10cSrcweir     // from the cache)
724*cdf0e10cSrcweir 	GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
725*cdf0e10cSrcweir 
726*cdf0e10cSrcweir     if( pEntry )
727*cdf0e10cSrcweir         pEntry->GraphicObjectWasSwappedOut( rObj );
728*cdf0e10cSrcweir }
729*cdf0e10cSrcweir 
730*cdf0e10cSrcweir // -----------------------------------------------------------------------------
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir sal_Bool GraphicCache::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
733*cdf0e10cSrcweir {
734*cdf0e10cSrcweir 	GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
735*cdf0e10cSrcweir 
736*cdf0e10cSrcweir     if( !pEntry )
737*cdf0e10cSrcweir         return sal_False;
738*cdf0e10cSrcweir 
739*cdf0e10cSrcweir 	return pEntry->FillSwappedGraphicObject( rObj, rSubstitute );
740*cdf0e10cSrcweir }
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir // -----------------------------------------------------------------------------
743*cdf0e10cSrcweir 
744*cdf0e10cSrcweir void GraphicCache::GraphicObjectWasSwappedIn( const GraphicObject& rObj )
745*cdf0e10cSrcweir {
746*cdf0e10cSrcweir 	GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj );
747*cdf0e10cSrcweir 
748*cdf0e10cSrcweir     if( pEntry )
749*cdf0e10cSrcweir     {
750*cdf0e10cSrcweir 	    if( pEntry->GetID().IsEmpty() )
751*cdf0e10cSrcweir 	    {
752*cdf0e10cSrcweir 		    ReleaseGraphicObject( rObj );
753*cdf0e10cSrcweir 		    AddGraphicObject( rObj, (Graphic&) rObj.GetGraphic(), NULL, NULL );
754*cdf0e10cSrcweir 	    }
755*cdf0e10cSrcweir 	    else
756*cdf0e10cSrcweir 		    pEntry->GraphicObjectWasSwappedIn( rObj );
757*cdf0e10cSrcweir     }
758*cdf0e10cSrcweir }
759*cdf0e10cSrcweir 
760*cdf0e10cSrcweir // -----------------------------------------------------------------------------
761*cdf0e10cSrcweir 
762*cdf0e10cSrcweir void GraphicCache::SetMaxDisplayCacheSize( sal_uLong nNewCacheSize )
763*cdf0e10cSrcweir {
764*cdf0e10cSrcweir 	mnMaxDisplaySize = nNewCacheSize;
765*cdf0e10cSrcweir 
766*cdf0e10cSrcweir 	if( GetMaxDisplayCacheSize() < GetUsedDisplayCacheSize() )
767*cdf0e10cSrcweir 		ImplFreeDisplayCacheSpace( GetUsedDisplayCacheSize() - GetMaxDisplayCacheSize() );
768*cdf0e10cSrcweir }
769*cdf0e10cSrcweir 
770*cdf0e10cSrcweir // -----------------------------------------------------------------------------
771*cdf0e10cSrcweir 
772*cdf0e10cSrcweir void GraphicCache::SetMaxObjDisplayCacheSize( sal_uLong nNewMaxObjSize, sal_Bool bDestroyGreaterCached )
773*cdf0e10cSrcweir {
774*cdf0e10cSrcweir 	const sal_Bool bDestroy = ( bDestroyGreaterCached && ( nNewMaxObjSize < mnMaxObjDisplaySize ) );
775*cdf0e10cSrcweir 
776*cdf0e10cSrcweir 	mnMaxObjDisplaySize = Min( nNewMaxObjSize, mnMaxDisplaySize );
777*cdf0e10cSrcweir 
778*cdf0e10cSrcweir 	if( bDestroy )
779*cdf0e10cSrcweir 	{
780*cdf0e10cSrcweir 		GraphicDisplayCacheEntry* pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.First();
781*cdf0e10cSrcweir 
782*cdf0e10cSrcweir 		while( pCacheObj )
783*cdf0e10cSrcweir 		{
784*cdf0e10cSrcweir 			if( pCacheObj->GetCacheSize() > mnMaxObjDisplaySize )
785*cdf0e10cSrcweir 			{
786*cdf0e10cSrcweir 				mnUsedDisplaySize -= pCacheObj->GetCacheSize();
787*cdf0e10cSrcweir 				maDisplayCache.Remove( pCacheObj );
788*cdf0e10cSrcweir 				delete pCacheObj;
789*cdf0e10cSrcweir 				pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject();
790*cdf0e10cSrcweir 			}
791*cdf0e10cSrcweir 			else
792*cdf0e10cSrcweir 				pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
793*cdf0e10cSrcweir 		}
794*cdf0e10cSrcweir 	}
795*cdf0e10cSrcweir }
796*cdf0e10cSrcweir 
797*cdf0e10cSrcweir // -----------------------------------------------------------------------------
798*cdf0e10cSrcweir 
799*cdf0e10cSrcweir void GraphicCache::SetCacheTimeout( sal_uLong nTimeoutSeconds )
800*cdf0e10cSrcweir {
801*cdf0e10cSrcweir     if( mnReleaseTimeoutSeconds != nTimeoutSeconds )
802*cdf0e10cSrcweir     {
803*cdf0e10cSrcweir         GraphicDisplayCacheEntry*   pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
804*cdf0e10cSrcweir         ::vos::TTimeValue           aReleaseTime;
805*cdf0e10cSrcweir 
806*cdf0e10cSrcweir         if( ( mnReleaseTimeoutSeconds = nTimeoutSeconds ) != 0 )
807*cdf0e10cSrcweir         {
808*cdf0e10cSrcweir             osl_getSystemTime( &aReleaseTime );
809*cdf0e10cSrcweir             aReleaseTime.addTime( ::vos::TTimeValue( nTimeoutSeconds, 0 ) );
810*cdf0e10cSrcweir         }
811*cdf0e10cSrcweir 
812*cdf0e10cSrcweir 	    while( pDisplayEntry )
813*cdf0e10cSrcweir 	    {
814*cdf0e10cSrcweir             pDisplayEntry->SetReleaseTime( aReleaseTime );
815*cdf0e10cSrcweir 		    pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
816*cdf0e10cSrcweir 	    }
817*cdf0e10cSrcweir     }
818*cdf0e10cSrcweir }
819*cdf0e10cSrcweir 
820*cdf0e10cSrcweir // -----------------------------------------------------------------------------
821*cdf0e10cSrcweir 
822*cdf0e10cSrcweir void GraphicCache::ClearDisplayCache()
823*cdf0e10cSrcweir {
824*cdf0e10cSrcweir 	for( void* pObj = maDisplayCache.First(); pObj; pObj = maDisplayCache.Next() )
825*cdf0e10cSrcweir 		delete (GraphicDisplayCacheEntry*) pObj;
826*cdf0e10cSrcweir 
827*cdf0e10cSrcweir 	maDisplayCache.Clear();
828*cdf0e10cSrcweir 	mnUsedDisplaySize = 0UL;
829*cdf0e10cSrcweir }
830*cdf0e10cSrcweir 
831*cdf0e10cSrcweir // -----------------------------------------------------------------------------
832*cdf0e10cSrcweir 
833*cdf0e10cSrcweir sal_Bool GraphicCache::IsDisplayCacheable( OutputDevice* pOut, const Point& rPt, const Size& rSz,
834*cdf0e10cSrcweir 									   const GraphicObject& rObj, const GraphicAttr& rAttr ) const
835*cdf0e10cSrcweir {
836*cdf0e10cSrcweir 	return( GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) <=
837*cdf0e10cSrcweir 			GetMaxObjDisplayCacheSize() );
838*cdf0e10cSrcweir }
839*cdf0e10cSrcweir 
840*cdf0e10cSrcweir // -----------------------------------------------------------------------------
841*cdf0e10cSrcweir 
842*cdf0e10cSrcweir sal_Bool GraphicCache::IsInDisplayCache( OutputDevice* pOut, const Point& rPt, const Size& rSz,
843*cdf0e10cSrcweir 									 const GraphicObject& rObj, const GraphicAttr& rAttr ) const
844*cdf0e10cSrcweir {
845*cdf0e10cSrcweir 	const Point					aPtPixel( pOut->LogicToPixel( rPt ) );
846*cdf0e10cSrcweir 	const Size					aSzPixel( pOut->LogicToPixel( rSz ) );
847*cdf0e10cSrcweir 	const GraphicCacheEntry*	pCacheEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
848*cdf0e10cSrcweir 	//GraphicDisplayCacheEntry*	pDisplayEntry = (GraphicDisplayCacheEntry*) ( (GraphicCache*) this )->maDisplayCache.First(); // -Wall removed ....
849*cdf0e10cSrcweir 	sal_Bool						bFound = sal_False;
850*cdf0e10cSrcweir 
851*cdf0e10cSrcweir     if( pCacheEntry )
852*cdf0e10cSrcweir     {
853*cdf0e10cSrcweir         for( long i = 0, nCount = maDisplayCache.Count(); !bFound && ( i < nCount ); i++ )
854*cdf0e10cSrcweir             if( ( (GraphicDisplayCacheEntry*) maDisplayCache.GetObject( i ) )->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) )
855*cdf0e10cSrcweir                 bFound = sal_True;
856*cdf0e10cSrcweir     }
857*cdf0e10cSrcweir 
858*cdf0e10cSrcweir 	return bFound;
859*cdf0e10cSrcweir }
860*cdf0e10cSrcweir 
861*cdf0e10cSrcweir // -----------------------------------------------------------------------------
862*cdf0e10cSrcweir 
863*cdf0e10cSrcweir ByteString GraphicCache::GetUniqueID( const GraphicObject& rObj ) const
864*cdf0e10cSrcweir {
865*cdf0e10cSrcweir 	ByteString			aRet;
866*cdf0e10cSrcweir 	GraphicCacheEntry*	pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
867*cdf0e10cSrcweir 
868*cdf0e10cSrcweir 	// ensure that the entry is correctly initialized (it has to be read at least once)
869*cdf0e10cSrcweir 	if( pEntry && pEntry->GetID().IsEmpty() )
870*cdf0e10cSrcweir 		pEntry->TryToSwapIn();
871*cdf0e10cSrcweir 
872*cdf0e10cSrcweir 	// do another call to ImplGetCacheEntry in case of modified entry list
873*cdf0e10cSrcweir 	pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj );
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir 	if( pEntry )
876*cdf0e10cSrcweir 		aRet = pEntry->GetID().GetIDString();
877*cdf0e10cSrcweir 
878*cdf0e10cSrcweir 	return aRet;
879*cdf0e10cSrcweir }
880*cdf0e10cSrcweir 
881*cdf0e10cSrcweir // -----------------------------------------------------------------------------
882*cdf0e10cSrcweir 
883*cdf0e10cSrcweir sal_Bool GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
884*cdf0e10cSrcweir 										  const GraphicObject& rObj, const GraphicAttr& rAttr,
885*cdf0e10cSrcweir 										  const BitmapEx& rBmpEx )
886*cdf0e10cSrcweir {
887*cdf0e10cSrcweir 	const sal_uLong nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr );
888*cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
889*cdf0e10cSrcweir 
890*cdf0e10cSrcweir 	if( nNeededSize <= GetMaxObjDisplayCacheSize() )
891*cdf0e10cSrcweir 	{
892*cdf0e10cSrcweir 		if( nNeededSize > GetFreeDisplayCacheSize() )
893*cdf0e10cSrcweir 			ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() );
894*cdf0e10cSrcweir 
895*cdf0e10cSrcweir 		GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ),
896*cdf0e10cSrcweir 																			pOut, rPt, rSz, rObj, rAttr, rBmpEx );
897*cdf0e10cSrcweir 
898*cdf0e10cSrcweir         if( GetCacheTimeout() )
899*cdf0e10cSrcweir         {
900*cdf0e10cSrcweir             ::vos::TTimeValue aReleaseTime;
901*cdf0e10cSrcweir 
902*cdf0e10cSrcweir             osl_getSystemTime( &aReleaseTime );
903*cdf0e10cSrcweir             aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) );
904*cdf0e10cSrcweir             pNewEntry->SetReleaseTime( aReleaseTime );
905*cdf0e10cSrcweir         }
906*cdf0e10cSrcweir 
907*cdf0e10cSrcweir 		maDisplayCache.Insert( pNewEntry, LIST_APPEND );
908*cdf0e10cSrcweir 		mnUsedDisplaySize += pNewEntry->GetCacheSize();
909*cdf0e10cSrcweir 		bRet = sal_True;
910*cdf0e10cSrcweir 	}
911*cdf0e10cSrcweir 
912*cdf0e10cSrcweir 	return bRet;
913*cdf0e10cSrcweir }
914*cdf0e10cSrcweir 
915*cdf0e10cSrcweir // -----------------------------------------------------------------------------
916*cdf0e10cSrcweir 
917*cdf0e10cSrcweir sal_Bool GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
918*cdf0e10cSrcweir 										  const GraphicObject& rObj, const GraphicAttr& rAttr,
919*cdf0e10cSrcweir 										  const GDIMetaFile& rMtf )
920*cdf0e10cSrcweir {
921*cdf0e10cSrcweir 	const sal_uLong nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr );
922*cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir 	if( nNeededSize <= GetMaxObjDisplayCacheSize() )
925*cdf0e10cSrcweir 	{
926*cdf0e10cSrcweir 		if( nNeededSize > GetFreeDisplayCacheSize() )
927*cdf0e10cSrcweir 			ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() );
928*cdf0e10cSrcweir 
929*cdf0e10cSrcweir 		GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ),
930*cdf0e10cSrcweir 																			pOut, rPt, rSz, rObj, rAttr, rMtf );
931*cdf0e10cSrcweir 
932*cdf0e10cSrcweir         if( GetCacheTimeout() )
933*cdf0e10cSrcweir         {
934*cdf0e10cSrcweir             ::vos::TTimeValue aReleaseTime;
935*cdf0e10cSrcweir 
936*cdf0e10cSrcweir             osl_getSystemTime( &aReleaseTime );
937*cdf0e10cSrcweir             aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) );
938*cdf0e10cSrcweir             pNewEntry->SetReleaseTime( aReleaseTime );
939*cdf0e10cSrcweir         }
940*cdf0e10cSrcweir 
941*cdf0e10cSrcweir 		maDisplayCache.Insert( pNewEntry, LIST_APPEND );
942*cdf0e10cSrcweir 		mnUsedDisplaySize += pNewEntry->GetCacheSize();
943*cdf0e10cSrcweir 		bRet = sal_True;
944*cdf0e10cSrcweir 	}
945*cdf0e10cSrcweir 
946*cdf0e10cSrcweir 	return bRet;
947*cdf0e10cSrcweir }
948*cdf0e10cSrcweir 
949*cdf0e10cSrcweir // -----------------------------------------------------------------------------
950*cdf0e10cSrcweir 
951*cdf0e10cSrcweir sal_Bool GraphicCache::DrawDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
952*cdf0e10cSrcweir 										const GraphicObject& rObj, const GraphicAttr& rAttr )
953*cdf0e10cSrcweir {
954*cdf0e10cSrcweir 	const Point					aPtPixel( pOut->LogicToPixel( rPt ) );
955*cdf0e10cSrcweir 	const Size					aSzPixel( pOut->LogicToPixel( rSz ) );
956*cdf0e10cSrcweir 	const GraphicCacheEntry*	pCacheEntry = ImplGetCacheEntry( rObj );
957*cdf0e10cSrcweir 	GraphicDisplayCacheEntry*	pDisplayCacheEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
958*cdf0e10cSrcweir 	sal_Bool						bRet = sal_False;
959*cdf0e10cSrcweir 
960*cdf0e10cSrcweir 	while( !bRet && pDisplayCacheEntry )
961*cdf0e10cSrcweir 	{
962*cdf0e10cSrcweir 		if( pDisplayCacheEntry->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) )
963*cdf0e10cSrcweir 		{
964*cdf0e10cSrcweir             ::vos::TTimeValue aReleaseTime;
965*cdf0e10cSrcweir 
966*cdf0e10cSrcweir 			// put found object at last used position
967*cdf0e10cSrcweir 			maDisplayCache.Insert( maDisplayCache.Remove( pDisplayCacheEntry ), LIST_APPEND );
968*cdf0e10cSrcweir 
969*cdf0e10cSrcweir             if( GetCacheTimeout() )
970*cdf0e10cSrcweir             {
971*cdf0e10cSrcweir                 osl_getSystemTime( &aReleaseTime );
972*cdf0e10cSrcweir                 aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) );
973*cdf0e10cSrcweir             }
974*cdf0e10cSrcweir 
975*cdf0e10cSrcweir             pDisplayCacheEntry->SetReleaseTime( aReleaseTime );
976*cdf0e10cSrcweir 			bRet = sal_True;
977*cdf0e10cSrcweir 		}
978*cdf0e10cSrcweir 		else
979*cdf0e10cSrcweir 			pDisplayCacheEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
980*cdf0e10cSrcweir 	}
981*cdf0e10cSrcweir 
982*cdf0e10cSrcweir 	if( bRet )
983*cdf0e10cSrcweir 		pDisplayCacheEntry->Draw( pOut, rPt, rSz );
984*cdf0e10cSrcweir 
985*cdf0e10cSrcweir 	return bRet;
986*cdf0e10cSrcweir }
987*cdf0e10cSrcweir 
988*cdf0e10cSrcweir // -----------------------------------------------------------------------------
989*cdf0e10cSrcweir 
990*cdf0e10cSrcweir sal_Bool GraphicCache::ImplFreeDisplayCacheSpace( sal_uLong nSizeToFree )
991*cdf0e10cSrcweir {
992*cdf0e10cSrcweir 	sal_uLong nFreedSize = 0UL;
993*cdf0e10cSrcweir 
994*cdf0e10cSrcweir 	if( nSizeToFree )
995*cdf0e10cSrcweir 	{
996*cdf0e10cSrcweir 		void* pObj = maDisplayCache.First();
997*cdf0e10cSrcweir 
998*cdf0e10cSrcweir         if( nSizeToFree > mnUsedDisplaySize )
999*cdf0e10cSrcweir             nSizeToFree = mnUsedDisplaySize;
1000*cdf0e10cSrcweir 
1001*cdf0e10cSrcweir 		while( pObj )
1002*cdf0e10cSrcweir 		{
1003*cdf0e10cSrcweir 			GraphicDisplayCacheEntry* pCacheObj = (GraphicDisplayCacheEntry*) pObj;
1004*cdf0e10cSrcweir 
1005*cdf0e10cSrcweir 			nFreedSize += pCacheObj->GetCacheSize();
1006*cdf0e10cSrcweir 			mnUsedDisplaySize -= pCacheObj->GetCacheSize();
1007*cdf0e10cSrcweir 			maDisplayCache.Remove( pObj );
1008*cdf0e10cSrcweir 			delete pCacheObj;
1009*cdf0e10cSrcweir 
1010*cdf0e10cSrcweir 			if( nFreedSize >= nSizeToFree )
1011*cdf0e10cSrcweir 				break;
1012*cdf0e10cSrcweir 			else
1013*cdf0e10cSrcweir 				pObj = maDisplayCache.GetCurObject();
1014*cdf0e10cSrcweir 		}
1015*cdf0e10cSrcweir 	}
1016*cdf0e10cSrcweir 
1017*cdf0e10cSrcweir 	return( nFreedSize >= nSizeToFree );
1018*cdf0e10cSrcweir }
1019*cdf0e10cSrcweir 
1020*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1021*cdf0e10cSrcweir 
1022*cdf0e10cSrcweir GraphicCacheEntry* GraphicCache::ImplGetCacheEntry( const GraphicObject& rObj )
1023*cdf0e10cSrcweir {
1024*cdf0e10cSrcweir 	GraphicCacheEntry* pRet = NULL;
1025*cdf0e10cSrcweir 
1026*cdf0e10cSrcweir 	for( void* pObj = maGraphicCache.First(); !pRet && pObj; pObj = maGraphicCache.Next() )
1027*cdf0e10cSrcweir 		if( ( (GraphicCacheEntry*) pObj )->HasGraphicObjectReference( rObj ) )
1028*cdf0e10cSrcweir 			pRet = (GraphicCacheEntry*) pObj;
1029*cdf0e10cSrcweir 
1030*cdf0e10cSrcweir 	return pRet;
1031*cdf0e10cSrcweir }
1032*cdf0e10cSrcweir 
1033*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1034*cdf0e10cSrcweir 
1035*cdf0e10cSrcweir IMPL_LINK( GraphicCache, ReleaseTimeoutHdl, Timer*, pTimer )
1036*cdf0e10cSrcweir {
1037*cdf0e10cSrcweir     pTimer->Stop();
1038*cdf0e10cSrcweir 
1039*cdf0e10cSrcweir     ::vos::TTimeValue           aCurTime;
1040*cdf0e10cSrcweir 	GraphicDisplayCacheEntry*   pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First();
1041*cdf0e10cSrcweir 
1042*cdf0e10cSrcweir     osl_getSystemTime( &aCurTime );
1043*cdf0e10cSrcweir 
1044*cdf0e10cSrcweir 	while( pDisplayEntry )
1045*cdf0e10cSrcweir 	{
1046*cdf0e10cSrcweir         const ::vos::TTimeValue& rReleaseTime = pDisplayEntry->GetReleaseTime();
1047*cdf0e10cSrcweir 
1048*cdf0e10cSrcweir 		if( !rReleaseTime.isEmpty() && ( rReleaseTime < aCurTime ) )
1049*cdf0e10cSrcweir 		{
1050*cdf0e10cSrcweir 			mnUsedDisplaySize -= pDisplayEntry->GetCacheSize();
1051*cdf0e10cSrcweir 			maDisplayCache.Remove( pDisplayEntry );
1052*cdf0e10cSrcweir 			delete pDisplayEntry;
1053*cdf0e10cSrcweir 			pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject();
1054*cdf0e10cSrcweir 		}
1055*cdf0e10cSrcweir 		else
1056*cdf0e10cSrcweir 			pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next();
1057*cdf0e10cSrcweir 	}
1058*cdf0e10cSrcweir 
1059*cdf0e10cSrcweir     pTimer->Start();
1060*cdf0e10cSrcweir 
1061*cdf0e10cSrcweir     return 0;
1062*cdf0e10cSrcweir }
1063