Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "SlsBitmapCache.hxx"
21 : #include "SlsCacheCompactor.hxx"
22 : #include "SlsBitmapCompressor.hxx"
23 : #include "SlsCacheConfiguration.hxx"
24 :
25 : #include "sdpage.hxx"
26 : #include "drawdoc.hxx"
27 :
28 : // Define the default value for the maximal cache size that is used for
29 : // previews that are currently not visible. The visible previews are all
30 : // held in memory at all times. This default is used only when the
31 : // configuration does not have a value.
32 : static const sal_Int32 MAXIMAL_CACHE_SIZE = 4L*1024L*1024L;
33 :
34 : using namespace ::com::sun::star::uno;
35 :
36 : namespace sd { namespace slidesorter { namespace cache {
37 :
38 272 : class BitmapCache::CacheEntry
39 : {
40 : public:
41 : CacheEntry(const Bitmap& rBitmap, sal_Int32 nLastAccessTime, bool bIsPrecious);
42 : CacheEntry(sal_Int32 nLastAccessTime, bool bIsPrecious);
43 408 : ~CacheEntry (void) {};
44 : inline void Recycle (const CacheEntry& rEntry);
45 : inline sal_Int32 GetMemorySize (void) const;
46 : void Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor);
47 : inline void Decompress (void);
48 :
49 696 : bool IsUpToDate (void) const { return mbIsUpToDate; }
50 775 : void SetUpToDate (bool bIsUpToDate) { mbIsUpToDate = bIsUpToDate; }
51 0 : sal_Int32 GetAccessTime (void) const { return mnLastAccessTime; }
52 534 : void SetAccessTime (sal_Int32 nAccessTime) { mnLastAccessTime = nAccessTime; }
53 :
54 364 : Bitmap GetPreview (void) const { return maPreview; }
55 : inline void SetPreview (const Bitmap& rPreview);
56 : bool HasPreview (void) const;
57 :
58 0 : Bitmap GetMarkedPreview (void) const { return maMarkedPreview; }
59 : inline void SetMarkedPreview (const Bitmap& rMarkePreview);
60 :
61 897 : bool HasReplacement (void) const { return (mpReplacement.get() != NULL); }
62 : inline bool HasLosslessReplacement (void) const;
63 704 : void Invalidate (void) { mpReplacement.reset(); mpCompressor.reset(); mbIsUpToDate = false; }
64 3548 : bool IsPrecious (void) const { return mbIsPrecious; }
65 0 : void SetPrecious (bool bIsPrecious) { mbIsPrecious = bIsPrecious; }
66 :
67 : private:
68 : Bitmap maPreview;
69 : Bitmap maMarkedPreview;
70 : ::boost::shared_ptr<BitmapReplacement> mpReplacement;
71 : ::boost::shared_ptr<BitmapCompressor> mpCompressor;
72 : Size maBitmapSize;
73 : bool mbIsUpToDate;
74 : sal_Int32 mnLastAccessTime;
75 : // When this flag is set then the bitmap is not modified by a cache
76 : // compactor.
77 : bool mbIsPrecious;
78 : };
79 : class CacheEntry;
80 :
81 : class CacheHash {
82 : public:
83 6068 : size_t operator()(const BitmapCache::CacheKey& p) const
84 6068 : { return (size_t)p; }
85 : };
86 :
87 112 : class BitmapCache::CacheBitmapContainer
88 : : public ::boost::unordered_map<CacheKey, CacheEntry, CacheHash>
89 : {
90 : public:
91 112 : CacheBitmapContainer (void) {}
92 : };
93 :
94 : namespace {
95 :
96 : typedef ::std::vector<
97 : ::std::pair< ::sd::slidesorter::cache::BitmapCache::CacheKey,
98 : ::sd::slidesorter::cache::BitmapCache::CacheEntry>
99 : > SortableBitmapContainer;
100 :
101 : /** Compare elements of the bitmap cache according to their last access
102 : time.
103 : */
104 : class AccessTimeComparator
105 : {
106 : public:
107 0 : bool operator () (
108 : const SortableBitmapContainer::value_type& e1,
109 : const SortableBitmapContainer::value_type& e2)
110 : {
111 0 : return e1.second.GetAccessTime() < e2.second.GetAccessTime();
112 : }
113 : };
114 :
115 : } // end of anonymous namespace
116 :
117 : //===== BitmapCache =========================================================
118 :
119 112 : BitmapCache::BitmapCache (const sal_Int32 nMaximalNormalCacheSize)
120 : : maMutex(),
121 0 : mpBitmapContainer(new CacheBitmapContainer()),
122 : mnNormalCacheSize(0),
123 : mnPreciousCacheSize(0),
124 : mnCurrentAccessTime(0),
125 : mnMaximalNormalCacheSize(MAXIMAL_CACHE_SIZE),
126 : mpCacheCompactor(),
127 112 : mbIsFull(false)
128 : {
129 112 : if (nMaximalNormalCacheSize > 0)
130 0 : mnMaximalNormalCacheSize = nMaximalNormalCacheSize;
131 : else
132 : {
133 112 : Any aCacheSize (CacheConfiguration::Instance()->GetValue("CacheSize"));
134 112 : if (aCacheSize.has<sal_Int32>())
135 0 : aCacheSize >>= mnMaximalNormalCacheSize;
136 : }
137 :
138 112 : mpCacheCompactor = CacheCompactor::Create(*this,mnMaximalNormalCacheSize);
139 112 : }
140 :
141 224 : BitmapCache::~BitmapCache (void)
142 : {
143 112 : Clear();
144 112 : }
145 :
146 112 : void BitmapCache::Clear (void)
147 : {
148 112 : ::osl::MutexGuard aGuard (maMutex);
149 :
150 112 : mpBitmapContainer->clear();
151 112 : mnNormalCacheSize = 0;
152 112 : mnPreciousCacheSize = 0;
153 112 : mnCurrentAccessTime = 0;
154 112 : }
155 :
156 2387 : bool BitmapCache::HasBitmap (const CacheKey& rKey)
157 : {
158 2387 : ::osl::MutexGuard aGuard (maMutex);
159 :
160 2387 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
161 9548 : return (iEntry != mpBitmapContainer->end()
162 9548 : && (iEntry->second.HasPreview() || iEntry->second.HasReplacement()));
163 : }
164 :
165 1046 : bool BitmapCache::BitmapIsUpToDate (const CacheKey& rKey)
166 : {
167 1046 : ::osl::MutexGuard aGuard (maMutex);
168 :
169 1046 : bool bIsUpToDate = false;
170 1046 : CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
171 1046 : if (aIterator != mpBitmapContainer->end())
172 696 : bIsUpToDate = aIterator->second.IsUpToDate();
173 :
174 1046 : return bIsUpToDate;
175 : }
176 :
177 364 : Bitmap BitmapCache::GetBitmap (const CacheKey& rKey)
178 : {
179 364 : ::osl::MutexGuard aGuard (maMutex);
180 :
181 364 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
182 364 : if (iEntry == mpBitmapContainer->end())
183 : {
184 : // Create an empty bitmap for the given key that acts as placeholder
185 : // until we are given the real one. Mark it as not being up to date.
186 0 : SetBitmap(rKey, Bitmap(), false);
187 0 : iEntry = mpBitmapContainer->find(rKey);
188 0 : iEntry->second.SetUpToDate(false);
189 : }
190 : else
191 : {
192 364 : iEntry->second.SetAccessTime(mnCurrentAccessTime++);
193 :
194 : // Maybe we have to decompress the preview.
195 364 : if ( ! iEntry->second.HasPreview() && iEntry->second.HasReplacement())
196 : {
197 0 : UpdateCacheSize(iEntry->second, REMOVE);
198 0 : iEntry->second.Decompress();
199 0 : UpdateCacheSize(iEntry->second, ADD);
200 : }
201 : }
202 364 : return iEntry->second.GetPreview();
203 : }
204 :
205 0 : Bitmap BitmapCache::GetMarkedBitmap (const CacheKey& rKey)
206 : {
207 0 : ::osl::MutexGuard aGuard (maMutex);
208 :
209 0 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
210 0 : if (iEntry != mpBitmapContainer->end())
211 : {
212 0 : iEntry->second.SetAccessTime(mnCurrentAccessTime++);
213 0 : return iEntry->second.GetMarkedPreview();
214 : }
215 : else
216 0 : return Bitmap();
217 : }
218 :
219 2 : void BitmapCache::ReleaseBitmap (const CacheKey& rKey)
220 : {
221 2 : ::osl::MutexGuard aGuard (maMutex);
222 :
223 2 : CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
224 2 : if (aIterator != mpBitmapContainer->end())
225 : {
226 0 : UpdateCacheSize(aIterator->second, REMOVE);
227 0 : mpBitmapContainer->erase(aIterator);
228 2 : }
229 2 : }
230 :
231 967 : bool BitmapCache::InvalidateBitmap (const CacheKey& rKey)
232 : {
233 967 : ::osl::MutexGuard aGuard (maMutex);
234 :
235 967 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
236 967 : if (iEntry != mpBitmapContainer->end())
237 : {
238 605 : iEntry->second.SetUpToDate(false);
239 :
240 : // When there is a preview then we release the replacement. The
241 : // preview itself is kept until a new one is created.
242 605 : if (iEntry->second.HasPreview())
243 : {
244 601 : UpdateCacheSize(iEntry->second, REMOVE);
245 601 : iEntry->second.Invalidate();
246 601 : UpdateCacheSize(iEntry->second, ADD);
247 : }
248 605 : return true;
249 : }
250 : else
251 362 : return false;
252 : }
253 :
254 83 : void BitmapCache::InvalidateCache (void)
255 : {
256 83 : ::osl::MutexGuard aGuard (maMutex);
257 :
258 83 : CacheBitmapContainer::iterator iEntry;
259 186 : for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
260 : {
261 103 : iEntry->second.Invalidate();
262 : }
263 83 : ReCalculateTotalCacheSize();
264 83 : }
265 :
266 181 : void BitmapCache::SetBitmap (
267 : const CacheKey& rKey,
268 : const Bitmap& rPreview,
269 : bool bIsPrecious)
270 : {
271 181 : ::osl::MutexGuard aGuard (maMutex);
272 :
273 181 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
274 181 : if (iEntry != mpBitmapContainer->end())
275 : {
276 170 : UpdateCacheSize(iEntry->second, REMOVE);
277 170 : iEntry->second.SetPreview(rPreview);
278 170 : iEntry->second.SetUpToDate(true);
279 170 : iEntry->second.SetAccessTime(mnCurrentAccessTime++);
280 : }
281 : else
282 : {
283 11 : iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
284 : rKey,
285 : CacheEntry(rPreview, mnCurrentAccessTime++, bIsPrecious))
286 22 : ).first;
287 : }
288 :
289 181 : if (iEntry != mpBitmapContainer->end())
290 181 : UpdateCacheSize(iEntry->second, ADD);
291 181 : }
292 :
293 0 : void BitmapCache::SetMarkedBitmap (
294 : const CacheKey& rKey,
295 : const Bitmap& rPreview)
296 : {
297 0 : ::osl::MutexGuard aGuard (maMutex);
298 :
299 0 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
300 0 : if (iEntry != mpBitmapContainer->end())
301 : {
302 0 : UpdateCacheSize(iEntry->second, REMOVE);
303 0 : iEntry->second.SetMarkedPreview(rPreview);
304 0 : iEntry->second.SetAccessTime(mnCurrentAccessTime++);
305 0 : UpdateCacheSize(iEntry->second, ADD);
306 0 : }
307 0 : }
308 :
309 985 : void BitmapCache::SetPrecious (const CacheKey& rKey, bool bIsPrecious)
310 : {
311 985 : ::osl::MutexGuard aGuard (maMutex);
312 :
313 985 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
314 985 : if (iEntry != mpBitmapContainer->end())
315 : {
316 860 : if (iEntry->second.IsPrecious() != bIsPrecious)
317 : {
318 0 : UpdateCacheSize(iEntry->second, REMOVE);
319 0 : iEntry->second.SetPrecious(bIsPrecious);
320 0 : UpdateCacheSize(iEntry->second, ADD);
321 : }
322 : }
323 125 : else if (bIsPrecious)
324 : {
325 125 : iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
326 : rKey,
327 : CacheEntry(Bitmap(), mnCurrentAccessTime++, bIsPrecious))
328 250 : ).first;
329 125 : UpdateCacheSize(iEntry->second, ADD);
330 985 : }
331 985 : }
332 :
333 83 : void BitmapCache::ReCalculateTotalCacheSize (void)
334 : {
335 83 : ::osl::MutexGuard aGuard (maMutex);
336 :
337 83 : mnNormalCacheSize = 0;
338 83 : mnPreciousCacheSize = 0;
339 83 : CacheBitmapContainer::iterator iEntry;
340 186 : for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
341 : {
342 103 : if (iEntry->second.IsPrecious())
343 103 : mnPreciousCacheSize += iEntry->second.GetMemorySize();
344 : else
345 0 : mnNormalCacheSize += iEntry->second.GetMemorySize();
346 : }
347 83 : mbIsFull = (mnNormalCacheSize >= mnMaximalNormalCacheSize);
348 :
349 83 : SAL_INFO("sd.sls", OSL_THIS_FUNC << ": cache size is " << mnNormalCacheSize << "/" << mnPreciousCacheSize);
350 83 : }
351 :
352 0 : void BitmapCache::Recycle (const BitmapCache& rCache)
353 : {
354 0 : ::osl::MutexGuard aGuard (maMutex);
355 :
356 0 : CacheBitmapContainer::const_iterator iOtherEntry;
357 0 : for (iOtherEntry=rCache.mpBitmapContainer->begin();
358 0 : iOtherEntry!=rCache.mpBitmapContainer->end();
359 : ++iOtherEntry)
360 : {
361 0 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(iOtherEntry->first));
362 0 : if (iEntry == mpBitmapContainer->end())
363 : {
364 0 : iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
365 0 : iOtherEntry->first,
366 : CacheEntry(mnCurrentAccessTime++, true))
367 0 : ).first;
368 0 : UpdateCacheSize(iEntry->second, ADD);
369 : }
370 0 : if (iEntry != mpBitmapContainer->end())
371 : {
372 0 : UpdateCacheSize(iEntry->second, REMOVE);
373 0 : iEntry->second.Recycle(iOtherEntry->second);
374 0 : UpdateCacheSize(iEntry->second, ADD);
375 : }
376 0 : }
377 0 : }
378 :
379 0 : ::std::unique_ptr<BitmapCache::CacheIndex> BitmapCache::GetCacheIndex (
380 : bool bIncludePrecious,
381 : bool bIncludeNoPreview) const
382 : {
383 0 : ::osl::MutexGuard aGuard (maMutex);
384 :
385 : // Create a copy of the bitmap container.
386 0 : SortableBitmapContainer aSortedContainer;
387 0 : aSortedContainer.reserve(mpBitmapContainer->size());
388 :
389 : // Copy the relevant entries.
390 0 : CacheBitmapContainer::iterator iEntry;
391 0 : for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
392 : {
393 0 : if ( ! bIncludePrecious && iEntry->second.IsPrecious())
394 0 : continue;
395 :
396 0 : if ( ! bIncludeNoPreview && ! iEntry->second.HasPreview())
397 0 : continue;
398 :
399 : aSortedContainer.push_back(SortableBitmapContainer::value_type(
400 0 : iEntry->first,iEntry->second));
401 : }
402 :
403 : // Sort the remaining entries.
404 0 : ::std::sort(aSortedContainer.begin(), aSortedContainer.end(), AccessTimeComparator());
405 :
406 : // Return a list with the keys of the sorted entries.
407 0 : ::std::unique_ptr<CacheIndex> pIndex(new CacheIndex());
408 0 : SortableBitmapContainer::iterator iIndexEntry;
409 0 : pIndex->reserve(aSortedContainer.size());
410 0 : for (iIndexEntry=aSortedContainer.begin(); iIndexEntry!=aSortedContainer.end(); ++iIndexEntry)
411 0 : pIndex->push_back(iIndexEntry->first);
412 0 : return pIndex;
413 : }
414 :
415 0 : void BitmapCache::Compress (
416 : const CacheKey& rKey,
417 : const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
418 : {
419 0 : ::osl::MutexGuard aGuard (maMutex);
420 :
421 0 : CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
422 0 : if (iEntry != mpBitmapContainer->end() && iEntry->second.HasPreview())
423 : {
424 0 : UpdateCacheSize(iEntry->second, REMOVE);
425 0 : iEntry->second.Compress(rpCompressor);
426 0 : UpdateCacheSize(iEntry->second, ADD);
427 0 : }
428 0 : }
429 :
430 1678 : void BitmapCache::UpdateCacheSize (const CacheEntry& rEntry, CacheOperation eOperation)
431 : {
432 1678 : sal_Int32 nEntrySize (rEntry.GetMemorySize());
433 1678 : sal_Int32& rCacheSize (rEntry.IsPrecious() ? mnPreciousCacheSize : mnNormalCacheSize);
434 1678 : switch (eOperation)
435 : {
436 : case ADD:
437 907 : rCacheSize += nEntrySize;
438 907 : if ( ! rEntry.IsPrecious() && mnNormalCacheSize>mnMaximalNormalCacheSize)
439 : {
440 0 : mbIsFull = true;
441 : SAL_INFO("sd.sls", OSL_THIS_FUNC << ": cache size is " << mnNormalCacheSize << " > " << mnMaximalNormalCacheSize);
442 0 : mpCacheCompactor->RequestCompaction();
443 : }
444 907 : break;
445 :
446 : case REMOVE:
447 771 : rCacheSize -= nEntrySize;
448 771 : if (mnNormalCacheSize < mnMaximalNormalCacheSize)
449 771 : mbIsFull = false;
450 771 : break;
451 :
452 : default:
453 : OSL_ASSERT(false);
454 0 : break;
455 : }
456 1678 : }
457 :
458 : //===== CacheEntry ============================================================
459 :
460 0 : BitmapCache::CacheEntry::CacheEntry(
461 : sal_Int32 nLastAccessTime,
462 : bool bIsPrecious)
463 : : maPreview(),
464 : maMarkedPreview(),
465 : mbIsUpToDate(true),
466 : mnLastAccessTime(nLastAccessTime),
467 0 : mbIsPrecious(bIsPrecious)
468 : {
469 0 : }
470 :
471 136 : BitmapCache::CacheEntry::CacheEntry(
472 : const Bitmap& rPreview,
473 : sal_Int32 nLastAccessTime,
474 : bool bIsPrecious)
475 : : maPreview(rPreview),
476 : maMarkedPreview(),
477 : mbIsUpToDate(true),
478 : mnLastAccessTime(nLastAccessTime),
479 136 : mbIsPrecious(bIsPrecious)
480 : {
481 136 : }
482 :
483 0 : inline void BitmapCache::CacheEntry::Recycle (const CacheEntry& rEntry)
484 : {
485 0 : if ((rEntry.HasPreview() || rEntry.HasLosslessReplacement())
486 0 : && ! (HasPreview() || HasLosslessReplacement()))
487 : {
488 0 : maPreview = rEntry.maPreview;
489 0 : maMarkedPreview = rEntry.maMarkedPreview;
490 0 : mpReplacement = rEntry.mpReplacement;
491 0 : mpCompressor = rEntry.mpCompressor;
492 0 : mnLastAccessTime = rEntry.mnLastAccessTime;
493 0 : mbIsUpToDate = rEntry.mbIsUpToDate;
494 : }
495 0 : }
496 :
497 1781 : inline sal_Int32 BitmapCache::CacheEntry::GetMemorySize (void) const
498 : {
499 1781 : sal_Int32 nSize (0);
500 1781 : nSize += maPreview.GetSizeBytes();
501 1781 : nSize += maMarkedPreview.GetSizeBytes();
502 1781 : if (mpReplacement.get() != NULL)
503 0 : nSize += mpReplacement->GetMemorySize();
504 1781 : return nSize;
505 : }
506 :
507 0 : void BitmapCache::CacheEntry::Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
508 : {
509 0 : if ( ! maPreview.IsEmpty())
510 : {
511 0 : if (mpReplacement.get() == NULL)
512 : {
513 0 : mpReplacement = rpCompressor->Compress(maPreview);
514 :
515 : #if OSL_DEBUG_LEVEL > 2
516 : sal_uInt32 nOldSize (maPreview.GetSizeBytes());
517 : sal_uInt32 nNewSize (mpReplacement.get()!=NULL ? mpReplacement->GetMemorySize() : 0);
518 : if (nOldSize == 0)
519 : nOldSize = 1;
520 : sal_Int32 nRatio (100L * nNewSize / nOldSize);
521 : SAL_INFO("sd.sls", OSL_THIS_FUNC << ": compressing bitmap for " << %x << " from " << nOldSize << " to " << nNewSize << " bytes (" << nRatio << "%)");
522 : #endif
523 :
524 0 : mpCompressor = rpCompressor;
525 : }
526 :
527 0 : maPreview.SetEmpty();
528 0 : maMarkedPreview.SetEmpty();
529 : }
530 0 : }
531 :
532 0 : inline void BitmapCache::CacheEntry::Decompress (void)
533 : {
534 0 : if (mpReplacement.get()!=NULL && mpCompressor.get()!=NULL && maPreview.IsEmpty())
535 : {
536 0 : maPreview = mpCompressor->Decompress(*mpReplacement);
537 0 : maMarkedPreview.SetEmpty();
538 0 : if ( ! mpCompressor->IsLossless())
539 0 : mbIsUpToDate = false;
540 : }
541 0 : }
542 :
543 170 : inline void BitmapCache::CacheEntry::SetPreview (const Bitmap& rPreview)
544 : {
545 170 : maPreview = rPreview;
546 170 : maMarkedPreview.SetEmpty();
547 170 : mpReplacement.reset();
548 170 : mpCompressor.reset();
549 170 : }
550 :
551 3127 : bool BitmapCache::CacheEntry::HasPreview (void) const
552 : {
553 3127 : return ! maPreview.IsEmpty();
554 : }
555 :
556 0 : inline void BitmapCache::CacheEntry::SetMarkedPreview (const Bitmap& rMarkedPreview)
557 : {
558 0 : maMarkedPreview = rMarkedPreview;
559 0 : }
560 :
561 0 : inline bool BitmapCache::CacheEntry::HasLosslessReplacement (void) const
562 : {
563 0 : return mpReplacement.get()!=NULL
564 0 : && mpCompressor.get()!=NULL
565 0 : && mpCompressor->IsLossless();
566 : }
567 :
568 114 : } } } // end of namespace ::sd::slidesorter::cache
569 :
570 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|