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