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 achieve 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 {
143 return mxViewId;
144 }
145
146
147
148
isAnchorOnly(void)149 sal_Bool SAL_CALL PresenterSlidePreview::isAnchorOnly (void)
150 {
151 return false;
152 }
153
154
155
156
157 //----- XWindowListener -------------------------------------------------------
158
windowResized(const awt::WindowEvent & rEvent)159 void SAL_CALL PresenterSlidePreview::windowResized (const awt::WindowEvent& rEvent)
160 {
161 (void)rEvent;
162 ThrowIfDisposed();
163 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
164 Resize();
165 }
166
167
168
169
170
windowMoved(const awt::WindowEvent & rEvent)171 void SAL_CALL PresenterSlidePreview::windowMoved (const awt::WindowEvent& rEvent)
172 {
173 (void)rEvent;
174 }
175
176
177
178
windowShown(const lang::EventObject & rEvent)179 void SAL_CALL PresenterSlidePreview::windowShown (const lang::EventObject& rEvent)
180 {
181 (void)rEvent;
182 ThrowIfDisposed();
183 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
184 Resize();
185 }
186
187
188
189
windowHidden(const lang::EventObject & rEvent)190 void SAL_CALL PresenterSlidePreview::windowHidden (const lang::EventObject& rEvent)
191 {
192 (void)rEvent;
193 }
194
195
196
197
198 //----- XPaintListener --------------------------------------------------------
199
windowPaint(const awt::PaintEvent & rEvent)200 void SAL_CALL PresenterSlidePreview::windowPaint (const awt::PaintEvent& rEvent)
201 {
202 ThrowIfDisposed();
203
204 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
205 if (mxWindow.is())
206 Paint(awt::Rectangle(
207 rEvent.UpdateRect.X,
208 rEvent.UpdateRect.Y,
209 rEvent.UpdateRect.Width,
210 rEvent.UpdateRect.Height));
211 }
212
213
214
215
216 //----- lang::XEventListener --------------------------------------------------
217
disposing(const lang::EventObject & rEvent)218 void SAL_CALL PresenterSlidePreview::disposing (const lang::EventObject& rEvent)
219 {
220 if (rEvent.Source == mxWindow)
221 {
222 mxWindow = NULL;
223 mxCanvas = NULL;
224 mxPreview = NULL;
225 }
226 }
227
228
229
230
231 //----- XDrawView -------------------------------------------------------------
232
setCurrentPage(const Reference<drawing::XDrawPage> & rxSlide)233 void SAL_CALL PresenterSlidePreview::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
234 {
235 ThrowIfDisposed();
236 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
237 SetSlide(rxSlide);
238 }
239
240
241
242
getCurrentPage(void)243 Reference<drawing::XDrawPage> SAL_CALL PresenterSlidePreview::getCurrentPage (void)
244 {
245 ThrowIfDisposed();
246 return NULL;
247 }
248
249
250
251
252 //-----------------------------------------------------------------------------
253
SetSlide(const Reference<drawing::XDrawPage> & rxPage)254 void PresenterSlidePreview::SetSlide (const Reference<drawing::XDrawPage>& rxPage)
255 {
256 mxCurrentSlide = rxPage;
257 mxPreview = NULL;
258
259 Reference<beans::XPropertySet> xPropertySet (mxCurrentSlide, UNO_QUERY);
260 if (xPropertySet.is())
261 {
262 awt::Size aSlideSize;
263 try
264 {
265 xPropertySet->getPropertyValue(
266 OUString::createFromAscii("Width")) >>= aSlideSize.Width;
267 xPropertySet->getPropertyValue(
268 OUString::createFromAscii("Height")) >>= aSlideSize.Height;
269 }
270 catch (beans::UnknownPropertyException&)
271 {
272 OSL_ASSERT(false);
273 }
274 }
275
276 // The preview is not transparent, therefore only this window, not its
277 // parent, has to be invalidated.
278 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
279 }
280
281
282
283
Paint(const awt::Rectangle & rBoundingBox)284 void PresenterSlidePreview::Paint (const awt::Rectangle& rBoundingBox)
285 {
286 (void)rBoundingBox;
287 if ( ! mxWindow.is())
288 return;
289 if ( ! mxCanvas.is())
290 return;
291 if ( ! mxPreviewRenderer.is())
292 return;
293
294 // Make sure that a preview in the correct size exists.
295 awt::Rectangle aWindowBox (mxWindow->getPosSize());
296
297 if ( ! mxPreview.is() && mxCurrentSlide.is())
298 {
299 // Create a new preview bitmap.
300 mxPreview = mxPreviewRenderer->createPreviewForCanvas(
301 mxCurrentSlide,
302 awt::Size(aWindowBox.Width, aWindowBox.Height),
303 gnSuperSampleFactor,
304 mxCanvas);
305 }
306
307 // Determine the bounding box of the preview.
308 awt::Rectangle aPreviewBox;
309 if (mxPreview.is())
310 {
311 const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize());
312 aPreviewBox = awt::Rectangle(
313 (aWindowBox.Width - aPreviewSize.Width)/2,
314 (aWindowBox.Height - aPreviewSize.Height)/2,
315 aPreviewSize.Width,
316 aPreviewSize.Height);
317 }
318 else
319 {
320 if (mnSlideAspectRatio > 0)
321 {
322 const awt::Size aPreviewSize (mxPreviewRenderer->calculatePreviewSize(
323 mnSlideAspectRatio,awt::Size(aWindowBox.Width, aWindowBox.Height)));
324 aPreviewBox = awt::Rectangle(
325 (aWindowBox.Width - aPreviewSize.Width)/2,
326 (aWindowBox.Height - aPreviewSize.Height)/2,
327 aPreviewSize.Width,
328 aPreviewSize.Height);
329 }
330 }
331
332 // Paint the background.
333 mpPresenterController->GetCanvasHelper()->Paint(
334 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
335 mxCanvas,
336 rBoundingBox,
337 awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
338 aPreviewBox);
339
340 // Paint the preview.
341 const rendering::ViewState aViewState(
342 geometry::AffineMatrix2D(1,0,0, 0,1,0),
343 NULL);
344
345 Sequence<double> aBackgroundColor(4);
346 rendering::RenderState aRenderState (
347 geometry::AffineMatrix2D(1, 0, aPreviewBox.X, 0, 1, aPreviewBox.Y),
348 NULL,
349 aBackgroundColor,
350 rendering::CompositeOperation::SOURCE);
351 PresenterCanvasHelper::SetDeviceColor(aRenderState, 0x00000000);
352 if (mxPreview.is())
353 {
354 mxCanvas->drawBitmap(mxPreview, aViewState, aRenderState);
355 }
356 else
357 {
358 if (mnSlideAspectRatio > 0)
359 {
360 Reference<rendering::XPolyPolygon2D> xPolygon (
361 PresenterGeometryHelper::CreatePolygon(aPreviewBox, mxCanvas->getDevice()));
362 if (xPolygon.is())
363 mxCanvas->fillPolyPolygon(xPolygon, aViewState, aRenderState);
364 }
365 }
366
367 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
368 if (xSpriteCanvas.is())
369 xSpriteCanvas->updateScreen(sal_False);
370 }
371
372
373
374
Resize(void)375 void PresenterSlidePreview::Resize (void)
376 {
377 if (mxPreviewRenderer.is() && mxPreview.is())
378 {
379 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
380 const awt::Size aNewPreviewSize (mxPreviewRenderer->calculatePreviewSize(
381 mnSlideAspectRatio,
382 awt::Size(aWindowBox.Width, aWindowBox.Height)));
383 const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize());
384 if (aNewPreviewSize.Width==aPreviewSize.Width
385 && aNewPreviewSize.Height==aPreviewSize.Height)
386 {
387 // The size of the window may have changed but the preview would
388 // be painted in the same size (but not necessarily at the same
389 // position.)
390 return;
391 }
392 }
393 SetSlide(mxCurrentSlide);
394 }
395
396
397
398
ThrowIfDisposed(void)399 void PresenterSlidePreview::ThrowIfDisposed (void)
400 {
401 if (PresenterSlidePreviewInterfaceBase::rBHelper.bDisposed || PresenterSlidePreviewInterfaceBase::rBHelper.bInDispose)
402 {
403 throw lang::DisposedException (
404 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
405 "PresenterSlidePreview object has already been disposed")),
406 static_cast<uno::XWeak*>(this));
407 }
408 }
409
410
411 } } // end of namespace ::sd::presenter
412