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 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 { 143 return mxViewId; 144 } 145 146 147 148 149 sal_Bool SAL_CALL PresenterSlidePreview::isAnchorOnly (void) 150 { 151 return false; 152 } 153 154 155 156 157 //----- XWindowListener ------------------------------------------------------- 158 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 171 void SAL_CALL PresenterSlidePreview::windowMoved (const awt::WindowEvent& rEvent) 172 { 173 (void)rEvent; 174 } 175 176 177 178 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 190 void SAL_CALL PresenterSlidePreview::windowHidden (const lang::EventObject& rEvent) 191 { 192 (void)rEvent; 193 } 194 195 196 197 198 //----- XPaintListener -------------------------------------------------------- 199 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 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 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 243 Reference<drawing::XDrawPage> SAL_CALL PresenterSlidePreview::getCurrentPage (void) 244 { 245 ThrowIfDisposed(); 246 return NULL; 247 } 248 249 250 251 252 //----------------------------------------------------------------------------- 253 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 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 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 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