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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26
27 #include "PresenterSlidePreview.hxx"
28 #include "PresenterCanvasHelper.hxx"
29 #include "PresenterGeometryHelper.hxx"
30 #include "PresenterPaintManager.hxx"
31 #include <com/sun/star/awt/XWindow.hpp>
32 #include <com/sun/star/awt/XWindowPeer.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
35 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
36 #include <com/sun/star/drawing/framework/XPane.hpp>
37 #include <com/sun/star/rendering/CompositeOperation.hpp>
38
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::drawing::framework;
42 using ::rtl::OUString;
43
44 namespace
45 {
46 // Use a super sample factor greater than 1 to achive a poor mans
47 // antialiasing effect for slide previews.
48 const sal_Int16 gnSuperSampleFactor = 2;
49 }
50
51 namespace sdext { namespace presenter {
52
53 //===== PresenterSlidePreview =================================================
54
PresenterSlidePreview(const Reference<XComponentContext> & rxContext,const Reference<XResourceId> & rxViewId,const Reference<XPane> & rxAnchorPane,const::rtl::Reference<PresenterController> & rpPresenterController)55 PresenterSlidePreview::PresenterSlidePreview (
56 const Reference<XComponentContext>& rxContext,
57 const Reference<XResourceId>& rxViewId,
58 const Reference<XPane>& rxAnchorPane,
59 const ::rtl::Reference<PresenterController>& rpPresenterController)
60 : PresenterSlidePreviewInterfaceBase(m_aMutex),
61 mpPresenterController(rpPresenterController),
62 mxPane(rxAnchorPane),
63 mxViewId(rxViewId),
64 mxPreviewRenderer(),
65 mxPreview(),
66 mxCurrentSlide(),
67 mnSlideAspectRatio(28.0 / 21.0),
68 mxWindow(),
69 mxCanvas()
70 {
71 if ( ! rxContext.is()
72 || ! rxViewId.is()
73 || ! rxAnchorPane.is()
74 || ! rpPresenterController.is())
75 {
76 throw RuntimeException(
77 OUString::createFromAscii(
78 "PresenterSlidePreview can not be constructed due to empty argument"),
79 static_cast<XWeak*>(this));
80 }
81
82 mxWindow = rxAnchorPane->getWindow();
83 mxCanvas = rxAnchorPane->getCanvas();
84
85 if (mxWindow.is())
86 {
87 mxWindow->addWindowListener(this);
88 mxWindow->addPaintListener(this);
89
90 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
91 if (xPeer.is())
92 xPeer->setBackground(util::Color(0xff000000));
93
94 mxWindow->setVisible(sal_True);
95 }
96
97 if (mpPresenterController.get() != NULL)
98 mnSlideAspectRatio = mpPresenterController->GetSlideAspectRatio();
99
100 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager(), UNO_QUERY);
101 if (xFactory.is())
102 mxPreviewRenderer = Reference<drawing::XSlideRenderer>(
103 xFactory->createInstanceWithContext(
104 OUString::createFromAscii("com.sun.star.drawing.SlideRenderer"),
105 rxContext),
106 UNO_QUERY);
107
108 Resize();
109 }
110
111
112
113
~PresenterSlidePreview(void)114 PresenterSlidePreview::~PresenterSlidePreview (void)
115 {
116 }
117
118
119
120
disposing(void)121 void SAL_CALL PresenterSlidePreview::disposing (void)
122 {
123 if (mxWindow.is())
124 {
125 mxWindow->removeWindowListener(this);
126 mxWindow->removePaintListener(this);
127 mxWindow = NULL;
128 mxCanvas = NULL;
129 }
130
131 Reference<lang::XComponent> xComponent (mxPreviewRenderer, UNO_QUERY);
132 if (xComponent.is())
133 xComponent->dispose();
134 }
135
136
137
138
139 //----- XResourceId -----------------------------------------------------------
140
getResourceId(void)141 Reference<XResourceId> SAL_CALL PresenterSlidePreview::getResourceId (void)
142 throw (RuntimeException)
143 {
144 return mxViewId;
145 }
146
147
148
149
isAnchorOnly(void)150 sal_Bool SAL_CALL PresenterSlidePreview::isAnchorOnly (void)
151 throw (RuntimeException)
152 {
153 return false;
154 }
155
156
157
158
159 //----- XWindowListener -------------------------------------------------------
160
windowResized(const awt::WindowEvent & rEvent)161 void SAL_CALL PresenterSlidePreview::windowResized (const awt::WindowEvent& rEvent)
162 throw (RuntimeException)
163 {
164 (void)rEvent;
165 ThrowIfDisposed();
166 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
167 Resize();
168 }
169
170
171
172
173
windowMoved(const awt::WindowEvent & rEvent)174 void SAL_CALL PresenterSlidePreview::windowMoved (const awt::WindowEvent& rEvent)
175 throw (RuntimeException)
176 {
177 (void)rEvent;
178 }
179
180
181
182
windowShown(const lang::EventObject & rEvent)183 void SAL_CALL PresenterSlidePreview::windowShown (const lang::EventObject& rEvent)
184 throw (RuntimeException)
185 {
186 (void)rEvent;
187 ThrowIfDisposed();
188 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
189 Resize();
190 }
191
192
193
194
windowHidden(const lang::EventObject & rEvent)195 void SAL_CALL PresenterSlidePreview::windowHidden (const lang::EventObject& rEvent)
196 throw (RuntimeException)
197 {
198 (void)rEvent;
199 }
200
201
202
203
204 //----- XPaintListener --------------------------------------------------------
205
windowPaint(const awt::PaintEvent & rEvent)206 void SAL_CALL PresenterSlidePreview::windowPaint (const awt::PaintEvent& rEvent)
207 throw (RuntimeException)
208 {
209 ThrowIfDisposed();
210
211 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
212 if (mxWindow.is())
213 Paint(awt::Rectangle(
214 rEvent.UpdateRect.X,
215 rEvent.UpdateRect.Y,
216 rEvent.UpdateRect.Width,
217 rEvent.UpdateRect.Height));
218 }
219
220
221
222
223 //----- lang::XEventListener --------------------------------------------------
224
disposing(const lang::EventObject & rEvent)225 void SAL_CALL PresenterSlidePreview::disposing (const lang::EventObject& rEvent)
226 throw (RuntimeException)
227 {
228 if (rEvent.Source == mxWindow)
229 {
230 mxWindow = NULL;
231 mxCanvas = NULL;
232 mxPreview = NULL;
233 }
234 }
235
236
237
238
239 //----- XDrawView -------------------------------------------------------------
240
setCurrentPage(const Reference<drawing::XDrawPage> & rxSlide)241 void SAL_CALL PresenterSlidePreview::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
242 throw (RuntimeException)
243 {
244 ThrowIfDisposed();
245 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
246 SetSlide(rxSlide);
247 }
248
249
250
251
getCurrentPage(void)252 Reference<drawing::XDrawPage> SAL_CALL PresenterSlidePreview::getCurrentPage (void)
253 throw (RuntimeException)
254 {
255 ThrowIfDisposed();
256 return NULL;
257 }
258
259
260
261
262 //-----------------------------------------------------------------------------
263
SetSlide(const Reference<drawing::XDrawPage> & rxPage)264 void PresenterSlidePreview::SetSlide (const Reference<drawing::XDrawPage>& rxPage)
265 {
266 mxCurrentSlide = rxPage;
267 mxPreview = NULL;
268
269 Reference<beans::XPropertySet> xPropertySet (mxCurrentSlide, UNO_QUERY);
270 if (xPropertySet.is())
271 {
272 awt::Size aSlideSize;
273 try
274 {
275 xPropertySet->getPropertyValue(
276 OUString::createFromAscii("Width")) >>= aSlideSize.Width;
277 xPropertySet->getPropertyValue(
278 OUString::createFromAscii("Height")) >>= aSlideSize.Height;
279 }
280 catch (beans::UnknownPropertyException&)
281 {
282 OSL_ASSERT(false);
283 }
284 }
285
286 // The preview is not transparent, therefore only this window, not its
287 // parent, has to be invalidated.
288 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
289 }
290
291
292
293
Paint(const awt::Rectangle & rBoundingBox)294 void PresenterSlidePreview::Paint (const awt::Rectangle& rBoundingBox)
295 {
296 (void)rBoundingBox;
297 if ( ! mxWindow.is())
298 return;
299 if ( ! mxCanvas.is())
300 return;
301 if ( ! mxPreviewRenderer.is())
302 return;
303
304 // Make sure that a preview in the correct size exists.
305 awt::Rectangle aWindowBox (mxWindow->getPosSize());
306
307 if ( ! mxPreview.is() && mxCurrentSlide.is())
308 {
309 // Create a new preview bitmap.
310 mxPreview = mxPreviewRenderer->createPreviewForCanvas(
311 mxCurrentSlide,
312 awt::Size(aWindowBox.Width, aWindowBox.Height),
313 gnSuperSampleFactor,
314 mxCanvas);
315 }
316
317 // Determine the bounding box of the preview.
318 awt::Rectangle aPreviewBox;
319 if (mxPreview.is())
320 {
321 const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize());
322 aPreviewBox = awt::Rectangle(
323 (aWindowBox.Width - aPreviewSize.Width)/2,
324 (aWindowBox.Height - aPreviewSize.Height)/2,
325 aPreviewSize.Width,
326 aPreviewSize.Height);
327 }
328 else
329 {
330 if (mnSlideAspectRatio > 0)
331 {
332 const awt::Size aPreviewSize (mxPreviewRenderer->calculatePreviewSize(
333 mnSlideAspectRatio,awt::Size(aWindowBox.Width, aWindowBox.Height)));
334 aPreviewBox = awt::Rectangle(
335 (aWindowBox.Width - aPreviewSize.Width)/2,
336 (aWindowBox.Height - aPreviewSize.Height)/2,
337 aPreviewSize.Width,
338 aPreviewSize.Height);
339 }
340 }
341
342 // Paint the background.
343 mpPresenterController->GetCanvasHelper()->Paint(
344 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
345 mxCanvas,
346 rBoundingBox,
347 awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
348 aPreviewBox);
349
350 // Paint the preview.
351 const rendering::ViewState aViewState(
352 geometry::AffineMatrix2D(1,0,0, 0,1,0),
353 NULL);
354
355 Sequence<double> aBackgroundColor(4);
356 rendering::RenderState aRenderState (
357 geometry::AffineMatrix2D(1, 0, aPreviewBox.X, 0, 1, aPreviewBox.Y),
358 NULL,
359 aBackgroundColor,
360 rendering::CompositeOperation::SOURCE);
361 PresenterCanvasHelper::SetDeviceColor(aRenderState, 0x00000000);
362 if (mxPreview.is())
363 {
364 mxCanvas->drawBitmap(mxPreview, aViewState, aRenderState);
365 }
366 else
367 {
368 if (mnSlideAspectRatio > 0)
369 {
370 Reference<rendering::XPolyPolygon2D> xPolygon (
371 PresenterGeometryHelper::CreatePolygon(aPreviewBox, mxCanvas->getDevice()));
372 if (xPolygon.is())
373 mxCanvas->fillPolyPolygon(xPolygon, aViewState, aRenderState);
374 }
375 }
376
377 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
378 if (xSpriteCanvas.is())
379 xSpriteCanvas->updateScreen(sal_False);
380 }
381
382
383
384
Resize(void)385 void PresenterSlidePreview::Resize (void)
386 {
387 if (mxPreviewRenderer.is() && mxPreview.is())
388 {
389 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
390 const awt::Size aNewPreviewSize (mxPreviewRenderer->calculatePreviewSize(
391 mnSlideAspectRatio,
392 awt::Size(aWindowBox.Width, aWindowBox.Height)));
393 const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize());
394 if (aNewPreviewSize.Width==aPreviewSize.Width
395 && aNewPreviewSize.Height==aPreviewSize.Height)
396 {
397 // The size of the window may have changed but the preview would
398 // be painted in the same size (but not necessarily at the same
399 // position.)
400 return;
401 }
402 }
403 SetSlide(mxCurrentSlide);
404 }
405
406
407
408
ThrowIfDisposed(void)409 void PresenterSlidePreview::ThrowIfDisposed (void)
410 throw (::com::sun::star::lang::DisposedException)
411 {
412 if (PresenterSlidePreviewInterfaceBase::rBHelper.bDisposed || PresenterSlidePreviewInterfaceBase::rBHelper.bInDispose)
413 {
414 throw lang::DisposedException (
415 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
416 "PresenterSlidePreview object has already been disposed")),
417 static_cast<uno::XWeak*>(this));
418 }
419 }
420
421
422 } } // end of namespace ::sd::presenter
423
424