diff options
Diffstat (limited to 'sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx')
-rw-r--r-- | sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx new file mode 100644 index 000000000000..f7fb30a4c6ec --- /dev/null +++ b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx @@ -0,0 +1,379 @@ +/************************************************************************* + * + * 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 "SlsQueueProcessor.hxx" +#include "SlsRequestPriorityClass.hxx" +#include "SlsRequestFactory.hxx" +#include "cache/SlsPageCacheManager.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "controller/SlideSorterController.hxx" + + +namespace sd { namespace slidesorter { namespace cache { + +GenericPageCache::GenericPageCache ( + const Size& rPreviewSize, + const bool bDoSuperSampling, + const SharedCacheContext& rpCacheContext) + : mpBitmapCache(), + maRequestQueue(rpCacheContext), + mpQueueProcessor(), + mpCacheContext(rpCacheContext), + maPreviewSize(rPreviewSize), + mbDoSuperSampling(bDoSuperSampling) +{ + // A large size may indicate an error of the caller. After all we + // are creating previews. + DBG_ASSERT (maPreviewSize.Width()<1000 && maPreviewSize.Height()<1000, + "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. " + "This may indicate an error."); +} + + + + +GenericPageCache::~GenericPageCache (void) +{ + if (mpQueueProcessor.get() != NULL) + mpQueueProcessor->Stop(); + maRequestQueue.Clear(); + if (mpQueueProcessor.get() != NULL) + mpQueueProcessor->Terminate(); + mpQueueProcessor.reset(); + + 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, + mbDoSuperSampling, + mpCacheContext)); +} + + + + +void GenericPageCache::ChangePreviewSize ( + const Size& rPreviewSize, + const bool bDoSuperSampling) +{ + if (rPreviewSize!=maPreviewSize || bDoSuperSampling!=mbDoSuperSampling) + { + // A large size may indicate an error of the caller. After all we + // are creating previews. + DBG_ASSERT (maPreviewSize.Width()<1000 && maPreviewSize.Height()<1000, + "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. " + "This may indicate an error."); + + if (mpBitmapCache.get() != NULL) + { + mpBitmapCache = PageCacheManager::Instance()->ChangeSize( + mpBitmapCache, maPreviewSize, rPreviewSize); + if (mpQueueProcessor.get() != NULL) + { + mpQueueProcessor->SetPreviewSize(rPreviewSize, bDoSuperSampling); + mpQueueProcessor->SetBitmapCache(mpBitmapCache); + } + } + maPreviewSize = rPreviewSize; + mbDoSuperSampling = bDoSuperSampling; + } +} + + + + +Bitmap GenericPageCache::GetPreviewBitmap ( + const CacheKey aKey, + const bool bResize) +{ + OSL_ASSERT(aKey != NULL); + + Bitmap aPreview; + bool bMayBeUpToDate = true; + ProvideCacheAndProcessor(); + const SdrPage* pPage = mpCacheContext->GetPage(aKey); + if (mpBitmapCache->HasBitmap(pPage)) + { + aPreview = mpBitmapCache->GetBitmap(pPage); + const Size aBitmapSize (aPreview.GetSizePixel()); + if (aBitmapSize != maPreviewSize) + { + // Scale the bitmap to the desired size when that is possible, + // i.e. the bitmap is not empty. + if (bResize && aBitmapSize.Width()>0 && aBitmapSize.Height()>0) + { + aPreview.Scale(maPreviewSize, BMP_SCALE_FAST); + } + bMayBeUpToDate = false; + } + else + 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, bMayBeUpToDate); + + return aPreview; +} + + + + +Bitmap GenericPageCache::GetMarkedPreviewBitmap ( + const CacheKey aKey, + const bool bResize) +{ + OSL_ASSERT(aKey != NULL); + + ProvideCacheAndProcessor(); + const SdrPage* pPage = mpCacheContext->GetPage(aKey); + Bitmap aMarkedPreview (mpBitmapCache->GetMarkedBitmap(pPage)); + const Size aBitmapSize (aMarkedPreview.GetSizePixel()); + if (bResize && aBitmapSize != maPreviewSize) + { + // 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) + { + aMarkedPreview.Scale(maPreviewSize, BMP_SCALE_FAST); + } + } + + return aMarkedPreview; +} + + + + +void GenericPageCache::SetMarkedPreviewBitmap ( + const CacheKey aKey, + const Bitmap& rMarkedBitmap) +{ + OSL_ASSERT(aKey != NULL); + + ProvideCacheAndProcessor(); + const SdrPage* pPage = mpCacheContext->GetPage(aKey); + mpBitmapCache->SetMarkedBitmap(pPage, rMarkedBitmap); +} + + + + +void GenericPageCache::RequestPreviewBitmap ( + const CacheKey aKey, + const 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) + { + const Bitmap aPreview (mpBitmapCache->GetBitmap(pPage)); + if (aPreview.IsEmpty() || aPreview.GetSizePixel()!=maPreviewSize) + 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); + } +} + + + + +bool GenericPageCache::InvalidatePreviewBitmap (const CacheKey aKey) +{ + // Invalidate the page in all caches that reference it, not just this one. + ::boost::shared_ptr<cache::PageCacheManager> pCacheManager ( + cache::PageCacheManager::Instance()); + if (pCacheManager) + return pCacheManager->InvalidatePreviewBitmap( + mpCacheContext->GetModel(), + aKey); + else if (mpBitmapCache.get() != NULL) + return mpBitmapCache->InvalidateBitmap(mpCacheContext->GetPage(aKey)); + else + return false; +} + + + + +void GenericPageCache::ReleasePreviewBitmap (const 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 (const bool bUpdateCache) +{ + if (mpBitmapCache) + { + // 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 ( + const CacheKey aKey, + const 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 + + + |