1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svx.hxx" 30 #include <svx/sdr/contact/objectcontactofpageview.hxx> 31 #include <svx/sdr/contact/viewobjectcontactofunocontrol.hxx> 32 #include <svx/svdpagv.hxx> 33 #include <svx/svdpage.hxx> 34 #include <svx/sdr/contact/displayinfo.hxx> 35 #include <svx/sdr/contact/viewobjectcontact.hxx> 36 #include <svx/svdview.hxx> 37 #include <svx/sdr/contact/viewcontact.hxx> 38 #include <svx/sdr/animation/objectanimator.hxx> 39 #include <svx/sdr/event/eventhandler.hxx> 40 #include <svx/sdrpagewindow.hxx> 41 #include <svx/sdrpaintwindow.hxx> 42 #include <drawinglayer/processor2d/vclprocessor2d.hxx> 43 #include <basegfx/matrix/b2dhommatrix.hxx> 44 #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 45 #include <svx/sdr/contact/objectcontacttools.hxx> 46 #include <com/sun/star/rendering/XSpriteCanvas.hpp> 47 #include <svx/unoapi.hxx> 48 49 ////////////////////////////////////////////////////////////////////////////// 50 51 using namespace com::sun::star; 52 53 ////////////////////////////////////////////////////////////////////////////// 54 55 namespace sdr 56 { 57 namespace contact 58 { 59 // internal access to SdrPage of SdrPageView 60 SdrPage* ObjectContactOfPageView::GetSdrPage() const 61 { 62 return GetPageWindow().GetPageView().GetPage(); 63 } 64 65 ObjectContactOfPageView::ObjectContactOfPageView(SdrPageWindow& rPageWindow) 66 : ObjectContact(), 67 mrPageWindow(rPageWindow) 68 { 69 // init PreviewRenderer flag 70 setPreviewRenderer(((SdrPaintView&)rPageWindow.GetPageView().GetView()).IsPreviewRenderer()); 71 72 // init timer 73 SetTimeout(1); 74 Stop(); 75 } 76 77 ObjectContactOfPageView::~ObjectContactOfPageView() 78 { 79 // execute missing LazyInvalidates and stop timer 80 Timeout(); 81 } 82 83 // LazyInvalidate request. Take action. 84 void ObjectContactOfPageView::setLazyInvalidate(ViewObjectContact& /*rVOC*/) 85 { 86 // do NOT call parent, but remember that something is to do by 87 // starting the LazyInvalidateTimer 88 Start(); 89 } 90 91 // call this to support evtl. preparations for repaint 92 void ObjectContactOfPageView::PrepareProcessDisplay() 93 { 94 if(IsActive()) 95 { 96 static bool bInvalidateDuringPaint(true); 97 98 if(bInvalidateDuringPaint) 99 { 100 // there are still non-triggered LazyInvalidate events, trigger these 101 Timeout(); 102 } 103 } 104 } 105 106 // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism 107 void ObjectContactOfPageView::Timeout() 108 { 109 // stop the timer 110 Stop(); 111 112 // invalidate all LazyInvalidate VOCs new situations 113 const sal_uInt32 nVOCCount(getViewObjectContactCount()); 114 115 for(sal_uInt32 a(0); a < nVOCCount; a++) 116 { 117 ViewObjectContact* pCandidate = getViewObjectContact(a); 118 pCandidate->triggerLazyInvalidate(); 119 } 120 } 121 122 // Process the whole displaying 123 void ObjectContactOfPageView::ProcessDisplay(DisplayInfo& rDisplayInfo) 124 { 125 const SdrPage* pStartPage = GetSdrPage(); 126 127 if(pStartPage && !rDisplayInfo.GetProcessLayers().IsEmpty()) 128 { 129 const ViewContact& rDrawPageVC = pStartPage->GetViewContact(); 130 131 if(rDrawPageVC.GetObjectCount()) 132 { 133 DoProcessDisplay(rDisplayInfo); 134 } 135 } 136 137 // after paint take care of the evtl. scheduled asynchronious commands. 138 // Do this by resetting the timer contained there. Thus, after the paint 139 // that timer will be triggered and the events will be executed. 140 if(HasEventHandler()) 141 { 142 sdr::event::TimerEventHandler& rEventHandler = GetEventHandler(); 143 144 if(!rEventHandler.IsEmpty()) 145 { 146 rEventHandler.Restart(); 147 } 148 } 149 } 150 151 // Process the whole displaying. Only use given DsiplayInfo, do not access other 152 // OutputDevices then the given ones. 153 void ObjectContactOfPageView::DoProcessDisplay(DisplayInfo& rDisplayInfo) 154 { 155 // visualize entered group when that feature is switched on and it's not 156 // a print output. #i29129# No ghosted display for printing. 157 sal_Bool bVisualizeEnteredGroup(DoVisualizeEnteredGroup() && !isOutputToPrinter()); 158 159 // Visualize entered groups: Set to ghosted as default 160 // start. Do this only for the DrawPage, not for MasterPages 161 if(bVisualizeEnteredGroup) 162 { 163 rDisplayInfo.SetGhostedDrawMode(); 164 } 165 166 // #114359# save old and set clip region 167 OutputDevice* pOutDev = TryToGetOutputDevice(); 168 OSL_ENSURE(0 != pOutDev, "ObjectContactOfPageView without OutDev, someone has overloaded TryToGetOutputDevice wrong (!)"); 169 sal_Bool bClipRegionPushed(sal_False); 170 const Region& rRedrawArea(rDisplayInfo.GetRedrawArea()); 171 172 if(!rRedrawArea.IsEmpty()) 173 { 174 bClipRegionPushed = sal_True; 175 pOutDev->Push(PUSH_CLIPREGION); 176 pOutDev->IntersectClipRegion(rRedrawArea); 177 } 178 179 // Get start node and process DrawPage contents 180 const ViewObjectContact& rDrawPageVOContact = GetSdrPage()->GetViewContact().GetViewObjectContact(*this); 181 182 // update current ViewInformation2D at the ObjectContact 183 const double fCurrentTime(getPrimitiveAnimator().GetTime()); 184 OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice(); 185 basegfx::B2DRange aViewRange; 186 187 // create ViewRange 188 if(isOutputToRecordingMetaFile()) 189 { 190 if(isOutputToPDFFile() || isOutputToPrinter()) 191 { 192 // #i98402# if it's a PDF export, set the ClipRegion as ViewRange. This is 193 // mainly because SW does not use DrawingLayer Page-Oriented and if not doing this, 194 // all existing objects will be collected as primitives and processed. 195 // OD 2009-03-05 #i99876# perform the same also for SW on printing. 196 const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect()); 197 198 aViewRange = basegfx::B2DRange( 199 aLogicClipRectangle.Left(), aLogicClipRectangle.Top(), 200 aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom()); 201 } 202 } 203 else 204 { 205 // use visible pixels, but transform to world coordinates 206 const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel()); 207 aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight()); 208 209 // if a clip region is set, use it 210 if(!rDisplayInfo.GetRedrawArea().IsEmpty()) 211 { 212 // get logic clip range and create discrete one 213 const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect()); 214 basegfx::B2DRange aLogicClipRange( 215 aLogicClipRectangle.Left(), aLogicClipRectangle.Top(), 216 aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom()); 217 basegfx::B2DRange aDiscreteClipRange(aLogicClipRange); 218 aDiscreteClipRange.transform(rTargetOutDev.GetViewTransformation()); 219 220 // align the discrete one to discrete boundaries (pixel bounds). Also 221 // expand X and Y max by one due to Rectangle definition source 222 aDiscreteClipRange.expand(basegfx::B2DTuple( 223 floor(aDiscreteClipRange.getMinX()), 224 floor(aDiscreteClipRange.getMinY()))); 225 aDiscreteClipRange.expand(basegfx::B2DTuple( 226 1.0 + ceil(aDiscreteClipRange.getMaxX()), 227 1.0 + ceil(aDiscreteClipRange.getMaxY()))); 228 229 // intersect current ViewRange with ClipRange 230 aViewRange.intersect(aDiscreteClipRange); 231 } 232 233 // transform to world coordinates 234 aViewRange.transform(rTargetOutDev.GetInverseViewTransformation()); 235 } 236 237 // update local ViewInformation2D 238 const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D( 239 basegfx::B2DHomMatrix(), 240 rTargetOutDev.GetViewTransformation(), 241 aViewRange, 242 GetXDrawPageForSdrPage(GetSdrPage()), 243 fCurrentTime, 244 uno::Sequence<beans::PropertyValue>()); 245 updateViewInformation2D(aNewViewInformation2D); 246 247 // get whole Primitive2DSequence; this will already make use of updated ViewInformation2D 248 // and may use the MapMode from the Target OutDev in the DisplayInfo 249 drawinglayer::primitive2d::Primitive2DSequence xPrimitiveSequence(rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo)); 250 251 // if there is something to show, use a primitive processor to render it. There 252 // is a choice between VCL and Canvas processors currently. The decision is made in 253 // createBaseProcessor2DFromOutputDevice and takes into accout things like the 254 // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered 255 // currently using the shown boolean. Canvas is not yet the default. 256 if(xPrimitiveSequence.hasElements()) 257 { 258 // prepare OutputDevice (historical stuff, maybe soon removed) 259 rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing 260 pOutDev->SetLayoutMode(0); // reset, default is no BiDi/RTL 261 262 // create renderer 263 drawinglayer::processor2d::BaseProcessor2D* pProcessor2D = createBaseProcessor2DFromOutputDevice( 264 rTargetOutDev, getViewInformation2D()); 265 266 if(pProcessor2D) 267 { 268 pProcessor2D->process(xPrimitiveSequence); 269 delete pProcessor2D; 270 } 271 } 272 273 // #114359# restore old ClipReghion 274 if(bClipRegionPushed) 275 { 276 pOutDev->Pop(); 277 } 278 279 // Visualize entered groups: Reset to original DrawMode 280 if(bVisualizeEnteredGroup) 281 { 282 rDisplayInfo.ClearGhostedDrawMode(); 283 } 284 } 285 286 // test if visualizing of entered groups is switched on at all 287 bool ObjectContactOfPageView::DoVisualizeEnteredGroup() const 288 { 289 SdrView& rView = GetPageWindow().GetPageView().GetView(); 290 return rView.DoVisualizeEnteredGroup(); 291 } 292 293 // get active group's (the entered group) ViewContact 294 const ViewContact* ObjectContactOfPageView::getActiveViewContact() const 295 { 296 SdrObjList* pActiveGroupList = GetPageWindow().GetPageView().GetObjList(); 297 298 if(pActiveGroupList) 299 { 300 if(pActiveGroupList->ISA(SdrPage)) 301 { 302 // It's a Page itself 303 return &(((SdrPage*)pActiveGroupList)->GetViewContact()); 304 } 305 else if(pActiveGroupList->GetOwnerObj()) 306 { 307 // Group object 308 return &(pActiveGroupList->GetOwnerObj()->GetViewContact()); 309 } 310 } 311 else if(GetSdrPage()) 312 { 313 // use page of associated SdrPageView 314 return &(GetSdrPage()->GetViewContact()); 315 } 316 317 return 0; 318 } 319 320 // Invalidate given rectangle at the window/output which is represented by 321 // this ObjectContact. 322 void ObjectContactOfPageView::InvalidatePartOfView(const basegfx::B2DRange& rRange) const 323 { 324 // invalidate at associated PageWindow 325 GetPageWindow().InvalidatePageWindow(rRange); 326 } 327 328 // Get info if given Rectangle is visible in this view 329 bool ObjectContactOfPageView::IsAreaVisible(const basegfx::B2DRange& rRange) const 330 { 331 // compare with the visible rectangle 332 if(rRange.isEmpty()) 333 { 334 // no range -> not visible 335 return false; 336 } 337 else 338 { 339 const OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice(); 340 const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel()); 341 basegfx::B2DRange aLogicViewRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight()); 342 343 aLogicViewRange.transform(rTargetOutDev.GetInverseViewTransformation()); 344 345 if(!aLogicViewRange.isEmpty() && !aLogicViewRange.overlaps(rRange)) 346 { 347 return false; 348 } 349 } 350 351 // call parent 352 return ObjectContact::IsAreaVisible(rRange); 353 } 354 355 // Get info about the need to visualize GluePoints 356 bool ObjectContactOfPageView::AreGluePointsVisible() const 357 { 358 return GetPageWindow().GetPageView().GetView().ImpIsGlueVisible(); 359 } 360 361 // check if text animation is allowed. 362 bool ObjectContactOfPageView::IsTextAnimationAllowed() const 363 { 364 SdrView& rView = GetPageWindow().GetPageView().GetView(); 365 const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions(); 366 return rOpt.GetIsAllowAnimatedText(); 367 } 368 369 // check if graphic animation is allowed. 370 bool ObjectContactOfPageView::IsGraphicAnimationAllowed() const 371 { 372 SdrView& rView = GetPageWindow().GetPageView().GetView(); 373 const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions(); 374 return rOpt.GetIsAllowAnimatedGraphics(); 375 } 376 377 // check if asynchronious graphis loading is allowed. Default is sal_False. 378 bool ObjectContactOfPageView::IsAsynchronGraphicsLoadingAllowed() const 379 { 380 SdrView& rView = GetPageWindow().GetPageView().GetView(); 381 return rView.IsSwapAsynchron(); 382 } 383 384 // check if buffering of MasterPages is allowed. Default is sal_False. 385 bool ObjectContactOfPageView::IsMasterPageBufferingAllowed() const 386 { 387 SdrView& rView = GetPageWindow().GetPageView().GetView(); 388 return rView.IsMasterPagePaintCaching(); 389 } 390 391 // print? 392 bool ObjectContactOfPageView::isOutputToPrinter() const 393 { 394 return (OUTDEV_PRINTER == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType()); 395 } 396 397 // window? 398 bool ObjectContactOfPageView::isOutputToWindow() const 399 { 400 return (OUTDEV_WINDOW == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType()); 401 } 402 403 // VirtualDevice? 404 bool ObjectContactOfPageView::isOutputToVirtualDevice() const 405 { 406 return (OUTDEV_VIRDEV == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType()); 407 } 408 409 // recording MetaFile? 410 bool ObjectContactOfPageView::isOutputToRecordingMetaFile() const 411 { 412 GDIMetaFile* pMetaFile = mrPageWindow.GetPaintWindow().GetOutputDevice().GetConnectMetaFile(); 413 return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause()); 414 } 415 416 // pdf export? 417 bool ObjectContactOfPageView::isOutputToPDFFile() const 418 { 419 return (0 != mrPageWindow.GetPaintWindow().GetOutputDevice().GetPDFWriter()); 420 } 421 422 // gray display mode 423 bool ObjectContactOfPageView::isDrawModeGray() const 424 { 425 const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode()); 426 return (nDrawMode == (DRAWMODE_GRAYLINE|DRAWMODE_GRAYFILL|DRAWMODE_BLACKTEXT|DRAWMODE_GRAYBITMAP|DRAWMODE_GRAYGRADIENT)); 427 } 428 429 // gray display mode 430 bool ObjectContactOfPageView::isDrawModeBlackWhite() const 431 { 432 const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode()); 433 return (nDrawMode == (DRAWMODE_BLACKLINE|DRAWMODE_BLACKTEXT|DRAWMODE_WHITEFILL|DRAWMODE_GRAYBITMAP|DRAWMODE_WHITEGRADIENT)); 434 } 435 436 // high contrast display mode 437 bool ObjectContactOfPageView::isDrawModeHighContrast() const 438 { 439 const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode()); 440 return (nDrawMode == (DRAWMODE_SETTINGSLINE|DRAWMODE_SETTINGSFILL|DRAWMODE_SETTINGSTEXT|DRAWMODE_SETTINGSGRADIENT)); 441 } 442 443 // access to SdrPageView 444 SdrPageView* ObjectContactOfPageView::TryToGetSdrPageView() const 445 { 446 return &(mrPageWindow.GetPageView()); 447 } 448 449 450 // access to OutputDevice 451 OutputDevice* ObjectContactOfPageView::TryToGetOutputDevice() const 452 { 453 SdrPreRenderDevice* pPreRenderDevice = mrPageWindow.GetPaintWindow().GetPreRenderDevice(); 454 455 if(pPreRenderDevice) 456 { 457 return &(pPreRenderDevice->GetPreRenderDevice()); 458 } 459 else 460 { 461 return &(mrPageWindow.GetPaintWindow().GetOutputDevice()); 462 } 463 } 464 465 // set all UNO controls displayed in the view to design/alive mode 466 void ObjectContactOfPageView::SetUNOControlsDesignMode( bool _bDesignMode ) const 467 { 468 const sal_uInt32 nCount(getViewObjectContactCount()); 469 470 for(sal_uInt32 a(0); a < nCount; a++) 471 { 472 const ViewObjectContact* pVOC = getViewObjectContact(a); 473 const ViewObjectContactOfUnoControl* pUnoObjectVOC = dynamic_cast< const ViewObjectContactOfUnoControl* >(pVOC); 474 475 if(pUnoObjectVOC) 476 { 477 pUnoObjectVOC->setControlDesignMode(_bDesignMode); 478 } 479 } 480 } 481 } // end of namespace contact 482 } // end of namespace sdr 483 484 ////////////////////////////////////////////////////////////////////////////// 485 // eof 486