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 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 233 // update local ViewInformation2D 234 const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D( 235 basegfx::B2DHomMatrix(), 236 rTargetOutDev.GetViewTransformation(), 237 aViewRange, 238 GetXDrawPageForSdrPage(GetSdrPage()), 239 fCurrentTime, 240 uno::Sequence<beans::PropertyValue>()); 241 updateViewInformation2D(aNewViewInformation2D); 242 243 // get whole Primitive2DSequence; this will already make use of updated ViewInformation2D 244 // and may use the MapMode from the Target OutDev in the DisplayInfo 245 drawinglayer::primitive2d::Primitive2DSequence xPrimitiveSequence(rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo)); 246 247 // if there is something to show, use a primitive processor to render it. There 248 // is a choice between VCL and Canvas processors currently. The decision is made in 249 // createBaseProcessor2DFromOutputDevice and takes into accout things like the 250 // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered 251 // currently using the shown boolean. Canvas is not yet the default. 252 if(xPrimitiveSequence.hasElements()) 253 { 254 // prepare OutputDevice (historical stuff, maybe soon removed) 255 rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing 256 pOutDev->SetLayoutMode(0); // reset, default is no BiDi/RTL 257 258 // create renderer 259 drawinglayer::processor2d::BaseProcessor2D* pProcessor2D = createBaseProcessor2DFromOutputDevice( 260 rTargetOutDev, getViewInformation2D()); 261 262 if(pProcessor2D) 263 { 264 pProcessor2D->process(xPrimitiveSequence); 265 delete pProcessor2D; 266 } 267 } 268 269 // #114359# restore old ClipReghion 270 if(bClipRegionPushed) 271 { 272 pOutDev->Pop(); 273 } 274 275 // Visualize entered groups: Reset to original DrawMode 276 if(bVisualizeEnteredGroup) 277 { 278 rDisplayInfo.ClearGhostedDrawMode(); 279 } 280 } 281 282 // test if visualizing of entered groups is switched on at all 283 bool ObjectContactOfPageView::DoVisualizeEnteredGroup() const 284 { 285 SdrView& rView = GetPageWindow().GetPageView().GetView(); 286 return rView.DoVisualizeEnteredGroup(); 287 } 288 289 // get active group's (the entered group) ViewContact 290 const ViewContact* ObjectContactOfPageView::getActiveViewContact() const 291 { 292 SdrObjList* pActiveGroupList = GetPageWindow().GetPageView().GetObjList(); 293 294 if(pActiveGroupList) 295 { 296 if(pActiveGroupList->ISA(SdrPage)) 297 { 298 // It's a Page itself 299 return &(((SdrPage*)pActiveGroupList)->GetViewContact()); 300 } 301 else if(pActiveGroupList->GetOwnerObj()) 302 { 303 // Group object 304 return &(pActiveGroupList->GetOwnerObj()->GetViewContact()); 305 } 306 } 307 else if(GetSdrPage()) 308 { 309 // use page of associated SdrPageView 310 return &(GetSdrPage()->GetViewContact()); 311 } 312 313 return 0; 314 } 315 316 // Invalidate given rectangle at the window/output which is represented by 317 // this ObjectContact. 318 void ObjectContactOfPageView::InvalidatePartOfView(const basegfx::B2DRange& rRange) const 319 { 320 // invalidate at associated PageWindow 321 GetPageWindow().InvalidatePageWindow(rRange); 322 } 323 324 // Get info if given Rectangle is visible in this view 325 bool ObjectContactOfPageView::IsAreaVisible(const basegfx::B2DRange& rRange) const 326 { 327 // compare with the visible rectangle 328 if(rRange.isEmpty()) 329 { 330 // no range -> not visible 331 return false; 332 } 333 else 334 { 335 const OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice(); 336 const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel()); 337 basegfx::B2DRange aLogicViewRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight()); 338 339 aLogicViewRange.transform(rTargetOutDev.GetInverseViewTransformation()); 340 341 if(!aLogicViewRange.isEmpty() && !aLogicViewRange.overlaps(rRange)) 342 { 343 return false; 344 } 345 } 346 347 // call parent 348 return ObjectContact::IsAreaVisible(rRange); 349 } 350 351 // Get info about the need to visualize GluePoints 352 bool ObjectContactOfPageView::AreGluePointsVisible() const 353 { 354 return GetPageWindow().GetPageView().GetView().ImpIsGlueVisible(); 355 } 356 357 // check if text animation is allowed. 358 bool ObjectContactOfPageView::IsTextAnimationAllowed() const 359 { 360 SdrView& rView = GetPageWindow().GetPageView().GetView(); 361 const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions(); 362 return rOpt.GetIsAllowAnimatedText(); 363 } 364 365 // check if graphic animation is allowed. 366 bool ObjectContactOfPageView::IsGraphicAnimationAllowed() const 367 { 368 SdrView& rView = GetPageWindow().GetPageView().GetView(); 369 const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions(); 370 return rOpt.GetIsAllowAnimatedGraphics(); 371 } 372 373 // check if asynchronious graphis loading is allowed. Default is sal_False. 374 bool ObjectContactOfPageView::IsAsynchronGraphicsLoadingAllowed() const 375 { 376 SdrView& rView = GetPageWindow().GetPageView().GetView(); 377 return rView.IsSwapAsynchron(); 378 } 379 380 // check if buffering of MasterPages is allowed. Default is sal_False. 381 bool ObjectContactOfPageView::IsMasterPageBufferingAllowed() const 382 { 383 SdrView& rView = GetPageWindow().GetPageView().GetView(); 384 return rView.IsMasterPagePaintCaching(); 385 } 386 387 // print? 388 bool ObjectContactOfPageView::isOutputToPrinter() const 389 { 390 return (OUTDEV_PRINTER == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType()); 391 } 392 393 // window? 394 bool ObjectContactOfPageView::isOutputToWindow() const 395 { 396 return (OUTDEV_WINDOW == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType()); 397 } 398 399 // VirtualDevice? 400 bool ObjectContactOfPageView::isOutputToVirtualDevice() const 401 { 402 return (OUTDEV_VIRDEV == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType()); 403 } 404 405 // recording MetaFile? 406 bool ObjectContactOfPageView::isOutputToRecordingMetaFile() const 407 { 408 GDIMetaFile* pMetaFile = mrPageWindow.GetPaintWindow().GetOutputDevice().GetConnectMetaFile(); 409 return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause()); 410 } 411 412 // pdf export? 413 bool ObjectContactOfPageView::isOutputToPDFFile() const 414 { 415 return (0 != mrPageWindow.GetPaintWindow().GetOutputDevice().GetPDFWriter()); 416 } 417 418 // gray display mode 419 bool ObjectContactOfPageView::isDrawModeGray() const 420 { 421 const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode()); 422 return (nDrawMode == (DRAWMODE_GRAYLINE|DRAWMODE_GRAYFILL|DRAWMODE_BLACKTEXT|DRAWMODE_GRAYBITMAP|DRAWMODE_GRAYGRADIENT)); 423 } 424 425 // gray display mode 426 bool ObjectContactOfPageView::isDrawModeBlackWhite() const 427 { 428 const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode()); 429 return (nDrawMode == (DRAWMODE_BLACKLINE|DRAWMODE_BLACKTEXT|DRAWMODE_WHITEFILL|DRAWMODE_GRAYBITMAP|DRAWMODE_WHITEGRADIENT)); 430 } 431 432 // high contrast display mode 433 bool ObjectContactOfPageView::isDrawModeHighContrast() const 434 { 435 const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode()); 436 return (nDrawMode == (DRAWMODE_SETTINGSLINE|DRAWMODE_SETTINGSFILL|DRAWMODE_SETTINGSTEXT|DRAWMODE_SETTINGSGRADIENT)); 437 } 438 439 // access to SdrPageView 440 SdrPageView* ObjectContactOfPageView::TryToGetSdrPageView() const 441 { 442 return &(mrPageWindow.GetPageView()); 443 } 444 445 446 // access to OutputDevice 447 OutputDevice* ObjectContactOfPageView::TryToGetOutputDevice() const 448 { 449 SdrPreRenderDevice* pPreRenderDevice = mrPageWindow.GetPaintWindow().GetPreRenderDevice(); 450 451 if(pPreRenderDevice) 452 { 453 return &(pPreRenderDevice->GetPreRenderDevice()); 454 } 455 else 456 { 457 return &(mrPageWindow.GetPaintWindow().GetOutputDevice()); 458 } 459 } 460 461 // set all UNO controls displayed in the view to design/alive mode 462 void ObjectContactOfPageView::SetUNOControlsDesignMode( bool _bDesignMode ) const 463 { 464 const sal_uInt32 nCount(getViewObjectContactCount()); 465 466 for(sal_uInt32 a(0); a < nCount; a++) 467 { 468 const ViewObjectContact* pVOC = getViewObjectContact(a); 469 const ViewObjectContactOfUnoControl* pUnoObjectVOC = dynamic_cast< const ViewObjectContactOfUnoControl* >(pVOC); 470 471 if(pUnoObjectVOC) 472 { 473 pUnoObjectVOC->setControlDesignMode(_bDesignMode); 474 } 475 } 476 } 477 } // end of namespace contact 478 } // end of namespace sdr 479 480 ////////////////////////////////////////////////////////////////////////////// 481 // eof 482