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