summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter/cache
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/cache')
-rwxr-xr-xsd/source/ui/slidesorter/cache/SlsBitmapCache.cxx631
-rwxr-xr-xsd/source/ui/slidesorter/cache/SlsBitmapCache.hxx211
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx273
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx160
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx81
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx65
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx236
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx100
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx181
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx74
-rwxr-xr-xsd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx310
-rwxr-xr-xsd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx146
-rwxr-xr-xsd/source/ui/slidesorter/cache/SlsPageCache.cxx124
-rw-r--r--sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx446
-rwxr-xr-xsd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx254
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx138
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx365
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx78
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx48
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx55
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx291
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx133
-rwxr-xr-xsd/source/ui/slidesorter/cache/makefile.mk64
23 files changed, 4464 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx
new file mode 100755
index 000000000000..1bbecbef3d66
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx
@@ -0,0 +1,631 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.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 {
+
+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 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;
+ 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 (const sal_Int32 nMaximalNormalCacheSize)
+ : maMutex(),
+ mpBitmapContainer(new CacheBitmapContainer()),
+ mnNormalCacheSize(0),
+ mnPreciousCacheSize(0),
+ mnCurrentAccessTime(0),
+ mnMaximalNormalCacheSize(MAXIMAL_CACHE_SIZE),
+ mpCacheCompactor(),
+ mbIsFull(false)
+{
+ if (nMaximalNormalCacheSize > 0)
+ mnMaximalNormalCacheSize = nMaximalNormalCacheSize;
+ else
+ {
+ Any aCacheSize (CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CacheSize"))));
+ if (aCacheSize.has<sal_Int32>())
+ aCacheSize >>= mnMaximalNormalCacheSize;
+ }
+
+ mpCacheCompactor = CacheCompactor::Create(*this,mnMaximalNormalCacheSize);
+}
+
+
+
+
+BitmapCache::~BitmapCache (void)
+{
+ Clear();
+}
+
+
+
+
+void BitmapCache::Clear (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mpBitmapContainer->clear();
+ mnNormalCacheSize = 0;
+ mnPreciousCacheSize = 0;
+ mnCurrentAccessTime = 0;
+}
+
+
+
+
+bool BitmapCache::IsFull (void) const
+{
+ return mbIsFull;
+}
+
+
+
+
+sal_Int32 BitmapCache::GetSize (void)
+{
+ return mnNormalCacheSize;
+}
+
+
+
+
+bool BitmapCache::HasBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ return (iEntry != mpBitmapContainer->end()
+ && (iEntry->second.HasPreview() || iEntry->second.HasReplacement()));
+}
+
+
+
+
+bool BitmapCache::BitmapIsUpToDate (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ bool bIsUpToDate = false;
+ CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
+ if (aIterator != mpBitmapContainer->end())
+ bIsUpToDate = aIterator->second.IsUpToDate();
+
+ return bIsUpToDate;
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> BitmapCache::GetBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry == mpBitmapContainer->end())
+ {
+ // 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.
+ SetBitmap (rKey, ::boost::shared_ptr<BitmapEx>(new BitmapEx()), false);
+ iEntry = mpBitmapContainer->find(rKey);
+ iEntry->second.SetUpToDate(false);
+ SSCD_SET_UPTODATE(iEntry->first,false);
+ }
+ else
+ {
+ 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();
+}
+
+
+
+
+void BitmapCache::InvalidateBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ 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 (
+ const CacheKey& rKey,
+ const ::boost::shared_ptr<BitmapEx>& rpPreview,
+ bool bIsPrecious)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.SetPreview(rpPreview);
+ iEntry->second.SetUpToDate(true);
+ SSCD_SET_UPTODATE(iEntry->first,true);
+ iEntry->second.SetAccessTime(mnCurrentAccessTime++);
+ }
+ else
+ {
+ iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
+ rKey,
+ CacheEntry (rpPreview, mnCurrentAccessTime++, bIsPrecious))
+ ).first;
+ }
+
+ if (iEntry != mpBitmapContainer->end())
+ UpdateCacheSize(iEntry->second, ADD);
+}
+
+
+
+
+void BitmapCache::SetPrecious (const CacheKey& rKey, bool bIsPrecious)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ if (iEntry->second.IsPrecious() != bIsPrecious)
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.SetPrecious(bIsPrecious);
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+ }
+ else if (bIsPrecious)
+ {
+ iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
+ rKey,
+ CacheEntry (
+ ::boost::shared_ptr<BitmapEx>(),
+ mnCurrentAccessTime++, bIsPrecious))
+ ).first;
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+}
+
+
+
+
+void BitmapCache::ReCalculateTotalCacheSize (void)
+{
+ ::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();
+}
+
+
+
+
+bool BitmapCache::CacheEntry::HasPreview (void) const
+{
+ if (mpPreview.get() != NULL)
+ return mpPreview->GetSizePixel().Width()>0 && mpPreview->GetSizePixel().Height()>0;
+ else
+ return false;
+}
+
+
+
+
+inline bool BitmapCache::CacheEntry::HasLosslessReplacement (void) const
+{
+ return mpReplacement.get()!=NULL
+ && mpCompressor.get()!=NULL
+ && mpCompressor->IsLossless();
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx b/sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx
new file mode 100755
index 000000000000..2c33e042342f
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx
@@ -0,0 +1,211 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_BITMAP_CACHE_HXX
+#define SD_SLIDESORTER_BITMAP_CACHE_HXX
+
+class SdrPage;
+
+#include <vcl/bitmapex.hxx>
+#include <osl/mutex.hxx>
+#include <memory>
+#include <boost/shared_ptr.hpp>
+#include <hash_map>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapReplacement;
+class CacheCompactor;
+class BitmapCompressor;
+
+/** This low level cache is the actual bitmap container. It supports a
+ precious flag for every preview bitmap and keeps track of total sizes
+ for all previews with as well as those without the flag. The precious
+ flag is used by compaction algorithms to determine which previews may be
+ compressed or even discarded and which have to remain in their original
+ form. The precious flag is usually set for the visible previews.
+*/
+class BitmapCache
+{
+public:
+ /** The key for looking up preview bitmaps is a pointer to an SdrPage
+ object. The prior use of PageObjectViewObjectContact objects (which
+ ultimatly use them) turned out to be less suitable because their
+ life time is shorter then that of the page objects. Frequent
+ destruction and re-creation of the preview bitmaps was the result.
+ */
+ typedef const SdrPage* CacheKey;
+ class CacheEntry;
+ class CacheBitmapContainer;
+ typedef ::std::vector<CacheKey> CacheIndex;
+
+ /** Create a new cache for bitmap objects.
+ @param nMaximalNormalCacheSize
+ When a size larger then zero is given then that size is used.
+ Otherwise the default value from the configuration is used.
+ When that does not exist either then a internal default value is
+ used.
+ */
+ BitmapCache (const sal_Int32 nMaximalNormalCacheSize = 0);
+
+ /** The destructor clears the cache and relases all bitmaps still in it.
+ */
+ ~BitmapCache (void);
+
+ /** Remove all preview bitmaps from the cache. After this call the
+ cache is empty.
+ */
+ void Clear (void);
+
+ /** Return <TRUE/> when the cache is full, i.e. the cache compactor had
+ to be run.
+ */
+ bool IsFull (void) const;
+
+ /** Return the memory size that is occupied by all non-precious bitmaps
+ in the cache.
+ */
+ sal_Int32 GetSize (void);
+
+ /** Return <TRUE/> when a preview bitmap exists for the given key.
+ */
+ bool HasBitmap (const CacheKey& rKey);
+
+ /** Return <TRUE/> when a preview bitmap exists for the given key and
+ when it is up-to-date.
+ */
+ bool BitmapIsUpToDate (const CacheKey& rKey);
+
+ /** Return the preview bitmap for the given contact object.
+ */
+ ::boost::shared_ptr<BitmapEx> GetBitmap (const CacheKey& rKey);
+
+ /** Mark the specified preview bitmap as not being up-to-date anymore.
+ */
+ void InvalidateBitmap (const CacheKey& rKey);
+
+ /** Mark all preview bitmaps as not being up-to-date anymore.
+ */
+ void InvalidateCache (void);
+
+ /** Add or replace a bitmap for the given key.
+ */
+ void SetBitmap (
+ const CacheKey& rKey,
+ const ::boost::shared_ptr<BitmapEx>& rpPreview,
+ bool bIsPrecious);
+
+ /** Mark the specified preview bitmap as precious, i.e. that it must not
+ be compressed or otherwise removed from the cache.
+ */
+ void SetPrecious (const CacheKey& rKey, bool bIsPrecious);
+
+ /** Calculate the cache size. This should rarely be necessary because
+ the cache size is tracked with each modification of preview
+ bitmaps.
+ */
+ void ReCalculateTotalCacheSize (void);
+
+ /** Use the previews in the given cache to initialize missing previews.
+ */
+ void Recycle (const BitmapCache& rCache);
+
+ /** Return a list of sorted cache keys that represent an index into (a
+ part of) the cache. The entries of the index are sorted according
+ to last access times with the least recently access time first.
+ @param bIncludePrecious
+ When this flag is <TRUE/> entries with the precious flag set are
+ included in the index. When the flag is <FALSE/> these entries
+ are ommited.
+ @param bIncludeNoPreview
+ When this flag is <TRUE/> entries with that have no preview
+ bitmaps are included in the index. When the flag is <FALSE/> these entries
+ are ommited.
+ */
+ ::std::auto_ptr<CacheIndex> GetCacheIndex (
+ bool bIncludePrecious,
+ bool bIncludeNoPreview) const;
+
+ /** Compress the specified preview bitmap with the given bitmap
+ compressor. A reference to the compressor is stored for later
+ decompression.
+ */
+ void Compress (
+ const CacheKey& rKey,
+ const ::boost::shared_ptr<BitmapCompressor>& rpCompressor);
+
+private:
+ mutable ::osl::Mutex maMutex;
+
+ ::std::auto_ptr<CacheBitmapContainer> mpBitmapContainer;
+
+ /** Total size of bytes that are occupied by bitmaps in the cache for
+ whom the slides are currently not inside the visible area.
+ */
+ sal_Int32 mnNormalCacheSize;
+
+ /** Total size of bytes that are occupied by bitmaps in the cache for
+ whom the slides are currently visible.
+ */
+ sal_Int32 mnPreciousCacheSize;
+
+ /** At the moment the access time is not an actual time or date value
+ but a counter that is increased with every access. It thus defines
+ the same ordering as a true time.
+ */
+ sal_Int32 mnCurrentAccessTime;
+
+ /** The maximal cache size for the off-screen preview bitmaps. When
+ mnNormalCacheSize grows larger than this value then the
+ mpCacheCompactor member is used to reduce the cache size.
+ */
+ sal_Int32 mnMaximalNormalCacheSize;
+
+ /** The cache compactor is used to reduce the number of bytes used by
+ off-screen preview bitmaps.
+ */
+ ::std::auto_ptr<CacheCompactor> mpCacheCompactor;
+
+ /** This flag stores if the cache is or recently was full, i.e. the
+ cache compactor has or had to be run in order to reduce the cache
+ size to the allowed value.
+ */
+ bool mbIsFull;
+
+ /** Update mnNormalCacheSize or mnPreciousCacheSize according to the
+ precious flag of the specified preview bitmap and the specified
+ operation.
+ */
+ enum CacheOperation { ADD, REMOVE };
+ void UpdateCacheSize (const CacheEntry& rKey, CacheOperation eOperation);
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
new file mode 100644
index 000000000000..86fc72885414
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
@@ -0,0 +1,273 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsBitmapCompressor.hxx"
+
+#include <tools/stream.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/pngread.hxx>
+#include <vcl/pngwrite.hxx>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+//===== NoBitmapCompression ===================================================
+
+/** This dummy replacement simply stores a shared pointer to the original
+ preview bitmap.
+*/
+class NoBitmapCompression::DummyReplacement
+ : public BitmapReplacement
+{
+public:
+ ::boost::shared_ptr<BitmapEx> mpPreview;
+ Size maOriginalSize;
+
+ DummyReplacement (const ::boost::shared_ptr<BitmapEx>& rpPreview) : mpPreview(rpPreview)
+ {
+ }
+
+ virtual ~DummyReplacement();
+
+ virtual sal_Int32 GetMemorySize (void) const;
+};
+
+NoBitmapCompression::DummyReplacement::~DummyReplacement()
+{
+}
+
+sal_Int32 NoBitmapCompression::DummyReplacement::GetMemorySize (void) const
+{
+ return mpPreview->GetSizeBytes();
+}
+
+::boost::shared_ptr<BitmapReplacement> NoBitmapCompression::Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
+{
+ return ::boost::shared_ptr<BitmapReplacement>(new DummyReplacement(rpBitmap));
+}
+
+::boost::shared_ptr<BitmapEx> NoBitmapCompression::Decompress (
+ const BitmapReplacement& rBitmapData) const
+{
+ return dynamic_cast<const DummyReplacement&>(rBitmapData).mpPreview;
+}
+
+
+
+
+bool NoBitmapCompression::IsLossless (void) const
+{
+ return true;
+}
+
+
+
+
+//===== CompressionByDeletion =================================================
+
+::boost::shared_ptr<BitmapReplacement> CompressionByDeletion::Compress (
+ const ::boost::shared_ptr<BitmapEx>& ) const
+{
+ return ::boost::shared_ptr<BitmapReplacement>();
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> CompressionByDeletion::Decompress (
+ const BitmapReplacement& ) const
+{
+ // Return a NULL pointer. This will eventually lead to a request for
+ // the creation of a new one.
+ return ::boost::shared_ptr<BitmapEx>();
+}
+
+
+
+
+bool CompressionByDeletion::IsLossless (void) const
+{
+ return false;
+}
+
+
+
+
+//===== ResolutionReduction ===================================================
+
+/** Store a scaled down bitmap together with the original size.
+*/
+class ResolutionReduction::ResolutionReducedReplacement : public BitmapReplacement
+{
+public:
+ ::boost::shared_ptr<BitmapEx> mpPreview;
+ Size maOriginalSize;
+
+ virtual ~ResolutionReducedReplacement();
+
+ virtual sal_Int32 GetMemorySize (void) const;
+};
+
+ResolutionReduction::ResolutionReducedReplacement::~ResolutionReducedReplacement()
+{
+}
+
+sal_Int32 ResolutionReduction::ResolutionReducedReplacement::GetMemorySize (void) const
+{
+ if (mpPreview.get() != NULL)
+ return mpPreview->GetSizeBytes();
+ else
+ return 0;
+}
+
+::boost::shared_ptr<BitmapReplacement> ResolutionReduction::Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
+{
+ ResolutionReducedReplacement* pResult = new ResolutionReducedReplacement();
+ pResult->mpPreview.reset(new BitmapEx(*rpBitmap));
+ Size aSize (rpBitmap->GetSizePixel());
+ pResult->maOriginalSize = aSize;
+ if (aSize.Width()>0 && aSize.Width()<mnWidth)
+ {
+ int nHeight = aSize.Height() * mnWidth / aSize.Width() ;
+ pResult->mpPreview->Scale(Size(mnWidth,nHeight));
+ }
+
+ return ::boost::shared_ptr<BitmapReplacement>(pResult);
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> ResolutionReduction::Decompress (
+ const BitmapReplacement& rBitmapData) const
+{
+ ::boost::shared_ptr<BitmapEx> pResult;
+
+ const ResolutionReducedReplacement* pData (
+ dynamic_cast<const ResolutionReducedReplacement*>(&rBitmapData));
+
+ if (pData->mpPreview.get() != NULL)
+ {
+ pResult.reset(new BitmapEx(*pData->mpPreview));
+ if (pData->maOriginalSize.Width() > mnWidth)
+ pResult->Scale(pData->maOriginalSize);
+ }
+
+ return pResult;
+}
+
+
+
+
+bool ResolutionReduction::IsLossless (void) const
+{
+ return false;
+}
+
+
+
+
+//===== PNGCompression ========================================================
+
+
+class PngCompression::PngReplacement : public BitmapReplacement
+{
+public:
+ void* mpData;
+ sal_Int32 mnDataSize;
+ Size maImageSize;
+ PngReplacement (void)
+ : mpData(NULL),
+ mnDataSize(0),
+ maImageSize(0,0)
+ {}
+ virtual ~PngReplacement (void)
+ {
+ delete [] (char*)mpData;
+ }
+ virtual sal_Int32 GetMemorySize (void) const
+ {
+ return mnDataSize;
+ }
+};
+
+
+
+
+::boost::shared_ptr<BitmapReplacement> PngCompression::Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
+{
+ ::vcl::PNGWriter aWriter (*rpBitmap);
+ SvMemoryStream aStream (32768, 32768);
+ aWriter.Write(aStream);
+
+ PngReplacement* pResult = new PngReplacement();
+ pResult->maImageSize = rpBitmap->GetSizePixel();
+ pResult->mnDataSize = aStream.Tell();
+ pResult->mpData = new char[pResult->mnDataSize];
+ memcpy(pResult->mpData, aStream.GetData(), pResult->mnDataSize);
+
+ return ::boost::shared_ptr<BitmapReplacement>(pResult);
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> PngCompression::Decompress (
+ const BitmapReplacement& rBitmapData) const
+{
+ BitmapEx* pResult = NULL;
+ const PngReplacement* pData (dynamic_cast<const PngReplacement*>(&rBitmapData));
+ if (pData != NULL)
+ {
+ SvMemoryStream aStream (pData->mpData, pData->mnDataSize, STREAM_READ);
+ ::vcl::PNGReader aReader (aStream);
+ pResult = new BitmapEx(aReader.Read());
+ }
+
+// sal_Int32 nRatio ((100L * (ULONG)pResult->GetSizeBytes()) / (ULONG)pData->mnDataSize);
+
+ return ::boost::shared_ptr<BitmapEx>(pResult);
+}
+
+
+
+
+bool PngCompression::IsLossless (void) const
+{
+ return true;
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx
new file mode 100644
index 000000000000..cd564ddddcfd
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx
@@ -0,0 +1,160 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_BITMAP_COMPRESSOR_HXX
+#define SD_SLIDESORTER_BITMAP_COMPRESSOR_HXX
+
+#include <sal/types.h>
+#include <tools/gen.hxx>
+#include <boost/shared_ptr.hpp>
+
+class BitmapEx;
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapReplacement;
+
+
+/** This interface class provides the minimal method set for classes that
+ implement the compression and decompression of preview bitmaps.
+*/
+class BitmapCompressor
+{
+public:
+ /** Compress the given bitmap into a replacement format that is specific
+ to the compressor class.
+ */
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const = 0;
+
+ /** Decompress the given replacement data into a preview bitmap.
+ Depending on the compression technique the returned bitmap may
+ differ from the original bitmap given to the Compress() method. It
+ may even of the wrong size or empty or the NULL pointer. It is the
+ task of the caller to create a new preview bitmap if the returned
+ one is not as desired.
+ */
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData)const=0;
+
+ /** Return whether the compression and decompression is lossless. This
+ value is used by the caller of Decompress() to decide whether to use
+ the returned bitmap as is or if a new preview has to be created.
+ */
+ virtual bool IsLossless (void) const = 0;
+};
+
+
+
+/** Interface for preview bitmap replacements. Each bitmap
+ compressor/decompressor has to provide an implementation that is
+ suitable to store the compressed bitmaps.
+*/
+class BitmapReplacement
+{
+public:
+ virtual sal_Int32 GetMemorySize (void) const { return 0; }
+};
+
+
+
+
+/** This is one trivial bitmap compressor. It stores bitmaps unmodified
+ instead of compressing them.
+ This compressor is lossless.
+*/
+class NoBitmapCompression
+ : public BitmapCompressor
+{
+ class DummyReplacement;
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+
+
+/** This is another trivial bitmap compressor. Instead of compressing a
+ bitmap, it throws the bitmap away. Its Decompress() method returns a
+ NULL pointer. The caller has to create a new preview bitmap instead.
+ This compressor clearly is not lossless.
+*/
+class CompressionByDeletion
+ : public BitmapCompressor
+{
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+
+
+/** Compress a preview bitmap by reducing its resolution. While the aspect
+ ratio is maintained the horizontal resolution is scaled down to 100
+ pixels.
+ This compressor is not lossless.
+*/
+class ResolutionReduction
+ : public BitmapCompressor
+{
+ class ResolutionReducedReplacement;
+ static const sal_Int32 mnWidth = 100;
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ /** Scale the replacement bitmap up to the original size.
+ */
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+
+
+/** Compress preview bitmaps using the PNG format.
+ This compressor is lossless.
+*/
+class PngCompression
+ : public BitmapCompressor
+{
+ class PngReplacement;
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx
new file mode 100644
index 000000000000..5ad30ef43c1f
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx
@@ -0,0 +1,81 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsBitmapFactory.hxx"
+
+#include "PreviewRenderer.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+#include <svx/svdtypes.hxx>
+#include <svx/svdpage.hxx>
+#include <vcl/bitmapex.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+class PageObjectViewObjectContact;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+
+BitmapFactory::BitmapFactory (void)
+ : maRenderer(NULL,false)
+{
+}
+
+
+
+
+BitmapFactory::~BitmapFactory (void)
+{
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> BitmapFactory::CreateBitmap (
+ const SdPage& rPage,
+ const Size& rPixelSize)
+{
+ Image aPreview (maRenderer.RenderPage (
+ &rPage,
+ rPixelSize,
+ String()));
+
+ return ::boost::shared_ptr<BitmapEx>(new BitmapEx(aPreview.GetBitmapEx()));
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx
new file mode 100644
index 000000000000..87cd1f268f80
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx
@@ -0,0 +1,65 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PREVIEW_BITMAP_FACTORY_HXX
+#define SD_SLIDESORTER_PREVIEW_BITMAP_FACTORY_HXX
+
+#include "PreviewRenderer.hxx"
+#include <boost/shared_ptr.hpp>
+
+class BitmapEx;
+class SdPage;
+class Size;
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** This factory class creates preview bitmaps for page objects. It is
+ merely an adapter for the PreviewRenderer.
+*/
+class BitmapFactory
+{
+public:
+ BitmapFactory (void);
+ ~BitmapFactory (void);
+
+ ::boost::shared_ptr<BitmapEx> CreateBitmap (
+ const SdPage& rPage,
+ const Size& rPixelSize);
+
+private:
+ PreviewRenderer maRenderer;
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx
new file mode 100644
index 000000000000..520ce4ce2cf8
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsCacheCompactor.hxx"
+
+#include "SlsBitmapCompressor.hxx"
+#include "SlsBitmapCache.hxx"
+#include "SlsCacheCompactor.hxx"
+#include "SlsCacheConfiguration.hxx"
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <set>
+
+using namespace ::com::sun::star::uno;
+
+// Uncomment the definition of VERBOSE to get some more OSL_TRACE messages.
+#ifdef DEBUG
+//#define VERBOSE
+#endif
+
+namespace {
+
+/** This is a trivial implementation of the CacheCompactor interface class.
+ It ignores calls to RequestCompaction() and thus will never decrease the
+ total size of off-screen preview bitmaps.
+*/
+class NoCacheCompaction
+ : public ::sd::slidesorter::cache::CacheCompactor
+{
+public:
+ NoCacheCompaction (
+ ::sd::slidesorter::cache::BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize)
+ : CacheCompactor(rCache, nMaximalCacheSize)
+ {}
+
+ virtual void RequestCompaction (void) { /* Ignored */ };
+
+protected:
+ virtual void Run (void) { /* Do nothing */ };
+};
+
+
+
+
+/** This implementation of the CacheCompactor interface class uses one of
+ several bitmap compression algorithms to reduce the number of the bytes
+ of the off-screen previews in the bitmap cache. See the documentation
+ of CacheCompactor::Create() for more details on configuration properties
+ that control the choice of compression algorithm.
+*/
+class CacheCompactionByCompression
+ : public ::sd::slidesorter::cache::CacheCompactor
+{
+public:
+ CacheCompactionByCompression (
+ ::sd::slidesorter::cache::BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize,
+ const ::boost::shared_ptr< ::sd::slidesorter::cache::BitmapCompressor>& rpCompressor);
+
+protected:
+ virtual void Run (void);
+
+private:
+ ::boost::shared_ptr< ::sd::slidesorter::cache::BitmapCompressor> mpCompressor;
+};
+
+
+} // end of anonymous namespace
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+::std::auto_ptr<CacheCompactor> CacheCompactor::Create (
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize)
+{
+ static const ::rtl::OUString sNone (RTL_CONSTASCII_USTRINGPARAM("None"));
+ static const ::rtl::OUString sCompress (RTL_CONSTASCII_USTRINGPARAM("Compress"));
+ static const ::rtl::OUString sErase (RTL_CONSTASCII_USTRINGPARAM("Erase"));
+ static const ::rtl::OUString sResolution (RTL_CONSTASCII_USTRINGPARAM("ResolutionReduction"));
+ static const ::rtl::OUString sPNGCompression (RTL_CONSTASCII_USTRINGPARAM("PNGCompression"));
+
+ ::boost::shared_ptr<BitmapCompressor> pCompressor;
+ ::rtl::OUString sCompressionPolicy(sPNGCompression);
+ Any aCompressionPolicy (CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CompressionPolicy"))));
+ if (aCompressionPolicy.has<rtl::OUString>())
+ aCompressionPolicy >>= sCompressionPolicy;
+ if (sCompressionPolicy == sNone)
+ pCompressor.reset(new NoBitmapCompression());
+ else if (sCompressionPolicy == sErase)
+ pCompressor.reset(new CompressionByDeletion());
+ else if (sCompressionPolicy == sResolution)
+ pCompressor.reset(new ResolutionReduction());
+ else
+ pCompressor.reset(new PngCompression());
+
+ ::std::auto_ptr<CacheCompactor> pCompactor (NULL);
+ ::rtl::OUString sCompactionPolicy(sCompress);
+ Any aCompactionPolicy (CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CompactionPolicy"))));
+ if (aCompactionPolicy.has<rtl::OUString>())
+ aCompactionPolicy >>= sCompactionPolicy;
+ if (sCompactionPolicy == sNone)
+ pCompactor.reset(new NoCacheCompaction(rCache,nMaximalCacheSize));
+ else
+ pCompactor.reset(new CacheCompactionByCompression(rCache,nMaximalCacheSize,pCompressor));
+
+ return pCompactor;
+}
+
+
+
+
+void CacheCompactor::RequestCompaction (void)
+{
+ if ( ! mbIsCompactionRunning && ! maCompactionTimer.IsActive())
+ maCompactionTimer.Start();
+}
+
+
+
+
+CacheCompactor::CacheCompactor(
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize)
+ : mrCache(rCache),
+ mnMaximalCacheSize(nMaximalCacheSize),
+ mbIsCompactionRunning(false)
+{
+ maCompactionTimer.SetTimeout(100 /*ms*/);
+ maCompactionTimer.SetTimeoutHdl(LINK(this,CacheCompactor,CompactionCallback));
+
+}
+
+
+
+
+IMPL_LINK(CacheCompactor, CompactionCallback, Timer*, EMPTYARG)
+{
+ mbIsCompactionRunning = true;
+
+ try
+ {
+ Run();
+ }
+ catch(::com::sun::star::uno::RuntimeException e) { }
+ catch(::com::sun::star::uno::Exception e) { }
+
+ mbIsCompactionRunning = false;
+ return 1;
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
+
+namespace {
+
+//===== CacheCompactionByCompression ==========================================
+
+CacheCompactionByCompression::CacheCompactionByCompression (
+ ::sd::slidesorter::cache::BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize,
+ const ::boost::shared_ptr< ::sd::slidesorter::cache::BitmapCompressor>& rpCompressor)
+ : CacheCompactor(rCache,nMaximalCacheSize),
+ mpCompressor(rpCompressor)
+{
+}
+
+
+
+
+void CacheCompactionByCompression::Run (void)
+{
+ if (mrCache.GetSize() > mnMaximalCacheSize)
+ {
+#ifdef VERBOSE
+ OSL_TRACE ("bitmap cache uses to much space: %d > %d",
+ mrCache.GetSize(), mnMaximalCacheSize);
+#endif
+
+ ::std::auto_ptr< ::sd::slidesorter::cache::BitmapCache::CacheIndex> pIndex (
+ mrCache.GetCacheIndex(false,false));
+ ::sd::slidesorter::cache::BitmapCache::CacheIndex::iterator iIndex;
+ for (iIndex=pIndex->begin(); iIndex!=pIndex->end(); ++iIndex)
+ {
+ if (*iIndex == NULL)
+ continue;
+
+ mrCache.Compress(*iIndex, mpCompressor);
+ if (mrCache.GetSize() < mnMaximalCacheSize)
+ break;
+ }
+ mrCache.ReCalculateTotalCacheSize();
+#ifdef VERBOSE
+ OSL_TRACE (" there are now %d bytes occupied", mrCache.GetSize());
+#endif
+ }
+}
+
+
+} // end of anonymous namespace
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx
new file mode 100644
index 000000000000..84e450dcfbc9
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx
@@ -0,0 +1,100 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CACHE_COMPACTOR_HXX
+#define SD_SLIDESORTER_CACHE_COMPACTOR_HXX
+
+#include <sal/types.h>
+#include <vcl/timer.hxx>
+#include <memory>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapCache;
+class BitmapCompressor;
+
+/** This is an interface class whose implementations are created via the
+ Create() factory method.
+*/
+class CacheCompactor
+{
+public:
+ virtual ~CacheCompactor (void) {};
+
+ /** Create a new instance of the CacheCompactor interface class. The
+ type of compaction algorithm used depends on values from the
+ configuration: the SlideSorter/PreviewCache/CompactionPolicy
+ property of the Impress.xcs file currently supports the values
+ "None" and "Compress". With the later the CompressionPolicy
+ property is evaluated which implementation of the BitmapCompress
+ interface class to use as bitmap compressor.
+ @param rCache
+ The bitmap cache on which to operate.
+ @param nMaximalCacheSize
+ The total number of bytes the off-screen bitmaps in the cache
+ may have. When the Run() method is (indirectly) called the
+ compactor tries to reduce that summed size of off-screen bitmaps
+ under this number. However, it is not guaranteed that this
+ works in all cases.
+ */
+ static ::std::auto_ptr<CacheCompactor> Create (
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize);
+
+ /** Request a compaction of the off-screen previews in the bitmap
+ cache. This calls via a timer the Run() method.
+ */
+ virtual void RequestCompaction (void);
+
+protected:
+ BitmapCache& mrCache;
+ sal_Int32 mnMaximalCacheSize;
+
+ CacheCompactor(
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize);
+
+ /** This method actually tries to reduce the total number of bytes used
+ by the off-screen preview bitmaps.
+ */
+ virtual void Run (void) = 0;
+
+private:
+ /** This timer is used to collect calles to RequestCompaction() and
+ eventually call Run().
+ */
+ Timer maCompactionTimer;
+ bool mbIsCompactionRunning;
+ DECL_LINK(CompactionCallback, Timer*);
+};
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx
new file mode 100644
index 000000000000..942a3e762acb
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx
@@ -0,0 +1,181 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsCacheConfiguration.hxx"
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#ifndef _COM_SUN_STAR_CONTAINER_PROPERTYVALUE_HPP_
+#include <com/sun/star/beans/PropertyValue.hpp>
+#endif
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace sd { namespace slidesorter { namespace cache {
+
+::boost::shared_ptr<CacheConfiguration> CacheConfiguration::mpInstance;
+::boost::weak_ptr<CacheConfiguration> CacheConfiguration::mpWeakInstance;
+Timer CacheConfiguration::maReleaseTimer;
+
+
+
+::boost::shared_ptr<CacheConfiguration> CacheConfiguration::Instance (void)
+{
+ ::vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ if (mpInstance.get() == NULL)
+ {
+ // Maybe somebody else kept a previously created instance alive.
+ if ( ! mpWeakInstance.expired())
+ mpInstance = ::boost::shared_ptr<CacheConfiguration>(mpWeakInstance);
+ if (mpInstance.get() == NULL)
+ {
+ // We have to create a new instance.
+ mpInstance.reset(new CacheConfiguration());
+ mpWeakInstance = mpInstance;
+ // Prepare to release this instance in the near future.
+ maReleaseTimer.SetTimeoutHdl(
+ LINK(mpInstance.get(),CacheConfiguration,TimerCallback));
+ maReleaseTimer.SetTimeout(5000 /* 5s */);
+ maReleaseTimer.Start();
+ }
+ }
+ return mpInstance;
+}
+
+
+
+
+CacheConfiguration::CacheConfiguration (void)
+{
+ // Get the cache size from configuration.
+ const ::rtl::OUString sConfigurationProviderServiceName(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider"));
+ const ::rtl::OUString sPathToImpressConfigurationRoot(
+ RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/"));
+ const ::rtl::OUString sPathToNode(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "MultiPaneGUI/SlideSorter/PreviewCache"));
+
+ try
+ {
+ do
+ {
+ // Obtain access to the configuration.
+ Reference<lang::XMultiServiceFactory> xProvider (
+ ::comphelper::getProcessServiceFactory()->createInstance(
+ sConfigurationProviderServiceName),
+ UNO_QUERY);
+ if ( ! xProvider.is())
+ break;
+
+ // Obtain access to Impress configuration.
+ Sequence<Any> aCreationArguments(3);
+ aCreationArguments[0] = makeAny(beans::PropertyValue(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("nodepath")),
+ 0,
+ makeAny(sPathToImpressConfigurationRoot),
+ beans::PropertyState_DIRECT_VALUE));
+ aCreationArguments[1] = makeAny(beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("depth")),
+ 0,
+ makeAny((sal_Int32)-1),
+ beans::PropertyState_DIRECT_VALUE));
+ aCreationArguments[2] = makeAny(beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("lazywrite")),
+ 0,
+ makeAny(true),
+ beans::PropertyState_DIRECT_VALUE));
+ ::rtl::OUString sAccessService (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationAccess")));
+ Reference<XInterface> xRoot (xProvider->createInstanceWithArguments(
+ sAccessService, aCreationArguments));
+ if ( ! xRoot.is())
+ break;
+ Reference<container::XHierarchicalNameAccess> xHierarchy (xRoot, UNO_QUERY);
+ if ( ! xHierarchy.is())
+ break;
+
+ // Get the node for the slide sorter preview cache.
+ mxCacheNode = Reference<container::XNameAccess>(
+ xHierarchy->getByHierarchicalName(sPathToNode),
+ UNO_QUERY);
+ }
+ while (false);
+ }
+ catch (RuntimeException aException)
+ {
+ (void)aException;
+ }
+ catch (Exception aException)
+ {
+ (void)aException;
+ }
+}
+
+
+
+
+Any CacheConfiguration::GetValue (const ::rtl::OUString& rName)
+{
+ Any aResult;
+
+ if (mxCacheNode != NULL)
+ {
+ try
+ {
+ aResult = mxCacheNode->getByName(rName);
+ }
+ catch (Exception aException)
+ {
+ (void)aException;
+ }
+ }
+
+ return aResult;
+}
+
+
+
+
+IMPL_LINK(CacheConfiguration,TimerCallback, Timer*,EMPTYARG)
+{
+ // Release out reference to the instance.
+ mpInstance.reset();
+ return 0;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx
new file mode 100644
index 000000000000..034480298006
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CACHE_CONFIGURATION_HXX
+#define SD_SLIDESORTER_CACHE_CONFIGURATION_HXX
+
+#include <com/sun/star/uno/Any.hxx>
+#include <vcl/timer.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** A very simple and easy-to-use access to configuration entries regarding
+ the slide sorter cache.
+*/
+class CacheConfiguration
+{
+public:
+ /** Return an instance to this class. The reference is released after 5
+ seconds. Subsequent calls to this function will create a new
+ instance.
+ */
+ static ::boost::shared_ptr<CacheConfiguration> Instance (void);
+
+ /** Look up the specified value in
+ MultiPaneGUI/SlideSorter/PreviewCache. When the specified value
+ does not exist then an empty Any is returned.
+ */
+ ::com::sun::star::uno::Any GetValue (const ::rtl::OUString& rName);
+
+private:
+ static ::boost::shared_ptr<CacheConfiguration> mpInstance;
+ /** When a caller holds a reference after we have released ours we use
+ this weak pointer to avoid creating a new instance.
+ */
+ static ::boost::weak_ptr<CacheConfiguration> mpWeakInstance;
+ static Timer maReleaseTimer;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::container::XNameAccess> mxCacheNode;
+
+ CacheConfiguration (void);
+
+ DECL_LINK(TimerCallback, Timer*);
+};
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx
new file mode 100755
index 000000000000..780a429df29e
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx
@@ -0,0 +1,310 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsGenericPageCache.hxx"
+
+#include "SlsQueueProcessor.hxx"
+#include "SlsRequestPriorityClass.hxx"
+#include "SlsRequestFactory.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "controller/SlideSorterController.hxx"
+
+namespace sd { namespace slidesorter { namespace cache {
+
+GenericPageCache::GenericPageCache (
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext)
+ : mpBitmapCache(),
+ maRequestQueue(rpCacheContext),
+ mpQueueProcessor(),
+ mpCacheContext(rpCacheContext),
+ maPreviewSize(rPreviewSize)
+{
+}
+
+
+
+
+GenericPageCache::~GenericPageCache (void)
+{
+ OSL_TRACE("terminating queue processor %p", mpQueueProcessor.get());
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Stop();
+ maRequestQueue.Clear();
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Terminate();
+ mpQueueProcessor.reset();
+ OSL_TRACE("queue processor stopped and terminated");
+
+ if (mpBitmapCache.get() != NULL)
+ PageCacheManager::Instance()->ReleaseCache(mpBitmapCache);
+ mpBitmapCache.reset();
+}
+
+
+
+
+void GenericPageCache::ProvideCacheAndProcessor (void)
+{
+ if (mpBitmapCache.get() == NULL)
+ mpBitmapCache = PageCacheManager::Instance()->GetCache(
+ mpCacheContext->GetModel(),
+ maPreviewSize);
+
+ if (mpQueueProcessor.get() == NULL)
+ mpQueueProcessor.reset(new QueueProcessor(
+ maRequestQueue,
+ mpBitmapCache,
+ maPreviewSize,
+ mpCacheContext));
+}
+
+
+
+
+void GenericPageCache::ChangePreviewSize (const Size& rPreviewSize)
+{
+ if (rPreviewSize != maPreviewSize)
+ {
+ if (mpBitmapCache.get() != NULL)
+ {
+ mpBitmapCache = PageCacheManager::Instance()->ChangeSize(
+ mpBitmapCache, maPreviewSize, rPreviewSize);
+ if (mpQueueProcessor.get() != NULL)
+ {
+ mpQueueProcessor->SetPreviewSize(rPreviewSize);
+ mpQueueProcessor->SetBitmapCache(mpBitmapCache);
+ }
+ }
+ maPreviewSize = rPreviewSize;
+ }
+}
+
+
+
+
+BitmapEx GenericPageCache::GetPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize)
+{
+ OSL_ASSERT(aKey != NULL);
+
+ BitmapEx aPreview;
+ bool bMayBeUpToDate = true;
+ ProvideCacheAndProcessor();
+ const SdrPage* pPage = mpCacheContext->GetPage(aKey);
+ if (mpBitmapCache->HasBitmap(pPage))
+ {
+ ::boost::shared_ptr<BitmapEx> pPreview(mpBitmapCache->GetBitmap(pPage));
+ OSL_ASSERT(pPreview.get() != NULL);
+ aPreview = *pPreview;
+ Size aBitmapSize (aPreview.GetSizePixel());
+ if (aBitmapSize != rSize)
+ {
+ // The bitmap has the wrong size.
+ DBG_ASSERT (rSize.Width() < 1000,
+ "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. "
+ "This may indicate an error.");
+
+ // Scale the bitmap to the desired size when that is possible,
+ // i.e. the bitmap is not empty.
+ if (aBitmapSize.Width()>0 && aBitmapSize.Height()>0)
+ aPreview.Scale (rSize, BMP_SCALE_FAST);
+ }
+ bMayBeUpToDate = true;
+ }
+ else
+ bMayBeUpToDate = false;
+
+ // Request the creation of a correctly sized preview bitmap. We do this
+ // even when the size of the bitmap in the cache is correct because its
+ // content may be not up-to-date anymore.
+ RequestPreviewBitmap(aKey, rSize, bMayBeUpToDate);
+
+ return aPreview;
+}
+
+
+
+
+void GenericPageCache::RequestPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize,
+ bool bMayBeUpToDate)
+{
+ OSL_ASSERT(aKey != NULL);
+
+ const SdrPage* pPage = mpCacheContext->GetPage(aKey);
+
+ ProvideCacheAndProcessor();
+
+ // Determine if the available bitmap is up to date.
+ bool bIsUpToDate = false;
+ if (bMayBeUpToDate)
+ bIsUpToDate = mpBitmapCache->BitmapIsUpToDate (pPage);
+ if (bIsUpToDate)
+ {
+ ::boost::shared_ptr<BitmapEx> pPreview (mpBitmapCache->GetBitmap(pPage));
+ if (pPreview.get()==NULL || pPreview->GetSizePixel()!=rSize)
+ bIsUpToDate = false;
+ }
+
+ if ( ! bIsUpToDate)
+ {
+ // No, the bitmap is not up-to-date. Request a new one.
+ RequestPriorityClass ePriorityClass (NOT_VISIBLE);
+ if (mpCacheContext->IsVisible(aKey))
+ {
+ if (mpBitmapCache->HasBitmap(pPage))
+ ePriorityClass = VISIBLE_OUTDATED_PREVIEW;
+ else
+ ePriorityClass = VISIBLE_NO_PREVIEW;
+ }
+ maRequestQueue.AddRequest(aKey, ePriorityClass);
+ mpQueueProcessor->Start(ePriorityClass);
+ }
+}
+
+
+
+
+void GenericPageCache::ReleasePreviewBitmap (CacheKey aKey)
+{
+ if (mpBitmapCache.get() != NULL)
+ {
+ // Suspend the queue processing temporarily to avoid the reinsertion
+ // of the request that is to be deleted.
+ mpQueueProcessor->Stop();
+
+ maRequestQueue.RemoveRequest(aKey);
+ mpQueueProcessor->RemoveRequest(aKey);
+
+ // Resume the queue processing.
+ if ( ! maRequestQueue.IsEmpty())
+ {
+ try
+ {
+ mpQueueProcessor->Start(maRequestQueue.GetFrontPriorityClass());
+ }
+ catch (::com::sun::star::uno::RuntimeException)
+ {
+ }
+ }
+ }
+
+ // We do not relase the preview bitmap that is associated with the page
+ // of the given request data because this method is called when the
+ // request data, typically a view-object-contact object, is destroyed.
+ // The page object usually lives longer than that and thus the preview
+ // bitmap may be used later on.
+}
+
+
+
+
+void GenericPageCache::InvalidateCache (bool bUpdateCache)
+{
+ if (mpBitmapCache.get() != NULL)
+ {
+ // When the cache is being invalidated then it makes no sense to
+ // continue creating preview bitmaps. However, this may be
+ // re-started below.
+ mpQueueProcessor->Stop();
+ maRequestQueue.Clear();
+
+ // Mark the previews in the cache as not being up-to-date anymore.
+ // Depending on the given bUpdateCache flag we start to create new
+ // preview bitmaps.
+ mpBitmapCache->InvalidateCache();
+ if (bUpdateCache)
+ RequestFactory()(maRequestQueue, mpCacheContext);
+ }
+}
+
+
+
+
+void GenericPageCache::SetPreciousFlag (CacheKey aKey, bool bIsPrecious)
+{
+ ProvideCacheAndProcessor();
+
+ // Change the request priority class according to the new precious flag.
+ if (bIsPrecious)
+ {
+ if (mpBitmapCache->HasBitmap(mpCacheContext->GetPage(aKey)))
+ maRequestQueue.ChangeClass(aKey,VISIBLE_OUTDATED_PREVIEW);
+ else
+ maRequestQueue.ChangeClass(aKey,VISIBLE_NO_PREVIEW);
+ }
+ else
+ {
+ if (mpBitmapCache->IsFull())
+ {
+ // When the bitmap cache is full then requests for slides that
+ // are not visible are removed.
+ maRequestQueue.RemoveRequest(aKey);
+ }
+ else
+ maRequestQueue.ChangeClass(aKey,NOT_VISIBLE);
+ }
+
+ mpBitmapCache->SetPrecious(mpCacheContext->GetPage(aKey), bIsPrecious);
+}
+
+
+
+
+void GenericPageCache::Pause (void)
+{
+ ProvideCacheAndProcessor();
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Pause();
+}
+
+
+
+
+void GenericPageCache::Resume (void)
+{
+ ProvideCacheAndProcessor();
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Resume();
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
diff --git a/sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx
new file mode 100755
index 000000000000..89fc657004e8
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx
@@ -0,0 +1,146 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_GENERIC_PAGE_CACHE_HXX
+#define SD_SLIDESORTER_GENERIC_PAGE_CACHE_HXX
+
+#include "SlideSorter.hxx"
+#include "SlsRequestQueue.hxx"
+#include "SlsQueueProcessor.hxx"
+#include <boost/function.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapCache;
+class QueueProcessor;
+
+/** This basically is the implementation class for the PageCache class.
+*/
+class GenericPageCache
+{
+public:
+ /** The page chache is created with references both to the SlideSorter.
+ This allows access to both view and model and the cache can so fill
+ itself with requests for all or just the visible pages.
+ */
+ GenericPageCache (
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext);
+
+ ~GenericPageCache (void);
+
+ /** Change the size of the preview bitmaps. This may be caused by a
+ resize of the slide sorter window or a change of the number of
+ columns.
+ */
+ void ChangePreviewSize (const Size& rPreviewSize);
+
+ /** Request a preview bitmap for the specified page object in the
+ specified size. The returned bitmap may be preview of the preview,
+ i.e. either a scaled (up or down) version of a previous preview (of
+ the wrong size) or an empty bitmap. In this case a request for the
+ generation of a new preview is created and inserted into the request
+ queue. When the preview is available the page shape will be told to
+ paint itself again. When it then calls this method again if
+ receives the correctly sized preview bitmap.
+ @param rRequestData
+ This data is used to determine the preview.
+ @param rSize
+ The size of the requested preview bitmap.
+ @return
+ Returns a bitmap that is either empty, contains a scaled (up or
+ down) version or is the requested bitmap.
+ */
+ BitmapEx GetPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize);
+
+ /** When the requested preview bitmap does not yet exist or is not
+ up-to-date then the rendering of one is scheduled. Otherwise this
+ method does nothing.
+ @param rRequestData
+ This data is used to determine the preview.
+ @param rSize
+ The size of the requested preview bitmap in pixel coordinates.
+ @param bMayBeUpToDate
+ This flag helps the method to determine whether an existing
+ preview that matches the request is up to date. If the caller
+ know that it is not then by passing <FALSE/> he tells us that we
+ do not have to check the up-to-date flag a second time. If
+ unsure pass <TRUE/>.
+ */
+ void RequestPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize,
+ bool bMayBeUpToDate = true);
+
+ /** Call this method when a view-object-contact object is being deleted
+ and does not need (a) its current bitmap in the cache and (b) a
+ requested a new bitmap.
+ */
+ void ReleasePreviewBitmap (CacheKey aKey);
+
+ /** Call this method when all preview bitmaps have to be generated anew.
+ This is the case when the size of the page objects on the screen has
+ changed or when the model has changed.
+ */
+ void InvalidateCache (bool bUpdateCache);
+
+ /** With the precious flag you can control whether a bitmap can be
+ removed from the cache or reduced in size to make room for other
+ bitmaps or is so precious that it will not be touched. A typical
+ use is to set the precious flag for the visible pages.
+ */
+ void SetPreciousFlag (CacheKey aKey, bool bIsPrecious);
+
+ void Pause (void);
+ void Resume (void);
+
+private:
+ ::boost::shared_ptr<BitmapCache> mpBitmapCache;
+
+ RequestQueue maRequestQueue;
+
+ ::boost::scoped_ptr<QueueProcessor> mpQueueProcessor;
+
+ SharedCacheContext mpCacheContext;
+
+ /** The current size of preview bitmaps.
+ */
+ Size maPreviewSize;
+
+ /** Both bitmap cache and queue processor are created on demand by this
+ method.
+ */
+ void ProvideCacheAndProcessor (void);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsPageCache.cxx b/sd/source/ui/slidesorter/cache/SlsPageCache.cxx
new file mode 100755
index 000000000000..714e1f008329
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsPageCache.cxx
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlsGenericPageCache.hxx"
+#include "SlsRequestFactory.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "model/SlideSorterModel.hxx"
+#include <boost/bind.hpp>
+#include <boost/bind/protect.hpp>
+
+using namespace ::com::sun::star;
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+//===== PageCache =============================================================
+
+PageCache::PageCache (
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext)
+ : mpImplementation(
+ new GenericPageCache(
+ rPreviewSize,
+ rpCacheContext))
+{
+}
+
+
+
+
+PageCache::~PageCache (void)
+{
+}
+
+
+
+
+void PageCache::ChangeSize(const Size& rPreviewSize)
+{
+ mpImplementation->ChangePreviewSize(rPreviewSize);
+}
+
+
+
+
+BitmapEx PageCache::GetPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize)
+{
+ return mpImplementation->GetPreviewBitmap(aKey, rSize);
+}
+
+
+
+
+void PageCache::ReleasePreviewBitmap (
+ CacheKey aKey)
+{
+ mpImplementation->ReleasePreviewBitmap(aKey);
+}
+
+
+
+
+void PageCache::InvalidateCache (bool bUpdateCache)
+{
+ mpImplementation->InvalidateCache(bUpdateCache);
+}
+
+
+
+
+void PageCache::SetPreciousFlag (
+ CacheKey aKey,
+ bool bIsPrecious)
+{
+ mpImplementation->SetPreciousFlag(aKey, bIsPrecious);
+}
+
+
+
+
+void PageCache::Pause (void)
+{
+ mpImplementation->Pause();
+}
+
+
+
+
+void PageCache::Resume (void)
+{
+ mpImplementation->Resume();
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
diff --git a/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx b/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx
new file mode 100644
index 000000000000..3c8a15892e7c
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx
@@ -0,0 +1,446 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "cache/SlsPageCacheManager.hxx"
+
+#include "SlsBitmapCache.hxx"
+#include "view/SlideSorterView.hxx"
+#include "model/SlideSorterModel.hxx"
+
+#include <deque>
+#include <map>
+#include <boost/weak_ptr.hpp>
+
+namespace {
+
+/** Collection of data that is stored for all active preview caches.
+*/
+class CacheDescriptor
+{
+public:
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey mpDocument;
+ Size maPreviewSize;
+
+ CacheDescriptor(
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey pDocument,
+ const Size& rPreviewSize)
+ :mpDocument(pDocument),maPreviewSize(rPreviewSize)
+ {}
+ /// Test for equality with respect to all members.
+ class Equal {public: bool operator() (
+ const CacheDescriptor& rDescriptor1, const CacheDescriptor& rDescriptor2) const {
+ return rDescriptor1.mpDocument==rDescriptor2.mpDocument
+ && rDescriptor1.maPreviewSize==rDescriptor2.maPreviewSize;
+ } };
+ /// Hash function that takes all members into account.
+ class Hash {public: size_t operator() (const CacheDescriptor& rDescriptor) const {
+ return (size_t)rDescriptor.mpDocument.get() + rDescriptor.maPreviewSize.Width();
+ } };
+};
+
+
+
+
+/** Collection of data that is stored for the inactive, recently used
+ caches.
+*/
+class RecentlyUsedCacheDescriptor
+{
+public:
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey mpDocument;
+ Size maPreviewSize;
+ ::boost::shared_ptr< ::sd::slidesorter::cache::PageCacheManager::Cache> mpCache;
+
+ RecentlyUsedCacheDescriptor(
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey pDocument,
+ const Size& rPreviewSize,
+ const ::boost::shared_ptr< ::sd::slidesorter::cache::PageCacheManager::Cache>& rpCache)
+ :mpDocument(pDocument),maPreviewSize(rPreviewSize),mpCache(rpCache)
+ {}
+};
+
+
+
+
+/** The list of recently used caches is organized as queue. When elements
+ are added the list is shortened to the maximally allowed number of
+ elements by removing the least recently used elements.
+*/
+typedef ::std::deque<RecentlyUsedCacheDescriptor> RecentlyUsedQueue;
+
+
+
+
+/** Compare the caches by preview size. Those that match the given size
+ come first, then, regardless of the given size, the largest ones before
+ the smaller ones.
+*/
+class BestFittingCacheComparer
+{
+public:
+ BestFittingCacheComparer (const Size& rPreferredSize)
+ : maPreferredSize(rPreferredSize)
+ {}
+ bool operator()(const ::sd::slidesorter::cache::PageCacheManager::BestFittingPageCaches::value_type& rElement1,
+ const ::sd::slidesorter::cache::PageCacheManager::BestFittingPageCaches::value_type& rElement2)
+ {
+ if (rElement1.first == maPreferredSize)
+ return true;
+ else if (rElement2.first == maPreferredSize)
+ return false;
+ else
+ return (rElement1.first.Width()*rElement1.first.Height()
+ > rElement2.first.Width()*rElement2.first.Height());
+ }
+
+private:
+ Size maPreferredSize;
+};
+
+} // end of anonymous namespace
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** Container for the active caches.
+*/
+class PageCacheManager::PageCacheContainer
+ : public ::std::hash_map<CacheDescriptor,
+ ::boost::shared_ptr<PageCacheManager::Cache>,
+ CacheDescriptor::Hash,
+ CacheDescriptor::Equal>
+{
+public:
+ PageCacheContainer (void) {}
+
+ /** Compare entries in the cache container with respect to the cache
+ address only.
+ */
+ class CompareWithCache { public:
+ CompareWithCache(const ::boost::shared_ptr<PageCacheManager::Cache>& rpCache)
+ : mpCache(rpCache) {}
+ bool operator () (const PageCacheContainer::value_type& rValue)
+ { return rValue.second == mpCache; }
+ private:
+ ::boost::shared_ptr<PageCacheManager::Cache> mpCache;
+ };
+};
+
+
+/** The recently used caches are stored in one queue for each document.
+*/
+class PageCacheManager::RecentlyUsedPageCaches
+ : public ::std::map<DocumentKey,RecentlyUsedQueue>
+{
+public:
+ RecentlyUsedPageCaches (void) {};
+};
+
+
+
+
+class PageCacheManager::Deleter
+{
+public:
+ void operator() (PageCacheManager* pObject) { delete pObject; }
+};
+
+
+
+//===== PageCacheManager ====================================================
+
+::boost::weak_ptr<PageCacheManager> PageCacheManager::mpInstance;
+
+::boost::shared_ptr<PageCacheManager> PageCacheManager::Instance (void)
+{
+ ::boost::shared_ptr<PageCacheManager> pInstance;
+
+ ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
+
+ pInstance = mpInstance.lock();
+ if (pInstance.get() == NULL)
+ {
+ pInstance = ::boost::shared_ptr<PageCacheManager>(
+ new PageCacheManager(),
+ PageCacheManager::Deleter());
+ mpInstance = pInstance;
+ }
+
+ return pInstance;
+}
+
+
+
+
+PageCacheManager::PageCacheManager (void)
+ : mpPageCaches(new PageCacheContainer()),
+ mpRecentlyUsedPageCaches(new RecentlyUsedPageCaches()),
+ mnMaximalRecentlyCacheCount(2)
+{
+}
+
+
+
+
+PageCacheManager::~PageCacheManager (void)
+{
+}
+
+
+
+
+::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::GetCache (
+ DocumentKey pDocument,
+ const Size& rPreviewSize)
+{
+ ::boost::shared_ptr<Cache> pResult;
+
+ // Look for the cache in the list of active caches.
+ CacheDescriptor aKey (pDocument, rPreviewSize);
+ PageCacheContainer::iterator iCache (mpPageCaches->find(aKey));
+ if (iCache != mpPageCaches->end())
+ pResult = iCache->second;
+
+ // Look for the cache in the list of recently used caches.
+ if (pResult.get() == NULL)
+ pResult = GetRecentlyUsedCache(pDocument, rPreviewSize);
+
+ // Create the cache when no suitable one does exist.
+ if (pResult.get() == NULL)
+ pResult.reset(new Cache());
+
+ // The cache may be newly created and thus empty or is old and may
+ // contain previews that are not up-to-date. Recycle previews from
+ // other caches to fill in the holes.
+ Recycle(pResult, pDocument,rPreviewSize);
+
+ // Put the new (or old) cache into the container.
+ if (pResult.get() != NULL)
+ mpPageCaches->insert(PageCacheContainer::value_type(aKey, pResult));
+
+ return pResult;
+}
+
+
+
+
+void PageCacheManager::Recycle (
+ const ::boost::shared_ptr<Cache>& rpCache,
+ DocumentKey pDocument,
+ const Size& rPreviewSize)
+{
+ BestFittingPageCaches aCaches;
+
+ // Add bitmap caches from active caches.
+ PageCacheContainer::iterator iActiveCache;
+ for (iActiveCache=mpPageCaches->begin(); iActiveCache!=mpPageCaches->end(); ++iActiveCache)
+ {
+ if (iActiveCache->first.mpDocument == pDocument)
+ aCaches.push_back(BestFittingPageCaches::value_type(
+ iActiveCache->first.maPreviewSize, iActiveCache->second));
+ }
+
+ // Add bitmap caches from recently used caches.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ RecentlyUsedQueue::const_iterator iRecentCache;
+ for (iRecentCache=iQueue->second.begin();iRecentCache!=iQueue->second.end();++iRecentCache)
+ aCaches.push_back(BestFittingPageCaches::value_type(
+ iRecentCache->maPreviewSize, iRecentCache->mpCache));
+ }
+
+ ::std::sort(aCaches.begin(), aCaches.end(), BestFittingCacheComparer(rPreviewSize));
+
+ BestFittingPageCaches::const_iterator iBestCache;
+ for (iBestCache=aCaches.begin(); iBestCache!=aCaches.end(); ++iBestCache)
+ {
+ rpCache->Recycle(*iBestCache->second);
+ }
+}
+
+
+
+
+void PageCacheManager::ReleaseCache (const ::boost::shared_ptr<Cache>& rpCache)
+{
+ PageCacheContainer::iterator iCache (::std::find_if(
+ mpPageCaches->begin(),
+ mpPageCaches->end(),
+ PageCacheContainer::CompareWithCache(rpCache)));
+
+ if (iCache != mpPageCaches->end())
+ {
+ OSL_ASSERT(iCache->second == rpCache);
+
+ PutRecentlyUsedCache(iCache->first.mpDocument,iCache->first.maPreviewSize,rpCache);
+
+ mpPageCaches->erase(iCache);
+ }
+}
+
+
+
+
+::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::ChangeSize (
+ const ::boost::shared_ptr<Cache>& rpCache,
+ const Size& rOldPreviewSize,
+ const Size& rNewPreviewSize)
+{
+ (void)rOldPreviewSize;
+
+ ::boost::shared_ptr<Cache> pResult;
+
+ if (rpCache.get() != NULL)
+ {
+ // Look up the given cache in the list of active caches.
+ PageCacheContainer::iterator iCacheToChange (::std::find_if(
+ mpPageCaches->begin(),
+ mpPageCaches->end(),
+ PageCacheContainer::CompareWithCache(rpCache)));
+ OSL_ASSERT(iCacheToChange != mpPageCaches->end());
+ if (iCacheToChange != mpPageCaches->end())
+ {
+ OSL_ASSERT(iCacheToChange->second == rpCache);
+
+ // Now, we can change the preview size of the existing one by
+ // removing the cache from the list and re-insert it with the
+ // updated size.
+ const ::sd::slidesorter::cache::PageCacheManager::DocumentKey aKey (
+ iCacheToChange->first.mpDocument);
+ mpPageCaches->erase(iCacheToChange);
+ mpPageCaches->insert(PageCacheContainer::value_type(
+ CacheDescriptor(aKey,rNewPreviewSize),
+ rpCache));
+
+ pResult = rpCache;
+ }
+ }
+
+ return pResult;
+}
+
+
+
+
+void PageCacheManager::InvalidatePreviewBitmap (
+ DocumentKey pDocument,
+ const SdrPage* pKey)
+{
+ if (pDocument!=NULL)
+ {
+ // Iterate over all caches that are currently in use and invalidate
+ // the previews in those that belong to the document.
+ PageCacheContainer::iterator iCache;
+ for (iCache=mpPageCaches->begin(); iCache!=mpPageCaches->end(); ++iCache)
+ if (iCache->first.mpDocument == pDocument)
+ iCache->second->InvalidateBitmap(pKey);
+
+ // Invalidate the previews in the recently used caches belonging to
+ // the given document.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ RecentlyUsedQueue::const_iterator iCache2;
+ for (iCache2=iQueue->second.begin(); iCache2!=iQueue->second.end(); ++iCache2)
+ iCache2->mpCache->InvalidateBitmap(pKey);
+ }
+ }
+}
+
+
+
+
+void PageCacheManager::InvalidateAllCaches (void)
+{
+ // Iterate over all caches that are currently in use and invalidate
+ // them.
+ PageCacheContainer::iterator iCache;
+ for (iCache=mpPageCaches->begin(); iCache!=mpPageCaches->end(); ++iCache)
+ iCache->second->InvalidateCache();
+
+ // Remove all recently used caches, there is not much sense in storing
+ // invalidated and unused caches.
+ mpRecentlyUsedPageCaches->clear();
+}
+
+
+
+
+::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::GetRecentlyUsedCache (
+ DocumentKey pDocument,
+ const Size& rPreviewSize)
+{
+ ::boost::shared_ptr<Cache> pCache;
+
+ // Look for the cache in the list of recently used caches.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ RecentlyUsedQueue::iterator iCache;
+ for (iCache=iQueue->second.begin(); iCache!= iQueue->second.end(); ++iCache)
+ if (iCache->maPreviewSize == rPreviewSize)
+ {
+ pCache = iCache->mpCache;
+ iQueue->second.erase(iCache);
+ break;
+ }
+ }
+
+ return pCache;
+}
+
+
+
+
+void PageCacheManager::PutRecentlyUsedCache(
+ DocumentKey pDocument,
+ const Size& rPreviewSize,
+ const ::boost::shared_ptr<Cache>& rpCache)
+{
+ // Look up the list of recently used caches for the given document.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue == mpRecentlyUsedPageCaches->end())
+ iQueue = mpRecentlyUsedPageCaches->insert(
+ RecentlyUsedPageCaches::value_type(pDocument, RecentlyUsedQueue())
+ ).first;
+
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ iQueue->second.push_front(RecentlyUsedCacheDescriptor(pDocument,rPreviewSize,rpCache));
+ // Shorten the list of recently used caches to the allowed maximal length.
+ while (iQueue->second.size() > mnMaximalRecentlyCacheCount)
+ iQueue->second.pop_back();
+ }
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
diff --git a/sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx
new file mode 100755
index 000000000000..bec9c7fa369d
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx
@@ -0,0 +1,254 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlsQueueProcessor.hxx"
+#include "SlsCacheConfiguration.hxx"
+#include "SlsRequestQueue.hxx"
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+//===== QueueProcessor ======================================================
+
+QueueProcessor::QueueProcessor (
+ RequestQueue& rQueue,
+ const ::boost::shared_ptr<BitmapCache>& rpCache,
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext)
+ : maMutex(),
+ maTimer(),
+ mnTimeBetweenHighPriorityRequests (10/*ms*/),
+ mnTimeBetweenLowPriorityRequests (100/*ms*/),
+ mnTimeBetweenRequestsWhenNotIdle (1000/*ms*/),
+ maPreviewSize(rPreviewSize),
+ mpCacheContext(rpCacheContext),
+ mrQueue(rQueue),
+ mpCache(rpCache),
+ maBitmapFactory(),
+ mbIsPaused(false)
+{
+ // Look into the configuration if there for overriding values.
+ ::com::sun::star::uno::Any aTimeBetweenReqeusts;
+ aTimeBetweenReqeusts = CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TimeBetweenHighPriorityRequests")));
+ if (aTimeBetweenReqeusts.has<sal_Int32>())
+ aTimeBetweenReqeusts >>= mnTimeBetweenHighPriorityRequests;
+
+ aTimeBetweenReqeusts = CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TimeBetweenLowPriorityRequests")));
+ if (aTimeBetweenReqeusts.has<sal_Int32>())
+ aTimeBetweenReqeusts >>= mnTimeBetweenLowPriorityRequests;
+
+ aTimeBetweenReqeusts = CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TimeBetweenRequestsDuringShow")));
+ if (aTimeBetweenReqeusts.has<sal_Int32>())
+ aTimeBetweenReqeusts >>= mnTimeBetweenRequestsWhenNotIdle;
+
+ maTimer.SetTimeoutHdl (LINK(this,QueueProcessor,ProcessRequestHdl));
+ maTimer.SetTimeout (mnTimeBetweenHighPriorityRequests);
+}
+
+
+
+
+
+QueueProcessor::~QueueProcessor (void)
+{
+}
+
+
+
+
+void QueueProcessor::Start (int nPriorityClass)
+{
+ if (mbIsPaused)
+ return;
+ if ( ! maTimer.IsActive())
+ {
+ if (nPriorityClass == 0)
+ maTimer.SetTimeout (mnTimeBetweenHighPriorityRequests);
+ else
+ maTimer.SetTimeout (mnTimeBetweenLowPriorityRequests);
+ maTimer.Start();
+ }
+}
+
+
+
+
+void QueueProcessor::Stop (void)
+{
+ if (maTimer.IsActive())
+ maTimer.Stop();
+}
+
+
+
+
+void QueueProcessor::Pause (void)
+{
+ mbIsPaused = true;
+}
+
+
+
+
+void QueueProcessor::Resume (void)
+{
+ mbIsPaused = false;
+ if ( ! mrQueue.IsEmpty())
+ Start(mrQueue.GetFrontPriorityClass());
+}
+
+
+
+
+void QueueProcessor::Terminate (void)
+{
+}
+
+
+
+
+void QueueProcessor::SetPreviewSize (const Size& rPreviewSize)
+{
+ maPreviewSize = rPreviewSize;
+}
+
+
+
+
+IMPL_LINK(QueueProcessor, ProcessRequestHdl, Timer*, EMPTYARG)
+{
+ ProcessRequests();
+ return 1;
+}
+
+
+
+
+void QueueProcessor::ProcessRequests (void)
+{
+ OSL_ASSERT(mpCacheContext.get()!=NULL);
+
+ // Never process more than one request at a time in order to prevent the
+ // lock up of the edit view.
+ if ( ! mrQueue.IsEmpty()
+ && ! mbIsPaused
+ && mpCacheContext->IsIdle())
+ {
+ CacheKey aKey = NULL;
+ RequestPriorityClass ePriorityClass (NOT_VISIBLE);
+ {
+ ::osl::MutexGuard aGuard (mrQueue.GetMutex());
+
+ if ( ! mrQueue.IsEmpty())
+ {
+ // Get the request with the highest priority from the queue.
+ ePriorityClass = mrQueue.GetFrontPriorityClass();
+ aKey = mrQueue.GetFront();
+ mrQueue.PopFront();
+ }
+ }
+
+ if (aKey != NULL)
+ ProcessOneRequest(aKey, ePriorityClass);
+ }
+
+ // Schedule the processing of the next element(s).
+ {
+ ::osl::MutexGuard aGuard (mrQueue.GetMutex());
+ if ( ! mrQueue.IsEmpty())
+ Start(mrQueue.GetFrontPriorityClass());
+ }
+}
+
+
+
+
+void QueueProcessor::ProcessOneRequest (
+ CacheKey aKey,
+ const RequestPriorityClass ePriorityClass)
+{
+ try
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Create a new preview bitmap and store it in the cache.
+ if (mpCache.get() != NULL
+ && mpCacheContext.get() != NULL)
+ {
+ const SdPage* pSdPage = dynamic_cast<const SdPage*>(mpCacheContext->GetPage(aKey));
+ if (pSdPage != NULL)
+ {
+ const ::boost::shared_ptr<BitmapEx> pPreview (
+ maBitmapFactory.CreateBitmap(*pSdPage, maPreviewSize));
+ mpCache->SetBitmap (
+ pSdPage,
+ pPreview,
+ ePriorityClass!=NOT_VISIBLE);
+
+ // Initiate a repaint of the new preview.
+ mpCacheContext->NotifyPreviewCreation(aKey, pPreview);
+ }
+ }
+ }
+ catch (::com::sun::star::uno::RuntimeException aException)
+ {
+ (void) aException;
+ OSL_ASSERT("RuntimeException caught in QueueProcessor");
+ }
+ catch (::com::sun::star::uno::Exception aException)
+ {
+ (void) aException;
+ OSL_ASSERT("Exception caught in QueueProcessor");
+ }
+}
+
+
+
+
+void QueueProcessor::RemoveRequest (CacheKey aKey)
+{
+ (void)aKey;
+ // See the method declaration above for an explanation why this makes sense.
+ ::osl::MutexGuard aGuard (maMutex);
+}
+
+
+
+
+void QueueProcessor::SetBitmapCache (
+ const ::boost::shared_ptr<BitmapCache>& rpCache)
+{
+ mpCache = rpCache;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
diff --git a/sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx
new file mode 100644
index 000000000000..e42ad092d0e2
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_QUEUE_PROCESSOR_HXX
+#define SD_SLIDESORTER_QUEUE_PROCESSOR_HXX
+
+#include "cache/SlsPageCache.hxx"
+#include "SlsRequestPriorityClass.hxx"
+#include "SlsBitmapFactory.hxx"
+#include "view/SlsPageObject.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "tools/IdleDetection.hxx"
+#include "SlsBitmapCache.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+
+#include <svx/svdpagv.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/timer.hxx>
+#include <boost/function.hpp>
+
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapCache;
+class RequestQueue;
+
+
+
+/** This queue processor is timer based, i.e. when an entry is added to the
+ queue and the processor is started with Start() in the base class a
+ timer is started that eventually calls ProcessRequest(). This is
+ repeated until the queue is empty or Stop() is called.
+*/
+class QueueProcessor
+{
+public:
+ typedef ::boost::function<bool()> IdleDetectionCallback;
+ QueueProcessor (
+ RequestQueue& rQueue,
+ const ::boost::shared_ptr<BitmapCache>& rpCache,
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext);
+ virtual ~QueueProcessor();
+
+ /** Start the processor. This implementation is timer based and waits
+ an defined amount of time that depends on the given argument before
+ the next entry in the queue is processed.
+ @param nPriorityClass
+ A priority class of 0 tells the processor that a high priority
+ request is waiting in the queue. The time to wait is thus
+ shorter then that for a low priority request (denoted by a value
+ of 1.) When the timer is already running it is not modified.
+ */
+ void Start (int nPriorityClass = 0);
+ void Stop (void);
+ void Pause (void);
+ void Resume (void);
+
+ void Terminate (void);
+
+ void SetPreviewSize (const Size& rSize);
+
+ /** As we can not really terminate the rendering of a preview bitmap for
+ a request in midair this method acts more like a semaphor. It
+ returns only when it is save for the caller to delete the request.
+ For this to work it is important to remove the request from the
+ queue before calling this method.
+ */
+ void RemoveRequest (CacheKey aKey);
+
+ /** Use this method when the page cache is (maybe) using a different
+ BitmapCache. This is usually necessary after calling
+ PageCacheManager::ChangeSize().
+ */
+ void SetBitmapCache (const ::boost::shared_ptr<BitmapCache>& rpCache);
+
+private:
+ /** This mutex is used to guard the queue processor. Be carefull not to
+ mix its use with that of the solar mutex.
+ */
+ ::osl::Mutex maMutex;
+
+ Timer maTimer;
+ DECL_LINK(ProcessRequestHdl, Timer*);
+ sal_uInt32 mnTimeBetweenHighPriorityRequests;
+ sal_uInt32 mnTimeBetweenLowPriorityRequests;
+ sal_uInt32 mnTimeBetweenRequestsWhenNotIdle;
+ Size maPreviewSize;
+ SharedCacheContext mpCacheContext;
+ RequestQueue& mrQueue;
+ ::boost::shared_ptr<BitmapCache> mpCache;
+ BitmapFactory maBitmapFactory;
+ bool mbIsPaused;
+
+ void ProcessRequests (void);
+ void ProcessOneRequest (
+ CacheKey aKey,
+ const RequestPriorityClass ePriorityClass);
+};
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx b/sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx
new file mode 100644
index 000000000000..08ca63284ea6
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx
@@ -0,0 +1,365 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_QUEUE_PROCESSOR_THREAD_HXX
+#define SD_SLIDESORTER_QUEUE_PROCESSOR_THREAD_HXX
+
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include <vcl/svapp.hxx>
+#include <osl/thread.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+class QueueProcessorThread
+ : public ::osl::Thread
+{
+public:
+ QueueProcessorThread (
+ view::SlideSorterView& rView,
+ Queue& rQueue,
+ BitmapCache& rCache);
+ ~QueueProcessorThread (void);
+
+ /** Start the execution of a suspended thread. A thread is suspended
+ after Stop() is called or when the queue on which it operates is
+ empty. Calling Start() on a running thread is OK.
+ */
+ void Start (void);
+
+ /** Stop the thread by suspending it. To re-start its execution call
+ Start().
+ */
+ void Stop (void);
+
+ /** As we can not really terminate the rendering of a preview bitmap for
+ a request in midair this method acts more like a semaphor. It
+ returns only when it is save for the caller to delete the request.
+ For this to work it is important to remove the request from the
+ queue before calling this method.
+ */
+ void RemoveRequest (RequestData& rRequest);
+
+ /** Terminate the execution of the thread. When the thread is detached
+ it deletes itself. Otherwise the caller of this method may call
+ delete after this method returnes.
+ */
+ void SAL_CALL Terminate (void);
+
+protected:
+ /** This virutal method is called (among others?) from the
+ inherited create method and acts as the main function of this
+ thread.
+ */
+ virtual void SAL_CALL run (void);
+
+ /** Called after the thread is terminated via the terminate
+ method. Used to kill the thread by calling delete on this.
+ */
+ virtual void SAL_CALL onTerminated (void);
+
+private:
+ /** Flag that indicates wether the onTerminated method has been already
+ called. If so then a subsequent call to detach deletes the thread.
+ */
+ volatile bool mbIsTerminated;
+
+ volatile bool mbCanBeJoined;
+
+ /** This mutex is used to guard the queue processor. Be carefull not to
+ mix its use with that of the solar mutex.
+ */
+ ::osl::Mutex maMutex;
+
+ view::SlideSorterView& mrView;
+ Queue& mrQueue;
+ BitmapCache& mrCache;
+
+ void ProcessQueueEntry (void);
+};
+
+
+
+
+//===== QueueProcessorThread ================================================
+
+template <class Queue, class Request, class Cache, class Factory>
+ QueueProcessorThread<Queue, Request, Cache, Factory>
+ ::QueueProcessorThread (
+ view::SlideSorterView& rView,
+ Queue& rQueue,
+ Cache& rCache)
+ : mbIsTerminated (false),
+ mbCanBeJoined (false),
+ mrView (rView),
+ mrQueue (rQueue),
+ mrCache (rCache)
+{
+ OSL_TRACE("QueueProcessorThread::constructor %p", this);
+ create();
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+ QueueProcessorThread<Queue, Request, Cache, Factory>
+ ::~QueueProcessorThread (void)
+{
+ OSL_TRACE("QueueProcessorThread::destructor %p", this);
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+void SAL_CALL QueueProcessorThread<Queue, Request, Cache, Factory>::run (void)
+{
+ OSL_TRACE("QueueProcessorThread::run(): running thread %p", this);
+ while ( ! mbIsTerminated)
+ {
+ OSL_TRACE("QueueProcessorThread::run(): still running thread %p: %d", this, mbIsTerminated?1:0);
+ if (mrQueue.IsEmpty())
+ {
+ // Sleep while the queue is empty.
+ OSL_TRACE("QueueProcessorThread::run(): suspending thread %p", this);
+ suspend();
+ OSL_TRACE("QueueProcessorThread::run(): running again thread %p", this);
+ }
+
+ else if (GetpApp()->AnyInput())
+ {
+ yield();
+ // When there is input waiting to be processed we wait a short
+ // time and try again.
+ TimeValue aTimeToWait;
+ aTimeToWait.Seconds = 0;
+ aTimeToWait.Nanosec = 50*1000*1000;
+ OSL_TRACE("QueueProcessorThread::run(): input pending: waiting %d nanoseconds",
+ aTimeToWait.Nanosec);
+ wait (aTimeToWait);
+ }
+
+ else
+ {
+ OSL_TRACE ("QueueProcessorThread::run(): Processing Query");
+ ProcessQueueEntry();
+ yield ();
+ }
+ }
+ OSL_TRACE("QueueProcessorThread::run(): exiting run %p", this);
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+void QueueProcessorThread<Queue, Request, Cache, Factory>
+ ::ProcessQueueEntry (void)
+{
+ Request* pRequest = NULL;
+ int nPriorityClass;
+ bool bRequestIsValid = false;
+
+ do
+ {
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry(): testing for mbIsTerminated %p", this);
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ if (mbIsTerminated)
+ break;
+ if (mrQueue.IsEmpty())
+ break;
+ }
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry():acquiring mutex for bitmap creation %p", this);
+ ::vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ ::osl::MutexGuard aGuard (maMutex);
+ if (mbIsTerminated)
+ break;
+
+ if (mrQueue.IsEmpty())
+ break;
+
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry(): have mutexes %p", this);
+
+ // Get the requeuest with the highest priority from the queue.
+ nPriorityClass = mrQueue.GetFrontPriorityClass();
+ pRequest = &mrQueue.GetFront();
+ mrQueue.PopFront();
+ bRequestIsValid = true;
+
+
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry():using request %p for creating bitmap", pRequest);
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry():processing request for page %d with priority class ",
+ pRequest->GetPage()->GetPageNum(), nPriorityClass);
+ try
+ {
+ // Create a new preview bitmap and store it in the cache.
+ if (mbIsTerminated)
+ break;
+ BitmapEx aBitmap (Factory::CreateBitmap (*pRequest, mrView));
+ if (mbIsTerminated)
+ break;
+ mrCache.SetBitmap (
+ pRequest->GetPage(),
+ aBitmap,
+ nPriorityClass==0);
+ }
+ catch (...)
+ {
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry(): caught exception; %p", this);
+ // We are rendering a preview and can do without if need
+ // be. So keep going if something happens that should
+ // not happen.
+ }
+ }
+ while (false);
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::Start (void)
+{
+ OSL_TRACE ("QueueProcessorThread::Start %p", this);
+ resume ();
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::Stop (void)
+{
+ OSL_TRACE ("QueueProcessorThread::Stop %p", this);
+ suspend();
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::RemoveRequest (RequestData& rRequest)
+{
+ OSL_TRACE ("QueueProcessorThread::RemoveRequest %p", this);
+ // Do nothing else then wait for the mutex to be released.
+ ::osl::MutexGuard aGuard (mrQueue.GetMutex());
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::Terminate (void)
+{
+ // ::vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ OSL_TRACE("QueueProcessorThread::Terminate(): terminating thread %p", this);
+ ::osl::Thread::terminate ();
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ OSL_TRACE("QueueProcessorThread::Terminate(): starting to join %p, %d", this, mbIsTerminated?1:0);
+ mbIsTerminated = true;
+ }
+ Start();
+}
+
+
+
+
+/** This callback method is called when the run() method terminates.
+*/
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void SAL_CALL QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::onTerminated (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ mbCanBeJoined = true;
+ /*
+ OSL_TRACE("QueueProcessorThread::Terminate():join %p, %d", this, mbIsTerminated?1:0);
+ while (true)
+ {
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ if (mbCanBeJoined)
+ break;
+ }
+ Start();
+ TimeValue aTimeToWait;
+ aTimeToWait.Seconds = 0;
+ aTimeToWait.Nanosec = 50*1000*1000;
+ OSL_TRACE("QueueProcessorThread::Terminate(): waiting for join");
+ wait (aTimeToWait);
+ }
+ if (mbCanBeJoined)
+ join();
+ else
+ OSL_TRACE("Can not join");
+ OSL_TRACE("QueueProcessorThread::Terminate():terminated thread %p :%d",
+ this, mbIsTerminated?1:0);
+ */
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx b/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx
new file mode 100644
index 000000000000..8030558759f3
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx
@@ -0,0 +1,78 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsRequestFactory.hxx"
+
+#include "SlsGenericPageCache.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include <svx/svdpagv.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+void RequestFactory::operator()(
+ RequestQueue& rRequestQueue,
+ const SharedCacheContext& rpCacheContext)
+{
+ ::boost::shared_ptr<std::vector<CacheKey> > aKeys;
+
+ // Add the requests for the visible pages.
+ aKeys = rpCacheContext->GetEntryList(true);
+ if (aKeys.get() != NULL)
+ {
+ std::vector<CacheKey>::const_iterator iKey;
+ std::vector<CacheKey>::const_iterator iEnd (aKeys->end());
+ for (iKey=aKeys->begin(); iKey!=iEnd; ++iKey)
+ rRequestQueue.AddRequest(*iKey, VISIBLE_NO_PREVIEW);
+ }
+
+ // Add the requests for the non-visible pages.
+ aKeys = rpCacheContext->GetEntryList(false);
+ if (aKeys.get() != NULL)
+ {
+ std::vector<CacheKey>::const_iterator iKey;
+ std::vector<CacheKey>::const_iterator iEnd (aKeys->end());
+ for (iKey=aKeys->begin(); iKey!=iEnd; ++iKey)
+ rRequestQueue.AddRequest(*iKey, NOT_VISIBLE);
+ }
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx b/sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx
new file mode 100644
index 000000000000..d2872c2ad7bf
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx
@@ -0,0 +1,48 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_REQUEST_FACTORY_HXX
+#define SD_SLIDESORTER_REQUEST_FACTORY_HXX
+
+#include "cache/SlsCacheContext.hxx"
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class RequestQueue;
+
+class RequestFactory
+{
+public:
+ void operator() (
+ RequestQueue& rRequestQueue,
+ const SharedCacheContext& rpCacheContext);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx b/sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx
new file mode 100644
index 000000000000..ebf6284a8f8b
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx
@@ -0,0 +1,55 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CACHE_REQUEST_PRIORITY_CLASS_HXX
+#define SD_SLIDESORTER_CACHE_REQUEST_PRIORITY_CLASS_HXX
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+/** Each request for a preview creation has a priority. This enum defines
+ the available priorities. The special values MIN__CLASS and MAX__CLASS
+ are/can be used for validation and have to be kept up-to-date.
+*/
+enum RequestPriorityClass
+{
+ MIN__CLASS = 0,
+
+ // The slide is visible. A preview does not yet exist.
+ VISIBLE_NO_PREVIEW = MIN__CLASS,
+ // The slide is visible. A preview exists but is not up-to-date anymore.
+ VISIBLE_OUTDATED_PREVIEW,
+ // The slide is not visible.
+ NOT_VISIBLE,
+
+ MAX__CLASS = NOT_VISIBLE
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx b/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx
new file mode 100644
index 000000000000..ccd590131343
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx
@@ -0,0 +1,291 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsRequestQueue.hxx"
+
+#include <set>
+
+
+#undef VERBOSE
+//#define VERBOSE
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** This class extends the actual request data with additional information
+ that is used by the priority queues.
+*/
+class Request
+{
+public:
+ Request (
+ CacheKey aKey, sal_Int32 nPriority, RequestPriorityClass eClass)
+ : maKey(aKey), mnPriorityInClass(nPriority), meClass(eClass)
+ {}
+ /** Sort requests according to priority classes and then to priorities.
+ */
+ class Comparator { public:
+ bool operator() (const Request& rRequest1, const Request& rRequest2)
+ {
+ if (rRequest1.meClass == rRequest2.meClass)
+ return (rRequest1.mnPriorityInClass > rRequest2.mnPriorityInClass);
+ else
+ return (rRequest1.meClass < rRequest2.meClass);
+ }
+ };
+ /** Request data is compared arbitrarily by their addresses in memory.
+ This just establishes an order so that the STL containers are happy.
+ The order is not semantically interpreted.
+ */
+ class DataComparator { public:
+ DataComparator (const Request&rRequest):maKey(rRequest.maKey){}
+ DataComparator (const CacheKey aKey):maKey(aKey){}
+ bool operator() (const Request& rRequest) { return maKey == rRequest.maKey; }
+ private: const CacheKey maKey;
+ };
+
+ CacheKey maKey;
+ sal_Int32 mnPriorityInClass;
+ RequestPriorityClass meClass;
+};
+
+
+class RequestQueue::Container
+ : public ::std::set<
+ Request,
+ Request::Comparator>
+{
+};
+
+
+
+
+//===== GenericRequestQueue =================================================
+
+
+RequestQueue::RequestQueue (const SharedCacheContext& rpCacheContext)
+ : maMutex(),
+ mpRequestQueue(new Container()),
+ mpCacheContext(rpCacheContext),
+ mnMinimumPriority(0),
+ mnMaximumPriority(1)
+{
+}
+
+
+
+
+RequestQueue::~RequestQueue (void)
+{
+}
+
+
+
+
+void RequestQueue::AddRequest (
+ CacheKey aKey,
+ RequestPriorityClass eRequestClass,
+ bool /*bInsertWithHighestPriority*/)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ OSL_ASSERT(eRequestClass>=MIN__CLASS && eRequestClass<=MAX__CLASS);
+
+ // If the request is already a member of the queue then remove it so
+ // that the following insertion will use the new prioritization.
+#ifdef VERBOSE
+ bool bRemoved =
+#endif
+ RemoveRequest(aKey);
+
+ // The priority of the request inside its priority class is defined by
+ // the page number. This ensures a strict top-to-bottom, left-to-right
+ // order.
+ sal_Int32 nPriority (mpCacheContext->GetPriority(aKey));
+ Request aRequest (aKey, nPriority, eRequestClass);
+ mpRequestQueue->insert(aRequest);
+
+ SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eRequestClass);
+
+#ifdef VERBOSE
+ OSL_TRACE("%s request for page %d with priority class %d",
+ bRemoved?"replaced":"added",
+ (rRequestData.GetPage()->GetPageNum()-1)/2,
+ eRequestClass);
+#endif
+}
+
+
+
+
+bool RequestQueue::RemoveRequest (
+ CacheKey aKey)
+{
+ bool bRequestWasRemoved (false);
+ ::osl::MutexGuard aGuard (maMutex);
+
+ while(true)
+ {
+ Container::const_iterator aRequestIterator = ::std::find_if (
+ mpRequestQueue->begin(),
+ mpRequestQueue->end(),
+ Request::DataComparator(aKey));
+ if (aRequestIterator != mpRequestQueue->end())
+ {
+ if (aRequestIterator->mnPriorityInClass == mnMinimumPriority+1)
+ mnMinimumPriority++;
+ else if (aRequestIterator->mnPriorityInClass == mnMaximumPriority-1)
+ mnMaximumPriority--;
+ mpRequestQueue->erase(aRequestIterator);
+ bRequestWasRemoved = true;
+
+ if (bRequestWasRemoved)
+ {
+ SSCD_SET_STATUS(rRequest.GetPage(),NONE);
+ }
+ }
+ else
+ break;
+ }
+
+ return bRequestWasRemoved;
+}
+
+
+
+
+void RequestQueue::ChangeClass (
+ CacheKey aKey,
+ RequestPriorityClass eNewRequestClass)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ OSL_ASSERT(eNewRequestClass>=MIN__CLASS && eNewRequestClass<=MAX__CLASS);
+
+ Container::const_iterator iRequest (
+ ::std::find_if (
+ mpRequestQueue->begin(),
+ mpRequestQueue->end(),
+ Request::DataComparator(aKey)));
+ if (iRequest!=mpRequestQueue->end() && iRequest->meClass!=eNewRequestClass)
+ {
+ AddRequest(aKey, eNewRequestClass, true);
+ SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eNewRequestClass);
+ }
+}
+
+
+
+
+CacheKey RequestQueue::GetFront (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (mpRequestQueue->empty())
+ throw ::com::sun::star::uno::RuntimeException(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "RequestQueue::GetFront(): queue is empty")),
+ NULL);
+
+ return mpRequestQueue->begin()->maKey;
+}
+
+
+
+
+RequestPriorityClass RequestQueue::GetFrontPriorityClass (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (mpRequestQueue->empty())
+ throw ::com::sun::star::uno::RuntimeException(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "RequestQueue::GetFrontPriorityClass(): queue is empty")),
+ NULL);
+
+ return mpRequestQueue->begin()->meClass;
+}
+
+
+
+
+void RequestQueue::PopFront (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if ( ! mpRequestQueue->empty())
+ {
+ SSCD_SET_STATUS(maRequestQueue.begin()->mpData->GetPage(),NONE);
+
+ mpRequestQueue->erase(mpRequestQueue->begin());
+
+ // Reset the priority counter if possible.
+ if (mpRequestQueue->empty())
+ {
+ mnMinimumPriority = 0;
+ mnMaximumPriority = 1;
+ }
+ }
+}
+
+
+
+
+bool RequestQueue::IsEmpty (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ return mpRequestQueue->empty();
+}
+
+
+
+
+void RequestQueue::Clear (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mpRequestQueue->clear();
+ mnMinimumPriority = 0;
+ mnMaximumPriority = 1;
+}
+
+
+
+
+::osl::Mutex& RequestQueue::GetMutex (void)
+{
+ return maMutex;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx b/sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx
new file mode 100644
index 000000000000..f59ec702ac01
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx
@@ -0,0 +1,133 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_REQUEST_QUEUE_HXX
+#define SD_SLIDESORTER_REQUEST_QUEUE_HXX
+
+#include "SlsRequestPriorityClass.hxx"
+#include "cache/SlsCacheContext.hxx"
+#include "taskpane/SlideSorterCacheDisplay.hxx"
+#include <drawdoc.hxx>
+#include "osl/mutex.hxx"
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class RequestData;
+
+/** The request queue stores requests that are described by the RequestData
+ sorted according to priority class and then priority.
+*/
+class RequestQueue
+{
+public:
+ RequestQueue (const SharedCacheContext& rpCacheContext);
+ ~RequestQueue (void);
+
+ /** Insert a request with highest or lowest priority in its priority
+ class. When the request is already present then it is first
+ removed. This effect is then a re-prioritization.
+ @param rRequestData
+ The request.
+ @param eRequestClass
+ The priority class in which to insert the request with highest
+ or lowest priority.
+ @param bInsertWithHighestPriority
+ When this flag is <TRUE/> the request is inserted with highes
+ priority in its class. When <FALSE/> the request is inserted
+ with lowest priority.
+ */
+ void AddRequest (
+ CacheKey aKey,
+ RequestPriorityClass eRequestClass,
+ bool bInsertWithHighestPriority = false);
+
+ /** Remove the specified request from the queue.
+ @param rRequestData
+ It is OK when the specified request is not a member of the
+ queue.
+ @return
+ Returns <TRUE/> when the request has been successfully been
+ removed from the queue. Otherwise, e.g. because the request was
+ not a member of the queue, <FALSE/> is returned.
+ */
+ bool RemoveRequest (CacheKey aKey);
+
+ /** Change the priority class of the specified request.
+ */
+ void ChangeClass (
+ CacheKey aKey,
+ RequestPriorityClass eNewRequestClass);
+
+ /** Get the request with the highest priority int the highest priority class.
+ */
+ CacheKey GetFront (void);
+
+ // For debugging.
+ RequestPriorityClass GetFrontPriorityClass (void);
+
+ /** Really a synonym for RemoveRequest(GetFront());
+ */
+ void PopFront (void);
+
+ /** Returns <TRUE/> when there is no element in the queue.
+ */
+ bool IsEmpty (void);
+
+ /** Remove all requests from the queue. This resets the minimum and
+ maximum priorities to their default values.
+ */
+ void Clear (void);
+
+ /** Return the mutex that guards the access to the priority queue.
+ */
+ ::osl::Mutex& GetMutex (void);
+
+private:
+ ::osl::Mutex maMutex;
+ class Container;
+ ::boost::scoped_ptr<Container> mpRequestQueue;
+ SharedCacheContext mpCacheContext;
+
+ /** A lower bound of the lowest priority of all elements in the queues.
+ The start value is 0. It is assigned and then decreased every time
+ when an element is inserted or marked as the request with lowest
+ priority.
+ */
+ int mnMinimumPriority;
+ /** An upper bound of the highest priority of all elements in the queues.
+ The start value is 1. It is assigned and then increased every time
+ when an element is inserted or marked as the request with highest
+ priority.
+ */
+ int mnMaximumPriority;
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
diff --git a/sd/source/ui/slidesorter/cache/makefile.mk b/sd/source/ui/slidesorter/cache/makefile.mk
new file mode 100755
index 000000000000..58862a28645a
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/makefile.mk
@@ -0,0 +1,64 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=slscache
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/SlsBitmapCache.obj \
+ $(SLO)$/SlsBitmapCompressor.obj \
+ $(SLO)$/SlsBitmapFactory.obj \
+ $(SLO)$/SlsCacheCompactor.obj \
+ $(SLO)$/SlsCacheConfiguration.obj \
+ $(SLO)$/SlsGenericPageCache.obj \
+ $(SLO)$/SlsPageCache.obj \
+ $(SLO)$/SlsPageCacheManager.obj \
+ $(SLO)$/SlsQueueProcessor.obj \
+ $(SLO)$/SlsRequestFactory.obj \
+ $(SLO)$/SlsRequestQueue.obj
+
+
+EXCEPTIONSFILES=
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+