1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include "PresenterPreviewCache.hxx"
21
22 #include <cache/SlsPageCache.hxx>
23 #include <cache/SlsCacheContext.hxx>
24 #include <vcl/bitmapex.hxx>
25 #include <sdpage.hxx>
26 #include <cppcanvas/vclfactory.hxx>
27 #include <com/sun/star/drawing/XDrawPage.hpp>
28
29 namespace com { namespace sun { namespace star { namespace uno { class XComponentContext; } } } }
30
31 using namespace ::com::sun::star;
32 using namespace ::com::sun::star::uno;
33 using namespace ::sd::slidesorter::cache;
34
35 namespace sd { namespace presenter {
36
37 class PresenterPreviewCache::PresenterCacheContext : public CacheContext
38 {
39 public:
40 PresenterCacheContext();
41
42 void SetDocumentSlides (
43 const Reference<container::XIndexAccess>& rxSlides,
44 const Reference<XInterface>& rxDocument);
45 void SetVisibleSlideRange (
46 const sal_Int32 nFirstVisibleSlideIndex,
47 const sal_Int32 nLastVisibleSlideIndex);
48 const SdrPage* GetPage (const sal_Int32 nSlideIndex) const;
49 void AddPreviewCreationNotifyListener (const Reference<drawing::XSlidePreviewCacheListener>& rxListener);
50 void RemovePreviewCreationNotifyListener (const Reference<drawing::XSlidePreviewCacheListener>& rxListener);
51
52 // CacheContext
53 virtual void NotifyPreviewCreation (CacheKey aKey) override;
54 virtual bool IsIdle() override;
55 virtual bool IsVisible (CacheKey aKey) override;
56 virtual const SdrPage* GetPage (CacheKey aKey) override;
57 virtual std::shared_ptr<std::vector<CacheKey> > GetEntryList (bool bVisible) override;
58 virtual sal_Int32 GetPriority (CacheKey aKey) override;
59 virtual css::uno::Reference<css::uno::XInterface> GetModel() override;
60
61 private:
62 Reference<container::XIndexAccess> mxSlides;
63 Reference<XInterface> mxDocument;
64 sal_Int32 mnFirstVisibleSlideIndex;
65 sal_Int32 mnLastVisibleSlideIndex;
66 typedef ::std::vector<css::uno::Reference<css::drawing::XSlidePreviewCacheListener> > ListenerContainer;
67 ListenerContainer maListeners;
68
69 void CallListeners (const sal_Int32 nSlideIndex);
70 };
71
72 //===== PresenterPreviewCache =================================================
73
PresenterPreviewCache()74 PresenterPreviewCache::PresenterPreviewCache ()
75 : PresenterPreviewCacheInterfaceBase(m_aMutex),
76 maPreviewSize(Size(200,200)),
77 mpCacheContext(new PresenterCacheContext()),
78 mpCache(new PageCache(maPreviewSize, Bitmap::HasFastScale(), mpCacheContext))
79 {
80 }
81
~PresenterPreviewCache()82 PresenterPreviewCache::~PresenterPreviewCache()
83 {
84 }
85
86 //----- XInitialize -----------------------------------------------------------
87
initialize(const Sequence<Any> & rArguments)88 void SAL_CALL PresenterPreviewCache::initialize (const Sequence<Any>& rArguments)
89 {
90 if (rArguments.hasElements())
91 throw RuntimeException();
92 }
93
94 //----- XSlidePreviewCache ----------------------------------------------------
95
setDocumentSlides(const Reference<container::XIndexAccess> & rxSlides,const Reference<XInterface> & rxDocument)96 void SAL_CALL PresenterPreviewCache::setDocumentSlides (
97 const Reference<container::XIndexAccess>& rxSlides,
98 const Reference<XInterface>& rxDocument)
99 {
100 ThrowIfDisposed();
101 OSL_ASSERT(mpCacheContext != nullptr);
102
103 mpCacheContext->SetDocumentSlides(rxSlides, rxDocument);
104 }
105
setVisibleRange(sal_Int32 nFirstVisibleSlideIndex,sal_Int32 nLastVisibleSlideIndex)106 void SAL_CALL PresenterPreviewCache::setVisibleRange (
107 sal_Int32 nFirstVisibleSlideIndex,
108 sal_Int32 nLastVisibleSlideIndex)
109 {
110 ThrowIfDisposed();
111 OSL_ASSERT(mpCacheContext != nullptr);
112
113 mpCacheContext->SetVisibleSlideRange (nFirstVisibleSlideIndex, nLastVisibleSlideIndex);
114 }
115
setPreviewSize(const css::geometry::IntegerSize2D & rSize)116 void SAL_CALL PresenterPreviewCache::setPreviewSize (
117 const css::geometry::IntegerSize2D& rSize)
118 {
119 ThrowIfDisposed();
120 OSL_ASSERT(mpCache != nullptr);
121
122 maPreviewSize = Size(rSize.Width, rSize.Height);
123 mpCache->ChangeSize(maPreviewSize, Bitmap::HasFastScale());
124 }
125
getSlidePreview(sal_Int32 nSlideIndex,const Reference<rendering::XCanvas> & rxCanvas)126 Reference<rendering::XBitmap> SAL_CALL PresenterPreviewCache::getSlidePreview (
127 sal_Int32 nSlideIndex,
128 const Reference<rendering::XCanvas>& rxCanvas)
129 {
130 ThrowIfDisposed();
131 OSL_ASSERT(mpCacheContext != nullptr);
132
133 cppcanvas::CanvasSharedPtr pCanvas (
134 cppcanvas::VCLFactory::createCanvas(rxCanvas));
135
136 const SdrPage* pPage = mpCacheContext->GetPage(nSlideIndex);
137 if (pPage == nullptr)
138 throw RuntimeException();
139
140 const BitmapEx aPreview (mpCache->GetPreviewBitmap(pPage,true));
141 if (aPreview.IsEmpty())
142 return nullptr;
143 else
144 return cppcanvas::VCLFactory::createBitmap(
145 pCanvas,
146 aPreview)->getUNOBitmap();
147 }
148
addPreviewCreationNotifyListener(const Reference<drawing::XSlidePreviewCacheListener> & rxListener)149 void SAL_CALL PresenterPreviewCache::addPreviewCreationNotifyListener (
150 const Reference<drawing::XSlidePreviewCacheListener>& rxListener)
151 {
152 if (rBHelper.bDisposed || rBHelper.bInDispose)
153 return;
154 if (rxListener.is())
155 mpCacheContext->AddPreviewCreationNotifyListener(rxListener);
156 }
157
removePreviewCreationNotifyListener(const css::uno::Reference<css::drawing::XSlidePreviewCacheListener> & rxListener)158 void SAL_CALL PresenterPreviewCache::removePreviewCreationNotifyListener (
159 const css::uno::Reference<css::drawing::XSlidePreviewCacheListener>& rxListener)
160 {
161 ThrowIfDisposed();
162 mpCacheContext->RemovePreviewCreationNotifyListener(rxListener);
163 }
164
pause()165 void SAL_CALL PresenterPreviewCache::pause()
166 {
167 ThrowIfDisposed();
168 OSL_ASSERT(mpCache != nullptr);
169 mpCache->Pause();
170 }
171
resume()172 void SAL_CALL PresenterPreviewCache::resume()
173 {
174 ThrowIfDisposed();
175 OSL_ASSERT(mpCache != nullptr);
176 mpCache->Resume();
177 }
178
ThrowIfDisposed()179 void PresenterPreviewCache::ThrowIfDisposed()
180 {
181 if (rBHelper.bDisposed || rBHelper.bInDispose)
182 {
183 throw lang::DisposedException ("PresenterPreviewCache object has already been disposed",
184 static_cast<uno::XWeak*>(this));
185 }
186 }
187
188 //===== PresenterPreviewCache::PresenterCacheContext ==========================
189
PresenterCacheContext()190 PresenterPreviewCache::PresenterCacheContext::PresenterCacheContext()
191 : mxSlides(),
192 mxDocument(),
193 mnFirstVisibleSlideIndex(-1),
194 mnLastVisibleSlideIndex(-1),
195 maListeners()
196 {
197 }
198
SetDocumentSlides(const Reference<container::XIndexAccess> & rxSlides,const Reference<XInterface> & rxDocument)199 void PresenterPreviewCache::PresenterCacheContext::SetDocumentSlides (
200 const Reference<container::XIndexAccess>& rxSlides,
201 const Reference<XInterface>& rxDocument)
202 {
203 mxSlides = rxSlides;
204 mxDocument = rxDocument;
205 mnFirstVisibleSlideIndex = -1;
206 mnLastVisibleSlideIndex = -1;
207 }
208
SetVisibleSlideRange(const sal_Int32 nFirstVisibleSlideIndex,const sal_Int32 nLastVisibleSlideIndex)209 void PresenterPreviewCache::PresenterCacheContext::SetVisibleSlideRange (
210 const sal_Int32 nFirstVisibleSlideIndex,
211 const sal_Int32 nLastVisibleSlideIndex)
212 {
213 if (nFirstVisibleSlideIndex > nLastVisibleSlideIndex || nFirstVisibleSlideIndex<0)
214 {
215 mnFirstVisibleSlideIndex = -1;
216 mnLastVisibleSlideIndex = -1;
217 }
218 else
219 {
220 mnFirstVisibleSlideIndex = nFirstVisibleSlideIndex;
221 mnLastVisibleSlideIndex = nLastVisibleSlideIndex;
222 }
223 if (mxSlides.is() && mnLastVisibleSlideIndex >= mxSlides->getCount())
224 mnLastVisibleSlideIndex = mxSlides->getCount() - 1;
225 }
226
AddPreviewCreationNotifyListener(const Reference<drawing::XSlidePreviewCacheListener> & rxListener)227 void PresenterPreviewCache::PresenterCacheContext::AddPreviewCreationNotifyListener (
228 const Reference<drawing::XSlidePreviewCacheListener>& rxListener)
229 {
230 maListeners.push_back(rxListener);
231 }
232
RemovePreviewCreationNotifyListener(const Reference<drawing::XSlidePreviewCacheListener> & rxListener)233 void PresenterPreviewCache::PresenterCacheContext::RemovePreviewCreationNotifyListener (
234 const Reference<drawing::XSlidePreviewCacheListener>& rxListener)
235 {
236 auto iListener = std::find(maListeners.begin(), maListeners.end(), rxListener);
237 if (iListener != maListeners.end())
238 maListeners.erase(iListener);
239 }
240
241 //----- CacheContext ----------------------------------------------------------
242
NotifyPreviewCreation(CacheKey aKey)243 void PresenterPreviewCache::PresenterCacheContext::NotifyPreviewCreation (
244 CacheKey aKey)
245 {
246 if ( ! mxSlides.is())
247 return;
248 const sal_Int32 nCount(mxSlides->getCount());
249 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
250 if (aKey == GetPage(nIndex))
251 CallListeners(nIndex);
252 }
253
IsIdle()254 bool PresenterPreviewCache::PresenterCacheContext::IsIdle()
255 {
256 return true;
257 }
258
IsVisible(CacheKey aKey)259 bool PresenterPreviewCache::PresenterCacheContext::IsVisible (CacheKey aKey)
260 {
261 if (mnFirstVisibleSlideIndex < 0)
262 return false;
263 for (sal_Int32 nIndex=mnFirstVisibleSlideIndex; nIndex<=mnLastVisibleSlideIndex; ++nIndex)
264 {
265 const SdrPage* pPage = GetPage(nIndex);
266 if (pPage == aKey)
267 return true;
268 }
269 return false;
270 }
271
GetPage(CacheKey aKey)272 const SdrPage* PresenterPreviewCache::PresenterCacheContext::GetPage (CacheKey aKey)
273 {
274 return aKey;
275 }
276
277 std::shared_ptr<std::vector<CacheKey> >
GetEntryList(bool bVisible)278 PresenterPreviewCache::PresenterCacheContext::GetEntryList (bool bVisible)
279 {
280 std::shared_ptr<std::vector<CacheKey> > pKeys (new std::vector<CacheKey>);
281
282 if ( ! mxSlides.is())
283 return pKeys;
284
285 const sal_Int32 nFirstIndex (bVisible ? mnFirstVisibleSlideIndex : 0);
286 const sal_Int32 nLastIndex (bVisible ? mnLastVisibleSlideIndex : mxSlides->getCount()-1);
287
288 if (nFirstIndex < 0)
289 return pKeys;
290
291 for (sal_Int32 nIndex=nFirstIndex; nIndex<=nLastIndex; ++nIndex)
292 {
293 pKeys->push_back(GetPage(nIndex));
294 }
295
296 return pKeys;
297 }
298
GetPriority(CacheKey aKey)299 sal_Int32 PresenterPreviewCache::PresenterCacheContext::GetPriority (CacheKey aKey)
300 {
301 if ( ! mxSlides.is())
302 return 0;
303
304 const sal_Int32 nCount (mxSlides->getCount());
305
306 for (sal_Int32 nIndex=mnFirstVisibleSlideIndex; nIndex<=mnLastVisibleSlideIndex; ++nIndex)
307 if (aKey == GetPage(nIndex))
308 return -nCount-1+nIndex;
309
310 for (sal_Int32 nIndex=0; nIndex<=nCount; ++nIndex)
311 if (aKey == GetPage(nIndex))
312 return nIndex;
313
314 return 0;
315 }
316
GetModel()317 Reference<XInterface> PresenterPreviewCache::PresenterCacheContext::GetModel()
318 {
319 return mxDocument;
320 }
321
GetPage(const sal_Int32 nSlideIndex) const322 const SdrPage* PresenterPreviewCache::PresenterCacheContext::GetPage (
323 const sal_Int32 nSlideIndex) const
324 {
325 if ( ! mxSlides.is())
326 return nullptr;
327 if (nSlideIndex < 0 || nSlideIndex >= mxSlides->getCount())
328 return nullptr;
329
330 Reference<drawing::XDrawPage> xSlide (mxSlides->getByIndex(nSlideIndex), UNO_QUERY);
331 const SdPage* pPage = SdPage::getImplementation(xSlide);
332 return dynamic_cast<const SdrPage*>(pPage);
333 }
334
CallListeners(const sal_Int32 nIndex)335 void PresenterPreviewCache::PresenterCacheContext::CallListeners (
336 const sal_Int32 nIndex)
337 {
338 ListenerContainer aListeners (maListeners);
339 for (const auto& rxListener : aListeners)
340 {
341 try
342 {
343 rxListener->notifyPreviewCreation(nIndex);
344 }
345 catch (lang::DisposedException&)
346 {
347 RemovePreviewCreationNotifyListener(rxListener);
348 }
349 }
350 }
351
352 } } // end of namespace ::sd::presenter
353
354
355 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_Draw_PresenterPreviewCache_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)356 com_sun_star_comp_Draw_PresenterPreviewCache_get_implementation(css::uno::XComponentContext*,
357 css::uno::Sequence<css::uno::Any> const &)
358 {
359 return cppu::acquire(new sd::presenter::PresenterPreviewCache);
360 }
361
362
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
364