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 
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 
114 PresenterSlidePreview::~PresenterSlidePreview (void)
115 {
116 }
117 
118 
119 
120 
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 
141 Reference<XResourceId> SAL_CALL PresenterSlidePreview::getResourceId (void)
142     throw (RuntimeException)
143 {
144     return mxViewId;
145 }
146 
147 
148 
149 
150 sal_Bool SAL_CALL PresenterSlidePreview::isAnchorOnly (void)
151     throw (RuntimeException)
152 {
153     return false;
154 }
155 
156 
157 
158 
159 //----- XWindowListener -------------------------------------------------------
160 
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 
174 void SAL_CALL PresenterSlidePreview::windowMoved (const awt::WindowEvent& rEvent)
175     throw (RuntimeException)
176 {
177     (void)rEvent;
178 }
179 
180 
181 
182 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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