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