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