1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "precompiled_sd.hxx" 29 30 #include "SlsGenericPageCache.hxx" 31 32 #include "SlsQueueProcessor.hxx" 33 #include "SlsRequestPriorityClass.hxx" 34 #include "SlsRequestFactory.hxx" 35 #include "cache/SlsPageCacheManager.hxx" 36 #include "model/SlideSorterModel.hxx" 37 #include "model/SlsPageDescriptor.hxx" 38 #include "controller/SlideSorterController.hxx" 39 40 41 namespace sd { namespace slidesorter { namespace cache { 42 43 GenericPageCache::GenericPageCache ( 44 const Size& rPreviewSize, 45 const bool bDoSuperSampling, 46 const SharedCacheContext& rpCacheContext) 47 : mpBitmapCache(), 48 maRequestQueue(rpCacheContext), 49 mpQueueProcessor(), 50 mpCacheContext(rpCacheContext), 51 maPreviewSize(rPreviewSize), 52 mbDoSuperSampling(bDoSuperSampling) 53 { 54 // A large size may indicate an error of the caller. After all we 55 // are creating previews. 56 DBG_ASSERT (maPreviewSize.Width()<1000 && maPreviewSize.Height()<1000, 57 "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. " 58 "This may indicate an error."); 59 } 60 61 62 63 64 GenericPageCache::~GenericPageCache (void) 65 { 66 if (mpQueueProcessor.get() != NULL) 67 mpQueueProcessor->Stop(); 68 maRequestQueue.Clear(); 69 if (mpQueueProcessor.get() != NULL) 70 mpQueueProcessor->Terminate(); 71 mpQueueProcessor.reset(); 72 73 if (mpBitmapCache.get() != NULL) 74 PageCacheManager::Instance()->ReleaseCache(mpBitmapCache); 75 mpBitmapCache.reset(); 76 } 77 78 79 80 81 void GenericPageCache::ProvideCacheAndProcessor (void) 82 { 83 if (mpBitmapCache.get() == NULL) 84 mpBitmapCache = PageCacheManager::Instance()->GetCache( 85 mpCacheContext->GetModel(), 86 maPreviewSize); 87 88 if (mpQueueProcessor.get() == NULL) 89 mpQueueProcessor.reset(new QueueProcessor( 90 maRequestQueue, 91 mpBitmapCache, 92 maPreviewSize, 93 mbDoSuperSampling, 94 mpCacheContext)); 95 } 96 97 98 99 100 void GenericPageCache::ChangePreviewSize ( 101 const Size& rPreviewSize, 102 const bool bDoSuperSampling) 103 { 104 if (rPreviewSize!=maPreviewSize || bDoSuperSampling!=mbDoSuperSampling) 105 { 106 // A large size may indicate an error of the caller. After all we 107 // are creating previews. 108 DBG_ASSERT (maPreviewSize.Width()<1000 && maPreviewSize.Height()<1000, 109 "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. " 110 "This may indicate an error."); 111 112 if (mpBitmapCache.get() != NULL) 113 { 114 mpBitmapCache = PageCacheManager::Instance()->ChangeSize( 115 mpBitmapCache, maPreviewSize, rPreviewSize); 116 if (mpQueueProcessor.get() != NULL) 117 { 118 mpQueueProcessor->SetPreviewSize(rPreviewSize, bDoSuperSampling); 119 mpQueueProcessor->SetBitmapCache(mpBitmapCache); 120 } 121 } 122 maPreviewSize = rPreviewSize; 123 mbDoSuperSampling = bDoSuperSampling; 124 } 125 } 126 127 128 129 130 Bitmap GenericPageCache::GetPreviewBitmap ( 131 const CacheKey aKey, 132 const bool bResize) 133 { 134 OSL_ASSERT(aKey != NULL); 135 136 Bitmap aPreview; 137 bool bMayBeUpToDate = true; 138 ProvideCacheAndProcessor(); 139 const SdrPage* pPage = mpCacheContext->GetPage(aKey); 140 if (mpBitmapCache->HasBitmap(pPage)) 141 { 142 aPreview = mpBitmapCache->GetBitmap(pPage); 143 const Size aBitmapSize (aPreview.GetSizePixel()); 144 if (aBitmapSize != maPreviewSize) 145 { 146 // Scale the bitmap to the desired size when that is possible, 147 // i.e. the bitmap is not empty. 148 if (bResize && aBitmapSize.Width()>0 && aBitmapSize.Height()>0) 149 { 150 aPreview.Scale(maPreviewSize, BMP_SCALE_FAST); 151 } 152 bMayBeUpToDate = false; 153 } 154 else 155 bMayBeUpToDate = true; 156 } 157 else 158 bMayBeUpToDate = false; 159 160 // Request the creation of a correctly sized preview bitmap. We do this 161 // even when the size of the bitmap in the cache is correct because its 162 // content may be not up-to-date anymore. 163 RequestPreviewBitmap(aKey, bMayBeUpToDate); 164 165 return aPreview; 166 } 167 168 169 170 171 Bitmap GenericPageCache::GetMarkedPreviewBitmap ( 172 const CacheKey aKey, 173 const bool bResize) 174 { 175 OSL_ASSERT(aKey != NULL); 176 177 ProvideCacheAndProcessor(); 178 const SdrPage* pPage = mpCacheContext->GetPage(aKey); 179 Bitmap aMarkedPreview (mpBitmapCache->GetMarkedBitmap(pPage)); 180 const Size aBitmapSize (aMarkedPreview.GetSizePixel()); 181 if (bResize && aBitmapSize != maPreviewSize) 182 { 183 // Scale the bitmap to the desired size when that is possible, 184 // i.e. the bitmap is not empty. 185 if (aBitmapSize.Width()>0 && aBitmapSize.Height()>0) 186 { 187 aMarkedPreview.Scale(maPreviewSize, BMP_SCALE_FAST); 188 } 189 } 190 191 return aMarkedPreview; 192 } 193 194 195 196 197 void GenericPageCache::SetMarkedPreviewBitmap ( 198 const CacheKey aKey, 199 const Bitmap& rMarkedBitmap) 200 { 201 OSL_ASSERT(aKey != NULL); 202 203 ProvideCacheAndProcessor(); 204 const SdrPage* pPage = mpCacheContext->GetPage(aKey); 205 mpBitmapCache->SetMarkedBitmap(pPage, rMarkedBitmap); 206 } 207 208 209 210 211 void GenericPageCache::RequestPreviewBitmap ( 212 const CacheKey aKey, 213 const bool bMayBeUpToDate) 214 { 215 OSL_ASSERT(aKey != NULL); 216 217 const SdrPage* pPage = mpCacheContext->GetPage(aKey); 218 219 ProvideCacheAndProcessor(); 220 221 // Determine if the available bitmap is up to date. 222 bool bIsUpToDate = false; 223 if (bMayBeUpToDate) 224 bIsUpToDate = mpBitmapCache->BitmapIsUpToDate (pPage); 225 if (bIsUpToDate) 226 { 227 const Bitmap aPreview (mpBitmapCache->GetBitmap(pPage)); 228 if (aPreview.IsEmpty() || aPreview.GetSizePixel()!=maPreviewSize) 229 bIsUpToDate = false; 230 } 231 232 if ( ! bIsUpToDate) 233 { 234 // No, the bitmap is not up-to-date. Request a new one. 235 RequestPriorityClass ePriorityClass (NOT_VISIBLE); 236 if (mpCacheContext->IsVisible(aKey)) 237 { 238 if (mpBitmapCache->HasBitmap(pPage)) 239 ePriorityClass = VISIBLE_OUTDATED_PREVIEW; 240 else 241 ePriorityClass = VISIBLE_NO_PREVIEW; 242 } 243 maRequestQueue.AddRequest(aKey, ePriorityClass); 244 mpQueueProcessor->Start(ePriorityClass); 245 } 246 } 247 248 249 250 251 bool GenericPageCache::InvalidatePreviewBitmap (const CacheKey aKey) 252 { 253 // Invalidate the page in all caches that reference it, not just this one. 254 ::boost::shared_ptr<cache::PageCacheManager> pCacheManager ( 255 cache::PageCacheManager::Instance()); 256 if (pCacheManager) 257 return pCacheManager->InvalidatePreviewBitmap( 258 mpCacheContext->GetModel(), 259 aKey); 260 else if (mpBitmapCache.get() != NULL) 261 return mpBitmapCache->InvalidateBitmap(mpCacheContext->GetPage(aKey)); 262 else 263 return false; 264 } 265 266 267 268 269 void GenericPageCache::ReleasePreviewBitmap (const CacheKey aKey) 270 { 271 if (mpBitmapCache.get() != NULL) 272 { 273 // Suspend the queue processing temporarily to avoid the reinsertion 274 // of the request that is to be deleted. 275 mpQueueProcessor->Stop(); 276 277 maRequestQueue.RemoveRequest(aKey); 278 mpQueueProcessor->RemoveRequest(aKey); 279 280 // Resume the queue processing. 281 if ( ! maRequestQueue.IsEmpty()) 282 { 283 try 284 { 285 mpQueueProcessor->Start(maRequestQueue.GetFrontPriorityClass()); 286 } 287 catch (::com::sun::star::uno::RuntimeException) 288 { 289 } 290 } 291 } 292 293 // We do not relase the preview bitmap that is associated with the page 294 // of the given request data because this method is called when the 295 // request data, typically a view-object-contact object, is destroyed. 296 // The page object usually lives longer than that and thus the preview 297 // bitmap may be used later on. 298 } 299 300 301 302 303 void GenericPageCache::InvalidateCache (const bool bUpdateCache) 304 { 305 if (mpBitmapCache) 306 { 307 // When the cache is being invalidated then it makes no sense to 308 // continue creating preview bitmaps. However, this may be 309 // re-started below. 310 mpQueueProcessor->Stop(); 311 maRequestQueue.Clear(); 312 313 // Mark the previews in the cache as not being up-to-date anymore. 314 // Depending on the given bUpdateCache flag we start to create new 315 // preview bitmaps. 316 mpBitmapCache->InvalidateCache(); 317 if (bUpdateCache) 318 RequestFactory()(maRequestQueue, mpCacheContext); 319 } 320 } 321 322 323 324 325 void GenericPageCache::SetPreciousFlag ( 326 const CacheKey aKey, 327 const bool bIsPrecious) 328 { 329 ProvideCacheAndProcessor(); 330 331 // Change the request priority class according to the new precious flag. 332 if (bIsPrecious) 333 { 334 if (mpBitmapCache->HasBitmap(mpCacheContext->GetPage(aKey))) 335 maRequestQueue.ChangeClass(aKey,VISIBLE_OUTDATED_PREVIEW); 336 else 337 maRequestQueue.ChangeClass(aKey,VISIBLE_NO_PREVIEW); 338 } 339 else 340 { 341 if (mpBitmapCache->IsFull()) 342 { 343 // When the bitmap cache is full then requests for slides that 344 // are not visible are removed. 345 maRequestQueue.RemoveRequest(aKey); 346 } 347 else 348 maRequestQueue.ChangeClass(aKey,NOT_VISIBLE); 349 } 350 351 mpBitmapCache->SetPrecious(mpCacheContext->GetPage(aKey), bIsPrecious); 352 } 353 354 355 356 357 void GenericPageCache::Pause (void) 358 { 359 ProvideCacheAndProcessor(); 360 if (mpQueueProcessor.get() != NULL) 361 mpQueueProcessor->Pause(); 362 } 363 364 365 366 367 void GenericPageCache::Resume (void) 368 { 369 ProvideCacheAndProcessor(); 370 if (mpQueueProcessor.get() != NULL) 371 mpQueueProcessor->Resume(); 372 } 373 374 375 376 } } } // end of namespace ::sd::slidesorter::cache 377 378 379 380