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