INTEGRATION: CWS impress69 (1.3.334); FILE MERGED
2005/10/14 11:00:58 af 1.3.334.6: RESYNC: (1.3-1.4); FILE MERGED 2005/09/23 07:47:59 af 1.3.334.5: #i54118# Recycle does not replace existing previews anymore. 2005/09/22 14:21:51 af 1.3.334.4: #i54916# Fixed Solaris compiler problem. 2005/09/22 09:23:50 af 1.3.334.3: #i54916# Added visualization for slide sorter cache. 2005/09/21 15:23:12 af 1.3.334.2: #i54916# Support for bitmap compression. 2005/09/14 11:04:25 af 1.3.334.1: #i54589# Added IsEmpty() and Recycle() methods. Keeping track of sizes for normal and precious bitmaps.
This commit is contained in:
530
sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx
vendored
530
sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx
vendored
@@ -4,9 +4,9 @@
|
|||||||
*
|
*
|
||||||
* $RCSfile: SlsBitmapCache.cxx,v $
|
* $RCSfile: SlsBitmapCache.cxx,v $
|
||||||
*
|
*
|
||||||
* $Revision: 1.4 $
|
* $Revision: 1.5 $
|
||||||
*
|
*
|
||||||
* last change: $Author: rt $ $Date: 2005-09-09 06:09:08 $
|
* last change: $Author: rt $ $Date: 2005-10-24 07:39:05 $
|
||||||
*
|
*
|
||||||
* The Contents of this file are made available subject to
|
* The Contents of this file are made available subject to
|
||||||
* the terms of GNU Lesser General Public License Version 2.1.
|
* the terms of GNU Lesser General Public License Version 2.1.
|
||||||
@@ -34,16 +34,124 @@
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
#include "SlsBitmapCache.hxx"
|
#include "SlsBitmapCache.hxx"
|
||||||
|
#include "SlsCacheCompactor.hxx"
|
||||||
|
#include "SlsBitmapCompressor.hxx"
|
||||||
|
#include "SlsCacheConfiguration.hxx"
|
||||||
|
|
||||||
|
#include "taskpane/SlideSorterCacheDisplay.hxx"
|
||||||
|
#include "sdpage.hxx"
|
||||||
|
#include "drawdoc.hxx"
|
||||||
|
|
||||||
|
// Uncomment the following define for some more OSL_TRACE messages.
|
||||||
|
#ifdef DEBUG
|
||||||
|
//#define VERBOSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define the default value for the maximal cache size that is used for
|
||||||
|
// previews that are currently not visible. The visible previews are all
|
||||||
|
// held in memory at all times. This default is used only when the
|
||||||
|
// configuration does not have a value.
|
||||||
|
static const sal_Int32 MAXIMAL_CACHE_SIZE = 4L*1024L*1024L;
|
||||||
|
|
||||||
|
using namespace ::com::sun::star::uno;
|
||||||
|
|
||||||
namespace sd { namespace slidesorter { namespace cache {
|
namespace sd { namespace slidesorter { namespace cache {
|
||||||
|
|
||||||
|
class BitmapCache::CacheEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CacheEntry(const ::boost::shared_ptr<BitmapEx>& rpBitmap,
|
||||||
|
sal_Int32 nLastAccessTime, bool bIsPrecious);
|
||||||
|
CacheEntry(sal_Int32 nLastAccessTime, bool bIsPrecious);
|
||||||
|
~CacheEntry (void) {};
|
||||||
|
inline void CacheEntry::Recycle (const CacheEntry& rEntry);
|
||||||
|
inline sal_Int32 GetMemorySize (void) const;
|
||||||
|
void Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor);
|
||||||
|
inline void Decompress (void);
|
||||||
|
|
||||||
|
bool IsUpToDate (void) const { return mbIsUpToDate; }
|
||||||
|
void SetUpToDate (bool bIsUpToDate) { mbIsUpToDate = bIsUpToDate; }
|
||||||
|
sal_Int32 GetAccessTime (void) const { return mnLastAccessTime; }
|
||||||
|
void SetAccessTime (sal_Int32 nAccessTime) { mnLastAccessTime = nAccessTime; }
|
||||||
|
::boost::shared_ptr<BitmapEx> GetPreview (void) const { return mpPreview; }
|
||||||
|
inline void SetPreview (const ::boost::shared_ptr<BitmapEx>& rpPreview);
|
||||||
|
bool HasPreview (void) const { return (mpPreview.get() != NULL); }
|
||||||
|
bool HasReplacement (void) const { return (mpReplacement.get() != NULL); }
|
||||||
|
inline bool HasLosslessReplacement (void) const;
|
||||||
|
void Clear (void) { mpPreview.reset(); mpReplacement.reset(); mpCompressor.reset(); }
|
||||||
|
void Invalidate (void) { mpReplacement.reset(); mpCompressor.reset(); mbIsUpToDate = false; }
|
||||||
|
bool IsPrecious (void) const { return mbIsPrecious; }
|
||||||
|
void SetPrecious (bool bIsPrecious) { mbIsPrecious = bIsPrecious; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
::boost::shared_ptr<BitmapEx> mpPreview;
|
||||||
|
::boost::shared_ptr<BitmapReplacement> mpReplacement;
|
||||||
|
::boost::shared_ptr<BitmapCompressor> mpCompressor;
|
||||||
|
Size maBitmapSize;
|
||||||
|
bool mbIsUpToDate;
|
||||||
|
sal_Int32 mnLastAccessTime;
|
||||||
|
// When this flag is set then the bitmap is not modified by a cache
|
||||||
|
// compactor.
|
||||||
|
bool mbIsPrecious;
|
||||||
|
};
|
||||||
|
class CacheEntry;
|
||||||
|
|
||||||
|
class CacheHash {
|
||||||
|
public:
|
||||||
|
size_t operator()(const BitmapCache::CacheKey& p) const
|
||||||
|
{ return (size_t)p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class BitmapCache::CacheBitmapContainer
|
||||||
|
: public ::std::hash_map<CacheKey, CacheEntry, CacheHash>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CacheBitmapContainer (void) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
typedef ::std::vector<
|
||||||
|
::std::pair< ::sd::slidesorter::cache::BitmapCache::CacheKey,
|
||||||
|
::sd::slidesorter::cache::BitmapCache::CacheEntry>
|
||||||
|
> SortableBitmapContainer;
|
||||||
|
|
||||||
|
/** Compare elements of the bitmap cache according to their last access
|
||||||
|
time.
|
||||||
|
*/
|
||||||
|
class AccessTimeComparator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool operator () (
|
||||||
|
const SortableBitmapContainer::value_type& e1,
|
||||||
|
const SortableBitmapContainer::value_type& e2)
|
||||||
|
{
|
||||||
|
return e1.second.GetAccessTime() < e2.second.GetAccessTime();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
//===== BitmapCache =========================================================
|
//===== BitmapCache =========================================================
|
||||||
|
|
||||||
BitmapCache::BitmapCache (void)
|
BitmapCache::BitmapCache (void)
|
||||||
: mnSize (0),
|
: maMutex(),
|
||||||
mnCurrentAccessTime(0)
|
mpBitmapContainer(new CacheBitmapContainer()),
|
||||||
|
mnNormalCacheSize(0),
|
||||||
|
mnPreciousCacheSize(0),
|
||||||
|
mnCurrentAccessTime(0),
|
||||||
|
mnMaximalNormalCacheSize(MAXIMAL_CACHE_SIZE),
|
||||||
|
mpCacheCompactor(),
|
||||||
|
mbIsFull(false)
|
||||||
{
|
{
|
||||||
|
Any aCacheSize (CacheConfiguration::Instance()->GetValue(
|
||||||
|
::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CacheSize"))));
|
||||||
|
if (aCacheSize.has<sal_Int32>())
|
||||||
|
aCacheSize >>= mnMaximalNormalCacheSize;
|
||||||
|
|
||||||
|
mpCacheCompactor = CacheCompactor::Create(*this,mnMaximalNormalCacheSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -61,17 +169,34 @@ void BitmapCache::Clear (void)
|
|||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
maBitmapContainer.clear();
|
mpBitmapContainer->clear();
|
||||||
mnSize = 0;
|
mnNormalCacheSize = 0;
|
||||||
|
mnPreciousCacheSize = 0;
|
||||||
mnCurrentAccessTime = 0;
|
mnCurrentAccessTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool BitmapCache::IsEmpty (void) const
|
||||||
|
{
|
||||||
|
return mpBitmapContainer->empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool BitmapCache::IsFull (void) const
|
||||||
|
{
|
||||||
|
return mbIsFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sal_Int32 BitmapCache::GetSize (void)
|
sal_Int32 BitmapCache::GetSize (void)
|
||||||
{
|
{
|
||||||
return mnSize;
|
return mnNormalCacheSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -81,7 +206,9 @@ bool BitmapCache::HasBitmap (const CacheKey& rKey)
|
|||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
return (maBitmapContainer.find(rKey) != maBitmapContainer.end());
|
CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
|
||||||
|
return (iEntry != mpBitmapContainer->end()
|
||||||
|
&& (iEntry->second.HasPreview() || iEntry->second.HasReplacement()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -92,9 +219,9 @@ bool BitmapCache::BitmapIsUpToDate (const CacheKey& rKey)
|
|||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
bool bIsUpToDate = false;
|
bool bIsUpToDate = false;
|
||||||
CacheBitmapContainer::iterator aIterator (maBitmapContainer.find(rKey));
|
CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
|
||||||
if (aIterator != maBitmapContainer.end())
|
if (aIterator != mpBitmapContainer->end())
|
||||||
bIsUpToDate = aIterator->second.mbIsUpToDate;
|
bIsUpToDate = aIterator->second.IsUpToDate();
|
||||||
|
|
||||||
return bIsUpToDate;
|
return bIsUpToDate;
|
||||||
}
|
}
|
||||||
@@ -102,22 +229,33 @@ bool BitmapCache::BitmapIsUpToDate (const CacheKey& rKey)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const BitmapEx& BitmapCache::GetBitmap (const CacheKey& rKey)
|
::boost::shared_ptr<BitmapEx> BitmapCache::GetBitmap (const CacheKey& rKey)
|
||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
CacheBitmapContainer::iterator aIterator (maBitmapContainer.find(rKey));
|
CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
|
||||||
if (aIterator == maBitmapContainer.end())
|
if (iEntry == mpBitmapContainer->end())
|
||||||
{
|
{
|
||||||
// Create an empty bitmap for the given key that acts as placeholder
|
// Create an empty bitmap for the given key that acts as placeholder
|
||||||
// until we are given the real one. Mark it as not being up to date.
|
// until we are given the real one. Mark it as not being up to date.
|
||||||
SetBitmap (rKey, BitmapEx(), false);
|
SetBitmap (rKey, ::boost::shared_ptr<BitmapEx>(new BitmapEx()), false);
|
||||||
aIterator = maBitmapContainer.find(rKey);
|
iEntry = mpBitmapContainer->find(rKey);
|
||||||
aIterator->second.mbIsUpToDate = false;
|
iEntry->second.SetUpToDate(false);
|
||||||
|
SSCD_SET_UPTODATE(iEntry->first,false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
aIterator->second.mnLastAccessTime = mnCurrentAccessTime++;
|
{
|
||||||
return aIterator->second.maBitmap;
|
iEntry->second.SetAccessTime(mnCurrentAccessTime++);
|
||||||
|
|
||||||
|
// Maybe we have to decompress the preview.
|
||||||
|
if ( ! iEntry->second.HasPreview() && iEntry->second.HasReplacement())
|
||||||
|
{
|
||||||
|
UpdateCacheSize(iEntry->second, REMOVE);
|
||||||
|
iEntry->second.Decompress();
|
||||||
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return iEntry->second.GetPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -127,11 +265,11 @@ void BitmapCache::ReleaseBitmap (const CacheKey& rKey)
|
|||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
CacheBitmapContainer::iterator aIterator (maBitmapContainer.find(rKey));
|
CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
|
||||||
if (aIterator != maBitmapContainer.end())
|
if (aIterator != mpBitmapContainer->end())
|
||||||
{
|
{
|
||||||
mnSize -= aIterator->second.maBitmap.GetSizeBytes();
|
UpdateCacheSize(aIterator->second, REMOVE);
|
||||||
maBitmapContainer.erase (aIterator);
|
mpBitmapContainer->erase(aIterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,43 +280,69 @@ void BitmapCache::InvalidateBitmap (const CacheKey& rKey)
|
|||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
CacheBitmapContainer::iterator aIterator (maBitmapContainer.find(rKey));
|
CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
|
||||||
if (aIterator != maBitmapContainer.end())
|
if (iEntry != mpBitmapContainer->end())
|
||||||
{
|
{
|
||||||
aIterator->second.mbIsUpToDate = false;
|
iEntry->second.SetUpToDate(false);
|
||||||
|
SSCD_SET_UPTODATE(iEntry->first,false);
|
||||||
|
|
||||||
|
// When there is a preview then we release the replacement. The
|
||||||
|
// preview itself is kept until a new one is created.
|
||||||
|
if (iEntry->second.HasPreview())
|
||||||
|
{
|
||||||
|
UpdateCacheSize(iEntry->second, REMOVE);
|
||||||
|
iEntry->second.Invalidate();
|
||||||
|
SSCD_SET_UPTODATE(iEntry->first,false);
|
||||||
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapCache::InvalidateCache (void)
|
||||||
|
{
|
||||||
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
|
CacheBitmapContainer::iterator iEntry;
|
||||||
|
for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
|
||||||
|
{
|
||||||
|
iEntry->second.Invalidate();
|
||||||
|
SSCD_SET_UPTODATE(iEntry->first,false);
|
||||||
|
}
|
||||||
|
ReCalculateTotalCacheSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void BitmapCache::SetBitmap (
|
void BitmapCache::SetBitmap (
|
||||||
const CacheKey& rKey,
|
const CacheKey& rKey,
|
||||||
const BitmapEx& rBitmap,
|
const ::boost::shared_ptr<BitmapEx>& rpPreview,
|
||||||
bool bIsPrecious)
|
bool bIsPrecious)
|
||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
CacheBitmapContainer::iterator aIterator (maBitmapContainer.find(rKey));
|
CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
|
||||||
if (aIterator != maBitmapContainer.end())
|
if (iEntry != mpBitmapContainer->end())
|
||||||
{
|
{
|
||||||
// Here we technically first insert the bitmap into the cache and
|
UpdateCacheSize(iEntry->second, REMOVE);
|
||||||
// then make room for it.
|
iEntry->second.SetPreview(rpPreview);
|
||||||
mnSize -= aIterator->second.maBitmap.GetSizeBytes();
|
iEntry->second.SetUpToDate(true);
|
||||||
aIterator->second.maBitmap = rBitmap;
|
SSCD_SET_UPTODATE(iEntry->first,true);
|
||||||
aIterator->second.mbIsUpToDate = true;
|
iEntry->second.SetAccessTime(mnCurrentAccessTime++);
|
||||||
aIterator->second.mnLastAccessTime = mnCurrentAccessTime++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
maBitmapContainer.insert (CacheBitmapContainer::value_type (
|
iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
|
||||||
rKey,
|
rKey,
|
||||||
CacheEntry (rBitmap, mnCurrentAccessTime++, bIsPrecious)));
|
CacheEntry (rpPreview, mnCurrentAccessTime++, bIsPrecious))
|
||||||
|
).first;
|
||||||
}
|
}
|
||||||
mnSize += rBitmap.GetSizeBytes();
|
|
||||||
|
|
||||||
OSL_TRACE ("bitmap cache occupies %d bytes for %d bitmaps",
|
if (iEntry != mpBitmapContainer->end())
|
||||||
mnSize, maBitmapContainer.size());
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -188,9 +352,9 @@ bool BitmapCache::IsPrecious (const CacheKey& rKey)
|
|||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
CacheBitmapContainer::iterator aIterator (maBitmapContainer.find(rKey));
|
CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
|
||||||
if (aIterator != maBitmapContainer.end())
|
if (aIterator != mpBitmapContainer->end())
|
||||||
return aIterator->second.mbIsPrecious;
|
return aIterator->second.IsPrecious();
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -202,24 +366,290 @@ void BitmapCache::SetPrecious (const CacheKey& rKey, bool bIsPrecious)
|
|||||||
{
|
{
|
||||||
::osl::MutexGuard aGuard (maMutex);
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
CacheBitmapContainer::iterator aIterator (maBitmapContainer.find(rKey));
|
CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
|
||||||
if (aIterator != maBitmapContainer.end())
|
if (iEntry != mpBitmapContainer->end())
|
||||||
aIterator->second.mbIsPrecious = bIsPrecious;
|
{
|
||||||
|
if (iEntry->second.IsPrecious() != bIsPrecious)
|
||||||
|
{
|
||||||
|
UpdateCacheSize(iEntry->second, REMOVE);
|
||||||
|
iEntry->second.SetPrecious(bIsPrecious);
|
||||||
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (bIsPrecious)
|
else if (bIsPrecious)
|
||||||
maBitmapContainer.insert (CacheBitmapContainer::value_type (
|
{
|
||||||
|
iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
|
||||||
rKey,
|
rKey,
|
||||||
CacheEntry (BitmapEx(), mnCurrentAccessTime++, bIsPrecious)));
|
CacheEntry (::boost::shared_ptr<BitmapEx>(new BitmapEx()),
|
||||||
|
mnCurrentAccessTime++, bIsPrecious))).first;
|
||||||
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const CacheBitmapContainer& BitmapCache::GetContainer (void) const
|
void BitmapCache::ReCalculateTotalCacheSize (void)
|
||||||
{
|
{
|
||||||
return maBitmapContainer;
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
|
mnNormalCacheSize = 0;
|
||||||
|
mnPreciousCacheSize = 0;
|
||||||
|
CacheBitmapContainer::iterator iEntry;
|
||||||
|
for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
|
||||||
|
{
|
||||||
|
if (iEntry->second.IsPrecious())
|
||||||
|
mnPreciousCacheSize += iEntry->second.GetMemorySize();
|
||||||
|
else
|
||||||
|
mnNormalCacheSize += iEntry->second.GetMemorySize();
|
||||||
|
}
|
||||||
|
mbIsFull = (mnNormalCacheSize >= mnMaximalNormalCacheSize);
|
||||||
|
|
||||||
|
#ifdef VERBOSE
|
||||||
|
OSL_TRACE("cache size is %d/%d", mnNormalCacheSize, mnPreciousCacheSize);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapCache::Recycle (const BitmapCache& rCache)
|
||||||
|
{
|
||||||
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
|
CacheBitmapContainer::const_iterator iOtherEntry;
|
||||||
|
for (iOtherEntry=rCache.mpBitmapContainer->begin();
|
||||||
|
iOtherEntry!=rCache.mpBitmapContainer->end();
|
||||||
|
++iOtherEntry)
|
||||||
|
{
|
||||||
|
CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(iOtherEntry->first));
|
||||||
|
if (iEntry == mpBitmapContainer->end())
|
||||||
|
{
|
||||||
|
iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
|
||||||
|
iOtherEntry->first,
|
||||||
|
CacheEntry(mnCurrentAccessTime++, true))
|
||||||
|
).first;
|
||||||
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
|
}
|
||||||
|
if (iEntry != mpBitmapContainer->end())
|
||||||
|
{
|
||||||
|
UpdateCacheSize(iEntry->second, REMOVE);
|
||||||
|
iEntry->second.Recycle(iOtherEntry->second);
|
||||||
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
::std::auto_ptr<BitmapCache::CacheIndex> BitmapCache::GetCacheIndex (
|
||||||
|
bool bIncludePrecious,
|
||||||
|
bool bIncludeNoPreview) const
|
||||||
|
{
|
||||||
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
|
// Create a copy of the bitmap container.
|
||||||
|
SortableBitmapContainer aSortedContainer;
|
||||||
|
aSortedContainer.reserve(mpBitmapContainer->size());
|
||||||
|
|
||||||
|
// Copy the relevant entries.
|
||||||
|
CacheBitmapContainer::iterator iEntry;
|
||||||
|
for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
|
||||||
|
{
|
||||||
|
if ( ! bIncludePrecious && iEntry->second.IsPrecious())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( ! bIncludeNoPreview && ! iEntry->second.HasPreview())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
aSortedContainer.push_back(SortableBitmapContainer::value_type(
|
||||||
|
iEntry->first,iEntry->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the remaining entries.
|
||||||
|
::std::sort(aSortedContainer.begin(), aSortedContainer.end(), AccessTimeComparator());
|
||||||
|
|
||||||
|
// Return a list with the keys of the sorted entries.
|
||||||
|
::std::auto_ptr<CacheIndex> pIndex(new CacheIndex());
|
||||||
|
SortableBitmapContainer::iterator iIndexEntry;
|
||||||
|
pIndex->reserve(aSortedContainer.size());
|
||||||
|
for (iIndexEntry=aSortedContainer.begin(); iIndexEntry!=aSortedContainer.end(); ++iIndexEntry)
|
||||||
|
pIndex->push_back(iIndexEntry->first);
|
||||||
|
return pIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapCache::Compress (
|
||||||
|
const CacheKey& rKey,
|
||||||
|
const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
|
||||||
|
{
|
||||||
|
::osl::MutexGuard aGuard (maMutex);
|
||||||
|
|
||||||
|
CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
|
||||||
|
if (iEntry != mpBitmapContainer->end() && iEntry->second.HasPreview())
|
||||||
|
{
|
||||||
|
UpdateCacheSize(iEntry->second, REMOVE);
|
||||||
|
iEntry->second.Compress(rpCompressor);
|
||||||
|
UpdateCacheSize(iEntry->second, ADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapCache::UpdateCacheSize (const CacheEntry& rEntry, CacheOperation eOperation)
|
||||||
|
{
|
||||||
|
sal_Int32 nEntrySize (rEntry.GetMemorySize());
|
||||||
|
sal_Int32& rCacheSize (rEntry.IsPrecious() ? mnPreciousCacheSize : mnNormalCacheSize);
|
||||||
|
switch (eOperation)
|
||||||
|
{
|
||||||
|
case ADD:
|
||||||
|
rCacheSize += nEntrySize;
|
||||||
|
if ( ! rEntry.IsPrecious() && mnNormalCacheSize>mnMaximalNormalCacheSize)
|
||||||
|
{
|
||||||
|
mbIsFull = true;
|
||||||
|
#ifdef VERBOSE
|
||||||
|
OSL_TRACE("cache size is %d > %d", mnNormalCacheSize,mnMaximalNormalCacheSize);
|
||||||
|
#endif
|
||||||
|
mpCacheCompactor->RequestCompaction();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOVE:
|
||||||
|
rCacheSize -= nEntrySize;
|
||||||
|
if (mnNormalCacheSize < mnMaximalNormalCacheSize)
|
||||||
|
mbIsFull = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
OSL_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===== CacheEntry ============================================================
|
||||||
|
|
||||||
|
BitmapCache::CacheEntry::CacheEntry(
|
||||||
|
sal_Int32 nLastAccessTime,
|
||||||
|
bool bIsPrecious)
|
||||||
|
: mpPreview(),
|
||||||
|
mbIsUpToDate(true),
|
||||||
|
mnLastAccessTime(nLastAccessTime),
|
||||||
|
mbIsPrecious(bIsPrecious)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BitmapCache::CacheEntry::CacheEntry(
|
||||||
|
const ::boost::shared_ptr<BitmapEx>& rpPreview,
|
||||||
|
sal_Int32 nLastAccessTime,
|
||||||
|
bool bIsPrecious)
|
||||||
|
: mpPreview(rpPreview),
|
||||||
|
mbIsUpToDate(true),
|
||||||
|
mnLastAccessTime(nLastAccessTime),
|
||||||
|
mbIsPrecious(bIsPrecious)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline void BitmapCache::CacheEntry::Recycle (const CacheEntry& rEntry)
|
||||||
|
{
|
||||||
|
if ((rEntry.HasPreview() || rEntry.HasLosslessReplacement())
|
||||||
|
&& ! (HasPreview() || HasLosslessReplacement()))
|
||||||
|
{
|
||||||
|
mpPreview = rEntry.mpPreview;
|
||||||
|
mpReplacement = rEntry.mpReplacement;
|
||||||
|
mpCompressor = rEntry.mpCompressor;
|
||||||
|
mnLastAccessTime = rEntry.mnLastAccessTime;
|
||||||
|
mbIsUpToDate = rEntry.mbIsUpToDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline sal_Int32 BitmapCache::CacheEntry::GetMemorySize (void) const
|
||||||
|
{
|
||||||
|
sal_Int32 nSize (0);
|
||||||
|
if (mpPreview.get() != NULL)
|
||||||
|
nSize += mpPreview->GetSizeBytes();
|
||||||
|
if (mpReplacement.get() != NULL)
|
||||||
|
nSize += mpReplacement->GetMemorySize();
|
||||||
|
return nSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapCache::CacheEntry::Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
|
||||||
|
{
|
||||||
|
if (mpPreview.get() != NULL)
|
||||||
|
{
|
||||||
|
if (mpReplacement.get() == NULL)
|
||||||
|
{
|
||||||
|
mpReplacement = rpCompressor->Compress(mpPreview);
|
||||||
|
|
||||||
|
#ifdef VERBOSE
|
||||||
|
sal_uInt32 nOldSize (mpPreview->GetSizeBytes());
|
||||||
|
sal_uInt32 nNewSize (mpReplacement.get()!=NULL ? mpReplacement->GetMemorySize() : 0);
|
||||||
|
if (nOldSize == 0)
|
||||||
|
nOldSize = 1;
|
||||||
|
sal_Int32 nRatio (100L * nNewSize / nOldSize);
|
||||||
|
OSL_TRACE("compressing bitmap for %x from %d to %d bytes (%d%%)",
|
||||||
|
this,
|
||||||
|
nOldSize,
|
||||||
|
nNewSize,
|
||||||
|
nRatio);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mpCompressor = rpCompressor;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpPreview.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline void BitmapCache::CacheEntry::Decompress (void)
|
||||||
|
{
|
||||||
|
if (mpReplacement.get()!=NULL && mpCompressor.get()!=NULL && mpPreview.get()==NULL)
|
||||||
|
{
|
||||||
|
mpPreview = mpCompressor->Decompress(*mpReplacement);
|
||||||
|
if ( ! mpCompressor->IsLossless())
|
||||||
|
mbIsUpToDate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline void BitmapCache::CacheEntry::SetPreview (const ::boost::shared_ptr<BitmapEx>& rpPreview)
|
||||||
|
{
|
||||||
|
mpPreview = rpPreview;
|
||||||
|
mpReplacement.reset();
|
||||||
|
mpCompressor.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool BitmapCache::CacheEntry::HasLosslessReplacement (void) const
|
||||||
|
{
|
||||||
|
return mpReplacement.get()!=NULL
|
||||||
|
&& mpCompressor.get()!=NULL
|
||||||
|
&& mpCompressor->IsLossless();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } } // end of namespace ::sd::slidesorter::cache
|
} } } // end of namespace ::sd::slidesorter::cache
|
||||||
|
Reference in New Issue
Block a user