/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the 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_FASTESTINTERPOLATE); } 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_FASTESTINTERPOLATE); } } 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 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