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 <drawinglayer/processor2d/vclprocessor2d.hxx> 39 #include <basegfx/matrix/b2dhommatrix.hxx> 40 #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 41 #include <svx/sdr/contact/objectcontacttools.hxx> 42 #include <com/sun/star/rendering/XSpriteCanvas.hpp> 43 #include <svx/unoapi.hxx> 44 45 ////////////////////////////////////////////////////////////////////////////// 46 47 using namespace com::sun::star; 48 49 ////////////////////////////////////////////////////////////////////////////// 50 51 namespace sdr 52 { 53 namespace contact 54 { 55 // internal access to SdrPage of SdrPageView 56 SdrPage* ObjectContactOfPageView::GetSdrPage() const 57 { 58 return GetPageWindow().GetPageView().GetPage(); 59 } 60 61 ObjectContactOfPageView::ObjectContactOfPageView(SdrPageWindow& rPageWindow) 62 : ObjectContact(), 63 mrPageWindow(rPageWindow) 64 { 65 // init PreviewRenderer flag 66 setPreviewRenderer(((SdrPaintView&)rPageWindow.GetPageView().GetView()).IsPreviewRenderer()); 67 68 // init timer 69 SetTimeout(1); 70 Stop(); 71 } 72 73 ObjectContactOfPageView::~ObjectContactOfPageView() 74 { 75 // execute missing LazyInvalidates and stop timer 76 Timeout(); 77 } 78 79 // LazyInvalidate request. Take action. 80 void ObjectContactOfPageView::setLazyInvalidate(ViewObjectContact& /*rVOC*/) 81 { 82 // do NOT call parent, but remember that something is to do by 83 // starting the LazyInvalidateTimer 84 Start(); 85 } 86 87 // call this to support evtl. preparations for repaint 88 void ObjectContactOfPageView::PrepareProcessDisplay() 89 { 90 if(IsActive()) 91 { 92 static bool bInvalidateDuringPaint(true); 93 94 if(bInvalidateDuringPaint) 95 { 96 // there are still non-triggered LazyInvalidate events, trigger these 97 Timeout(); 98 } 99 } 100 } 101 102 // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism 103 void ObjectContactOfPageView::Timeout() 104 { 105 // stop the timer 106 Stop(); 107 108 // invalidate all LazyInvalidate VOCs new situations 109 const sal_uInt32 nVOCCount(getViewObjectContactCount()); 110 111 for(sal_uInt32 a(0); a < nVOCCount; a++) 112 { 113 ViewObjectContact* pCandidate = getViewObjectContact(a); 114 pCandidate->triggerLazyInvalidate(); 115 } 116 } 117 118 // Process the whole displaying 119 void ObjectContactOfPageView::ProcessDisplay(DisplayInfo& rDisplayInfo) 120 { 121 const SdrPage* pStartPage = GetSdrPage(); 122 123 if(pStartPage && !rDisplayInfo.GetProcessLayers().IsEmpty()) 124 { 125 const ViewContact& rDrawPageVC = pStartPage->GetViewContact(); 126 127 if(rDrawPageVC.GetObjectCount()) 128 { 129 DoProcessDisplay(rDisplayInfo); 130 } 131 } 132 133 // after paint take care of the evtl. scheduled asynchronious commands. 134 // Do this by resetting the timer contained there. Thus, after the paint 135 // that timer will be triggered and the events will be executed. 136 if(HasEventHandler()) 137 { 138 sdr::event::TimerEventHandler& rEventHandler = GetEventHandler(); 139 140 if(!rEventHandler.IsEmpty()) 141 { 142 rEventHandler.Restart(); 143 } 144 } 145 } 146 147 // Process the whole displaying. Only use given DsiplayInfo, do not access other 148 // OutputDevices then the given ones. 149 void ObjectContactOfPageView::DoProcessDisplay(DisplayInfo& rDisplayInfo) 150 { 151 // visualize entered group when that feature is switched on and it's not 152 // a print output. #i29129# No ghosted display for printing. 153 sal_Bool bVisualizeEnteredGroup(DoVisualizeEnteredGroup() && !isOutputToPrinter()); 154 155 // Visualize entered groups: Set to ghosted as default 156 // start. Do this only for the DrawPage, not for MasterPages 157 if(bVisualizeEnteredGroup) 158 { 159 rDisplayInfo.SetGhostedDrawMode(); 160 } 161 162 // #114359# save old and set clip region 163 OutputDevice* pOutDev = TryToGetOutputDevice(); 164 OSL_ENSURE(0 != pOutDev, "ObjectContactOfPageView without OutDev, someone has overloaded TryToGetOutputDevice wrong (!)"); 165 sal_Bool bClipRegionPushed(sal_False); 166 const Region& rRedrawArea(rDisplayInfo.GetRedrawArea()); 167 168 if(!rRedrawArea.IsEmpty()) 169 { 170 bClipRegionPushed = sal_True; 171 pOutDev->Push(PUSH_CLIPREGION); 172 pOutDev->IntersectClipRegion(rRedrawArea); 173 } 174 175 // Get start node and process DrawPage contents 176 const ViewObjectContact& rDrawPageVOContact = GetSdrPage()->GetViewContact().GetViewObjectContact(*this); 177 178 // update current ViewInformation2D at the ObjectContact 179 const double fCurrentTime(getPrimitiveAnimator().GetTime()); 180 OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice(); 181 basegfx::B2DRange aViewRange; 182 basegfx::B2DHomMatrix aViewTransformation; 183 184 // create ViewRange 185 if(isOutputToRecordingMetaFile()) 186 { 187 if(isOutputToPDFFile() || isOutputToPrinter()) 188 { 189 // #i98402# if it's a PDF export, set the ClipRegion as ViewRange. This is 190 // mainly because SW does not use DrawingLayer Page-Oriented and if not doing this, 191 // all existing objects will be collected as primitives and processed. 192 // OD 2009-03-05 #i99876# perform the same also for SW on printing. 193 const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect()); 194 195 aViewRange = basegfx::B2DRange( 196 aLogicClipRectangle.Left(), aLogicClipRectangle.Top(), 197 aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom()); 198 } 199 } 200 else 201 { 202 // use visible pixels, but transform to world coordinates 203 const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel()); 204 aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight()); 205 206 // if a clip region is set, use it 207 if(!rDisplayInfo.GetRedrawArea().IsEmpty()) 208 { 209 // get logic clip range and create discrete one 210 const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect()); 211 basegfx::B2DRange aLogicClipRange( 212 aLogicClipRectangle.Left(), aLogicClipRectangle.Top(), 213 aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom()); 214 basegfx::B2DRange aDiscreteClipRange(aLogicClipRange); 215 aDiscreteClipRange.transform(rTargetOutDev.GetViewTransformation()); 216 217 // align the discrete one to discrete boundaries (pixel bounds). Also 218 // expand X and Y max by one due to Rectangle definition source 219 aDiscreteClipRange.expand(basegfx::B2DTuple( 220 floor(aDiscreteClipRange.getMinX()), 221 floor(aDiscreteClipRange.getMinY()))); 222 aDiscreteClipRange.expand(basegfx::B2DTuple( 223 1.0 + ceil(aDiscreteClipRange.getMaxX()), 224 1.0 + ceil(aDiscreteClipRange.getMaxY()))); 225 226 // intersect current ViewRange with ClipRange 227 aViewRange.intersect(aDiscreteClipRange); 228 } 229 230 // transform to world coordinates 231 aViewRange.transform(rTargetOutDev.GetInverseViewTransformation()); 232 233 // for metafile, leave ViewTransformation empty, but for pixel renderer 234 // get it from OutputDevice 235 aViewTransformation = rTargetOutDev.GetViewTransformation(); 236 } 237 238 // update local ViewInformation2D 239 const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D( 240 basegfx::B2DHomMatrix(), 241 aViewTransformation, 242 aViewRange, 243 GetXDrawPageForSdrPage(GetSdrPage()), 244 fCurrentTime, 245 uno::Sequence<beans::PropertyValue>()); 246 updateViewInformation2D(aNewViewInformation2D); 247 248 // get whole Primitive2DSequence; this will already make use of updated ViewInformation2D 249 // and may use the MapMode from the Target OutDev in the DisplayInfo 250 drawinglayer::primitive2d::Primitive2DSequence xPrimitiveSequence(rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo)); 251 252 // if there is something to show, use a primitive processor to render it. There 253 // is a choice between VCL and Canvas processors currently. The decision is made in 254 // createBaseProcessor2DFromOutputDevice and takes into accout things like the 255 // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered 256 // currently using the shown boolean. Canvas is not yet the default. 257 if(xPrimitiveSequence.hasElements()) 258 { 259 // prepare OutputDevice (historical stuff, maybe soon removed) 260 rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing 261 pOutDev->SetLayoutMode(0); // reset, default is no BiDi/RTL 262 263 // create renderer 264 drawinglayer::processor2d::BaseProcessor2D* pProcessor2D = createBaseProcessor2DFromOutputDevice( 265 rTargetOutDev, 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