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 
GenericPageCache(const Size & rPreviewSize,const bool bDoSuperSampling,const SharedCacheContext & rpCacheContext)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 
~GenericPageCache(void)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 
ProvideCacheAndProcessor(void)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 
ChangePreviewSize(const Size & rPreviewSize,const bool bDoSuperSampling)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 
GetPreviewBitmap(const CacheKey aKey,const bool bResize)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_FASTESTINTERPOLATE);
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 
GetMarkedPreviewBitmap(const CacheKey aKey,const bool bResize)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_FASTESTINTERPOLATE);
184         }
185     }
186 
187     return aMarkedPreview;
188 }
189 
190 
191 
192 
SetMarkedPreviewBitmap(const CacheKey aKey,const Bitmap & rMarkedBitmap)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 
RequestPreviewBitmap(const CacheKey aKey,const bool bMayBeUpToDate)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 
InvalidatePreviewBitmap(const CacheKey aKey)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 
ReleasePreviewBitmap(const CacheKey aKey)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 
InvalidateCache(const bool bUpdateCache)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 
SetPreciousFlag(const CacheKey aKey,const bool bIsPrecious)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 
Pause(void)353 void GenericPageCache::Pause (void)
354 {
355     ProvideCacheAndProcessor();
356     if (mpQueueProcessor.get() != NULL)
357         mpQueueProcessor->Pause();
358 }
359 
360 
361 
362 
Resume(void)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