1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 
27 #include "SlsBitmapCache.hxx"
28 #include "SlsCacheCompactor.hxx"
29 #include "SlsBitmapCompressor.hxx"
30 #include "SlsCacheConfiguration.hxx"
31 
32 #include "sdpage.hxx"
33 #include "drawdoc.hxx"
34 
35 // Uncomment the following define for some more OSL_TRACE messages.
36 #ifdef DEBUG
37 //#define VERBOSE
38 #endif
39 
40 // Define the default value for the maximal cache size that is used for
41 // previews that are currently not visible.  The visible previews are all
42 // held in memory at all times.  This default is used only when the
43 // configuration does not have a value.
44 static const sal_Int32 MAXIMAL_CACHE_SIZE = 4L*1024L*1024L;
45 
46 using namespace ::com::sun::star::uno;
47 
48 namespace sd { namespace slidesorter { namespace cache {
49 
50 class BitmapCache::CacheEntry
51 {
52 public:
53     CacheEntry(const Bitmap& rBitmap, sal_Int32 nLastAccessTime, bool bIsPrecious);
54     CacheEntry(sal_Int32 nLastAccessTime, bool bIsPrecious);
~CacheEntry(void)55     ~CacheEntry (void) {};
56     inline void Recycle (const CacheEntry& rEntry);
57     inline sal_Int32 GetMemorySize (void) const;
58     void Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor);
59     inline void Decompress (void);
60 
IsUpToDate(void) const61     bool IsUpToDate (void) const { return mbIsUpToDate; }
SetUpToDate(bool bIsUpToDate)62     void SetUpToDate (bool bIsUpToDate) { mbIsUpToDate = bIsUpToDate; }
GetAccessTime(void) const63     sal_Int32 GetAccessTime (void) const { return mnLastAccessTime; }
SetAccessTime(sal_Int32 nAccessTime)64     void SetAccessTime (sal_Int32 nAccessTime) { mnLastAccessTime = nAccessTime; }
65 
GetPreview(void) const66     Bitmap GetPreview (void) const { return maPreview; }
67     inline void SetPreview (const Bitmap& rPreview);
68     bool HasPreview (void) const;
69 
GetMarkedPreview(void) const70     Bitmap GetMarkedPreview (void) const { return maMarkedPreview; }
71     inline void SetMarkedPreview (const Bitmap& rMarkePreview);
72     bool HasMarkedPreview (void) const;
73 
HasReplacement(void) const74     bool HasReplacement (void) const { return (mpReplacement.get() != NULL); }
75     inline bool HasLosslessReplacement (void) const;
Clear(void)76     void Clear (void) { maPreview.SetEmpty(); maMarkedPreview.SetEmpty();
77         mpReplacement.reset(); mpCompressor.reset(); }
Invalidate(void)78     void Invalidate (void) { mpReplacement.reset(); mpCompressor.reset(); mbIsUpToDate = false; }
IsPrecious(void) const79     bool IsPrecious (void) const { return mbIsPrecious; }
SetPrecious(bool bIsPrecious)80     void SetPrecious (bool bIsPrecious) { mbIsPrecious = bIsPrecious; }
81 
82 private:
83     Bitmap maPreview;
84     Bitmap maMarkedPreview;
85     ::boost::shared_ptr<BitmapReplacement> mpReplacement;
86     ::boost::shared_ptr<BitmapCompressor> mpCompressor;
87     Size maBitmapSize;
88     bool mbIsUpToDate;
89     sal_Int32 mnLastAccessTime;
90     // When this flag is set then the bitmap is not modified by a cache
91     // compactor.
92     bool mbIsPrecious;
93 };
94 class CacheEntry;
95 
96 class CacheHash {
97 public:
operator ()(const BitmapCache::CacheKey & p) const98     size_t operator()(const BitmapCache::CacheKey& p) const
99     { return (size_t)p; }
100 };
101 
102 class BitmapCache::CacheBitmapContainer
103     : public ::std::hash_map<CacheKey, CacheEntry, CacheHash>
104 {
105 public:
CacheBitmapContainer(void)106     CacheBitmapContainer (void) {}
107 };
108 
109 namespace {
110 
111 typedef ::std::vector<
112     ::std::pair< ::sd::slidesorter::cache::BitmapCache::CacheKey,
113       ::sd::slidesorter::cache::BitmapCache::CacheEntry>
114     > SortableBitmapContainer;
115 
116     /** Compare elements of the bitmap cache according to their last access
117         time.
118     */
119     class AccessTimeComparator
120     {
121     public:
operator ()(const SortableBitmapContainer::value_type & e1,const SortableBitmapContainer::value_type & e2)122         bool operator () (
123             const SortableBitmapContainer::value_type& e1,
124             const SortableBitmapContainer::value_type& e2)
125         {
126             return e1.second.GetAccessTime() < e2.second.GetAccessTime();
127         }
128     };
129 
130 
131 } // end of anonymous namespace
132 
133 
134 //=====  BitmapCache  =========================================================
135 
BitmapCache(const sal_Int32 nMaximalNormalCacheSize)136 BitmapCache::BitmapCache (const sal_Int32 nMaximalNormalCacheSize)
137     : maMutex(),
138       mpBitmapContainer(new CacheBitmapContainer()),
139       mnNormalCacheSize(0),
140       mnPreciousCacheSize(0),
141       mnCurrentAccessTime(0),
142       mnMaximalNormalCacheSize(MAXIMAL_CACHE_SIZE),
143       mpCacheCompactor(),
144       mbIsFull(false)
145 {
146     if (nMaximalNormalCacheSize > 0)
147         mnMaximalNormalCacheSize = nMaximalNormalCacheSize;
148     else
149     {
150         Any aCacheSize (CacheConfiguration::Instance()->GetValue(
151         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CacheSize"))));
152         if (aCacheSize.has<sal_Int32>())
153             aCacheSize >>= mnMaximalNormalCacheSize;
154     }
155 
156     mpCacheCompactor = CacheCompactor::Create(*this,mnMaximalNormalCacheSize);
157 }
158 
159 
160 
161 
~BitmapCache(void)162 BitmapCache::~BitmapCache (void)
163 {
164     Clear();
165 }
166 
167 
168 
169 
Clear(void)170 void BitmapCache::Clear (void)
171 {
172     ::osl::MutexGuard aGuard (maMutex);
173 
174     mpBitmapContainer->clear();
175     mnNormalCacheSize = 0;
176     mnPreciousCacheSize = 0;
177     mnCurrentAccessTime = 0;
178 }
179 
180 
181 
182 
IsFull(void) const183 bool BitmapCache::IsFull (void) const
184 {
185     return mbIsFull;
186 }
187 
188 
189 
190 
GetSize(void)191 sal_Int32 BitmapCache::GetSize (void)
192 {
193     return mnNormalCacheSize;
194 }
195 
196 
197 
198 
HasBitmap(const CacheKey & rKey)199 bool BitmapCache::HasBitmap (const CacheKey& rKey)
200 {
201     ::osl::MutexGuard aGuard (maMutex);
202 
203     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
204     return (iEntry != mpBitmapContainer->end()
205         && (iEntry->second.HasPreview() || iEntry->second.HasReplacement()));
206 }
207 
208 
209 
210 
BitmapIsUpToDate(const CacheKey & rKey)211 bool BitmapCache::BitmapIsUpToDate (const CacheKey& rKey)
212 {
213     ::osl::MutexGuard aGuard (maMutex);
214 
215     bool bIsUpToDate = false;
216     CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
217     if (aIterator != mpBitmapContainer->end())
218         bIsUpToDate = aIterator->second.IsUpToDate();
219 
220     return bIsUpToDate;
221 }
222 
223 
224 
225 
GetBitmap(const CacheKey & rKey)226 Bitmap BitmapCache::GetBitmap (const CacheKey& rKey)
227 {
228     ::osl::MutexGuard aGuard (maMutex);
229 
230     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
231     if (iEntry == mpBitmapContainer->end())
232     {
233         // Create an empty bitmap for the given key that acts as placeholder
234         // until we are given the real one.  Mark it as not being up to date.
235         SetBitmap(rKey, Bitmap(), false);
236         iEntry = mpBitmapContainer->find(rKey);
237         iEntry->second.SetUpToDate(false);
238     }
239     else
240     {
241         iEntry->second.SetAccessTime(mnCurrentAccessTime++);
242 
243         // Maybe we have to decompress the preview.
244         if ( ! iEntry->second.HasPreview() && iEntry->second.HasReplacement())
245         {
246             UpdateCacheSize(iEntry->second, REMOVE);
247             iEntry->second.Decompress();
248             UpdateCacheSize(iEntry->second, ADD);
249         }
250     }
251     return iEntry->second.GetPreview();
252 }
253 
254 
255 
256 
GetMarkedBitmap(const CacheKey & rKey)257 Bitmap BitmapCache::GetMarkedBitmap (const CacheKey& rKey)
258 {
259     ::osl::MutexGuard aGuard (maMutex);
260 
261     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
262     if (iEntry != mpBitmapContainer->end())
263     {
264         iEntry->second.SetAccessTime(mnCurrentAccessTime++);
265         return iEntry->second.GetMarkedPreview();
266     }
267     else
268         return Bitmap();
269 }
270 
271 
272 
273 
ReleaseBitmap(const CacheKey & rKey)274 void BitmapCache::ReleaseBitmap (const CacheKey& rKey)
275 {
276     ::osl::MutexGuard aGuard (maMutex);
277 
278     CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
279     if (aIterator != mpBitmapContainer->end())
280     {
281         UpdateCacheSize(aIterator->second, REMOVE);
282         mpBitmapContainer->erase(aIterator);
283     }
284 }
285 
286 
287 
288 
InvalidateBitmap(const CacheKey & rKey)289 bool BitmapCache::InvalidateBitmap (const CacheKey& rKey)
290 {
291     ::osl::MutexGuard aGuard (maMutex);
292 
293     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
294     if (iEntry != mpBitmapContainer->end())
295     {
296         iEntry->second.SetUpToDate(false);
297 
298         // When there is a preview then we release the replacement.  The
299         // preview itself is kept until a new one is created.
300         if (iEntry->second.HasPreview())
301         {
302             UpdateCacheSize(iEntry->second, REMOVE);
303             iEntry->second.Invalidate();
304             UpdateCacheSize(iEntry->second, ADD);
305         }
306         return true;
307     }
308     else
309         return false;
310 }
311 
312 
313 
314 
InvalidateCache(void)315 void BitmapCache::InvalidateCache (void)
316 {
317     ::osl::MutexGuard aGuard (maMutex);
318 
319     CacheBitmapContainer::iterator iEntry;
320     for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
321     {
322         iEntry->second.Invalidate();
323     }
324     ReCalculateTotalCacheSize();
325 }
326 
327 
328 
329 
SetBitmap(const CacheKey & rKey,const Bitmap & rPreview,bool bIsPrecious)330 void BitmapCache::SetBitmap (
331     const CacheKey& rKey,
332     const Bitmap& rPreview,
333     bool bIsPrecious)
334 {
335     ::osl::MutexGuard aGuard (maMutex);
336 
337     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
338     if (iEntry != mpBitmapContainer->end())
339     {
340         UpdateCacheSize(iEntry->second, REMOVE);
341         iEntry->second.SetPreview(rPreview);
342         iEntry->second.SetUpToDate(true);
343         iEntry->second.SetAccessTime(mnCurrentAccessTime++);
344     }
345     else
346     {
347         iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
348             rKey,
349             CacheEntry(rPreview, mnCurrentAccessTime++, bIsPrecious))
350             ).first;
351     }
352 
353     if (iEntry != mpBitmapContainer->end())
354         UpdateCacheSize(iEntry->second, ADD);
355 }
356 
357 
358 
359 
SetMarkedBitmap(const CacheKey & rKey,const Bitmap & rPreview)360 void BitmapCache::SetMarkedBitmap (
361     const CacheKey& rKey,
362     const Bitmap& rPreview)
363 {
364     ::osl::MutexGuard aGuard (maMutex);
365 
366     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
367     if (iEntry != mpBitmapContainer->end())
368     {
369         UpdateCacheSize(iEntry->second, REMOVE);
370         iEntry->second.SetMarkedPreview(rPreview);
371         iEntry->second.SetAccessTime(mnCurrentAccessTime++);
372         UpdateCacheSize(iEntry->second, ADD);
373     }
374 }
375 
376 
377 
378 
SetPrecious(const CacheKey & rKey,bool bIsPrecious)379 void BitmapCache::SetPrecious (const CacheKey& rKey, bool bIsPrecious)
380 {
381     ::osl::MutexGuard aGuard (maMutex);
382 
383     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
384     if (iEntry != mpBitmapContainer->end())
385     {
386         if (iEntry->second.IsPrecious() != bIsPrecious)
387         {
388             UpdateCacheSize(iEntry->second, REMOVE);
389             iEntry->second.SetPrecious(bIsPrecious);
390             UpdateCacheSize(iEntry->second, ADD);
391         }
392     }
393     else if (bIsPrecious)
394     {
395         iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
396             rKey,
397             CacheEntry(Bitmap(), mnCurrentAccessTime++, bIsPrecious))
398             ).first;
399         UpdateCacheSize(iEntry->second, ADD);
400     }
401 }
402 
403 
404 
405 
ReCalculateTotalCacheSize(void)406 void BitmapCache::ReCalculateTotalCacheSize (void)
407 {
408     ::osl::MutexGuard aGuard (maMutex);
409 
410     mnNormalCacheSize = 0;
411     mnPreciousCacheSize = 0;
412     CacheBitmapContainer::iterator iEntry;
413     for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end();  ++iEntry)
414     {
415         if (iEntry->second.IsPrecious())
416             mnPreciousCacheSize += iEntry->second.GetMemorySize();
417         else
418             mnNormalCacheSize += iEntry->second.GetMemorySize();
419     }
420     mbIsFull = (mnNormalCacheSize  >= mnMaximalNormalCacheSize);
421 
422 #ifdef VERBOSE
423     OSL_TRACE("cache size is %d/%d", mnNormalCacheSize, mnPreciousCacheSize);
424 #endif
425 }
426 
427 
428 
429 
Recycle(const BitmapCache & rCache)430 void BitmapCache::Recycle (const BitmapCache& rCache)
431 {
432     ::osl::MutexGuard aGuard (maMutex);
433 
434     CacheBitmapContainer::const_iterator iOtherEntry;
435     for (iOtherEntry=rCache.mpBitmapContainer->begin();
436          iOtherEntry!=rCache.mpBitmapContainer->end();
437          ++iOtherEntry)
438     {
439         CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(iOtherEntry->first));
440         if (iEntry == mpBitmapContainer->end())
441         {
442             iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
443                 iOtherEntry->first,
444                 CacheEntry(mnCurrentAccessTime++, true))
445                 ).first;
446             UpdateCacheSize(iEntry->second, ADD);
447         }
448         if (iEntry != mpBitmapContainer->end())
449         {
450             UpdateCacheSize(iEntry->second, REMOVE);
451             iEntry->second.Recycle(iOtherEntry->second);
452             UpdateCacheSize(iEntry->second, ADD);
453         }
454     }
455 }
456 
457 
458 
459 
GetCacheIndex(bool bIncludePrecious,bool bIncludeNoPreview) const460 ::std::auto_ptr<BitmapCache::CacheIndex> BitmapCache::GetCacheIndex (
461     bool bIncludePrecious,
462     bool bIncludeNoPreview) const
463 {
464     ::osl::MutexGuard aGuard (maMutex);
465 
466     // Create a copy of the bitmap container.
467     SortableBitmapContainer aSortedContainer;
468     aSortedContainer.reserve(mpBitmapContainer->size());
469 
470     // Copy the relevant entries.
471     CacheBitmapContainer::iterator iEntry;
472     for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
473     {
474         if ( ! bIncludePrecious && iEntry->second.IsPrecious())
475             continue;
476 
477         if ( ! bIncludeNoPreview && ! iEntry->second.HasPreview())
478             continue;
479 
480         aSortedContainer.push_back(SortableBitmapContainer::value_type(
481             iEntry->first,iEntry->second));
482     }
483 
484     // Sort the remaining entries.
485     ::std::sort(aSortedContainer.begin(), aSortedContainer.end(), AccessTimeComparator());
486 
487     // Return a list with the keys of the sorted entries.
488     ::std::auto_ptr<CacheIndex> pIndex(new CacheIndex());
489     SortableBitmapContainer::iterator iIndexEntry;
490     pIndex->reserve(aSortedContainer.size());
491     for (iIndexEntry=aSortedContainer.begin(); iIndexEntry!=aSortedContainer.end(); ++iIndexEntry)
492         pIndex->push_back(iIndexEntry->first);
493     return pIndex;
494 }
495 
496 
497 
498 
Compress(const CacheKey & rKey,const::boost::shared_ptr<BitmapCompressor> & rpCompressor)499 void BitmapCache::Compress (
500     const CacheKey& rKey,
501     const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
502 {
503     ::osl::MutexGuard aGuard (maMutex);
504 
505     CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
506     if (iEntry != mpBitmapContainer->end() && iEntry->second.HasPreview())
507     {
508         UpdateCacheSize(iEntry->second, REMOVE);
509         iEntry->second.Compress(rpCompressor);
510         UpdateCacheSize(iEntry->second, ADD);
511     }
512 }
513 
514 
515 
516 
UpdateCacheSize(const CacheEntry & rEntry,CacheOperation eOperation)517 void BitmapCache::UpdateCacheSize (const CacheEntry& rEntry, CacheOperation eOperation)
518 {
519     sal_Int32 nEntrySize (rEntry.GetMemorySize());
520     sal_Int32& rCacheSize (rEntry.IsPrecious() ? mnPreciousCacheSize : mnNormalCacheSize);
521     switch (eOperation)
522     {
523         case ADD:
524             rCacheSize += nEntrySize;
525             if ( ! rEntry.IsPrecious() && mnNormalCacheSize>mnMaximalNormalCacheSize)
526             {
527                 mbIsFull = true;
528 #ifdef VERBOSE
529                 OSL_TRACE("cache size is %d > %d", mnNormalCacheSize,mnMaximalNormalCacheSize);
530 #endif
531                 mpCacheCompactor->RequestCompaction();
532             }
533             break;
534 
535         case REMOVE:
536             rCacheSize -= nEntrySize;
537             if (mnNormalCacheSize < mnMaximalNormalCacheSize)
538                 mbIsFull = false;
539             break;
540 
541         default:
542             OSL_ASSERT(false);
543             break;
544     }
545 }
546 
547 
548 
549 
550 //===== CacheEntry ============================================================
551 
CacheEntry(sal_Int32 nLastAccessTime,bool bIsPrecious)552 BitmapCache::CacheEntry::CacheEntry(
553     sal_Int32 nLastAccessTime,
554     bool bIsPrecious)
555     : maPreview(),
556       maMarkedPreview(),
557       mbIsUpToDate(true),
558       mnLastAccessTime(nLastAccessTime),
559       mbIsPrecious(bIsPrecious)
560 {
561 }
562 
563 
564 
565 
CacheEntry(const Bitmap & rPreview,sal_Int32 nLastAccessTime,bool bIsPrecious)566 BitmapCache::CacheEntry::CacheEntry(
567     const Bitmap& rPreview,
568     sal_Int32 nLastAccessTime,
569     bool bIsPrecious)
570     : maPreview(rPreview),
571       maMarkedPreview(),
572       mbIsUpToDate(true),
573       mnLastAccessTime(nLastAccessTime),
574       mbIsPrecious(bIsPrecious)
575 {
576 }
577 
578 
579 
580 
Recycle(const CacheEntry & rEntry)581 inline void BitmapCache::CacheEntry::Recycle (const CacheEntry& rEntry)
582 {
583     if ((rEntry.HasPreview() || rEntry.HasLosslessReplacement())
584         && ! (HasPreview() || HasLosslessReplacement()))
585     {
586         maPreview = rEntry.maPreview;
587         maMarkedPreview = rEntry.maMarkedPreview;
588         mpReplacement = rEntry.mpReplacement;
589         mpCompressor = rEntry.mpCompressor;
590         mnLastAccessTime = rEntry.mnLastAccessTime;
591         mbIsUpToDate = rEntry.mbIsUpToDate;
592     }
593 }
594 
595 
596 
597 
GetMemorySize(void) const598 inline sal_Int32 BitmapCache::CacheEntry::GetMemorySize (void) const
599 {
600     sal_Int32 nSize (0);
601     nSize += maPreview.GetSizeBytes();
602     nSize += maMarkedPreview.GetSizeBytes();
603     if (mpReplacement.get() != NULL)
604         nSize += mpReplacement->GetMemorySize();
605     return nSize;
606 }
607 
608 
609 
610 
Compress(const::boost::shared_ptr<BitmapCompressor> & rpCompressor)611 void BitmapCache::CacheEntry::Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
612 {
613     if ( ! maPreview.IsEmpty())
614     {
615         if (mpReplacement.get() == NULL)
616         {
617             mpReplacement = rpCompressor->Compress(maPreview);
618 
619 #ifdef VERBOSE
620             sal_uInt32 nOldSize (maPreview.GetSizeBytes());
621             sal_uInt32 nNewSize (mpReplacement.get()!=NULL ? mpReplacement->GetMemorySize() : 0);
622             if (nOldSize == 0)
623                 nOldSize = 1;
624             sal_Int32 nRatio (100L * nNewSize / nOldSize);
625             OSL_TRACE("compressing bitmap for %x from %d to %d bytes (%d%%)",
626                 this,
627                 nOldSize,
628                 nNewSize,
629                 nRatio);
630 #endif
631 
632             mpCompressor = rpCompressor;
633         }
634 
635         maPreview.SetEmpty();
636         maMarkedPreview.SetEmpty();
637     }
638 }
639 
640 
641 
642 
Decompress(void)643 inline void BitmapCache::CacheEntry::Decompress (void)
644 {
645     if (mpReplacement.get()!=NULL && mpCompressor.get()!=NULL && maPreview.IsEmpty())
646     {
647         maPreview = mpCompressor->Decompress(*mpReplacement);
648         maMarkedPreview.SetEmpty();
649         if ( ! mpCompressor->IsLossless())
650             mbIsUpToDate = false;
651     }
652 }
653 
654 
655 
SetPreview(const Bitmap & rPreview)656 inline void BitmapCache::CacheEntry::SetPreview (const Bitmap& rPreview)
657 {
658     maPreview = rPreview;
659     maMarkedPreview.SetEmpty();
660     mpReplacement.reset();
661     mpCompressor.reset();
662 }
663 
664 
665 
666 
HasPreview(void) const667 bool BitmapCache::CacheEntry::HasPreview (void) const
668 {
669     return ! maPreview.IsEmpty();
670 }
671 
672 
673 
674 
SetMarkedPreview(const Bitmap & rMarkedPreview)675 inline void BitmapCache::CacheEntry::SetMarkedPreview (const Bitmap& rMarkedPreview)
676 {
677     maMarkedPreview = rMarkedPreview;
678 }
679 
680 
681 
682 
HasMarkedPreview(void) const683 bool BitmapCache::CacheEntry::HasMarkedPreview (void) const
684 {
685     return ! maMarkedPreview.IsEmpty();
686 }
687 
688 
689 
690 
HasLosslessReplacement(void) const691 inline bool BitmapCache::CacheEntry::HasLosslessReplacement (void) const
692 {
693     return mpReplacement.get()!=NULL
694         && mpCompressor.get()!=NULL
695         && mpCompressor->IsLossless();
696 }
697 
698 
699 } } } // end of namespace ::sd::slidesorter::cache
700