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 27 #include <svx/sdr/contact/viewobjectcontactofgraphic.hxx> 28 #include <svx/sdr/contact/viewcontactofgraphic.hxx> 29 #include <svx/sdr/event/eventhandler.hxx> 30 #include <svx/svdograf.hxx> 31 #include <svx/sdr/contact/objectcontact.hxx> 32 #include <svx/svdmodel.hxx> 33 #include <svx/svdpage.hxx> 34 35 ////////////////////////////////////////////////////////////////////////////// 36 37 namespace sdr 38 { 39 namespace event 40 { 41 class AsynchGraphicLoadingEvent : public BaseEvent 42 { 43 // the ViewContactOfGraphic to work with 44 sdr::contact::ViewObjectContactOfGraphic& mrVOCOfGraphic; 45 46 public: 47 // basic constructor. 48 AsynchGraphicLoadingEvent(EventHandler& rEventHandler, sdr::contact::ViewObjectContactOfGraphic& rVOCOfGraphic); 49 50 // destructor 51 virtual ~AsynchGraphicLoadingEvent(); 52 53 // the called method if the event is triggered 54 virtual void ExecuteEvent(); 55 }; 56 AsynchGraphicLoadingEvent(EventHandler & rEventHandler,sdr::contact::ViewObjectContactOfGraphic & rVOCOfGraphic)57 AsynchGraphicLoadingEvent::AsynchGraphicLoadingEvent( 58 EventHandler& rEventHandler, sdr::contact::ViewObjectContactOfGraphic& rVOCOfGraphic) 59 : BaseEvent(rEventHandler), 60 mrVOCOfGraphic(rVOCOfGraphic) 61 { 62 } 63 ~AsynchGraphicLoadingEvent()64 AsynchGraphicLoadingEvent::~AsynchGraphicLoadingEvent() 65 { 66 mrVOCOfGraphic.forgetAsynchGraphicLoadingEvent(this); 67 } 68 ExecuteEvent()69 void AsynchGraphicLoadingEvent::ExecuteEvent() 70 { 71 mrVOCOfGraphic.doAsynchGraphicLoading(); 72 } 73 } // end of namespace event 74 } // end of namespace sdr 75 76 ////////////////////////////////////////////////////////////////////////////// 77 78 namespace sdr 79 { 80 namespace contact 81 { 82 // Test graphics state and eventually trigger a SwapIn event or an Asynchronous 83 // load event. Return value gives info if SwapIn was triggered or not impPrepareGraphicWithAsynchroniousLoading()84 bool ViewObjectContactOfGraphic::impPrepareGraphicWithAsynchroniousLoading() 85 { 86 bool bRetval(false); 87 SdrGrafObj& rGrafObj = getSdrGrafObj(); 88 89 if(rGrafObj.IsSwappedOut()) 90 { 91 if(rGrafObj.IsLinkedGraphic()) 92 { 93 // update graphic link 94 rGrafObj.ImpUpdateGraphicLink(); 95 } 96 else 97 { 98 // SwapIn needs to be done. Decide if it can be done asynchronious. 99 bool bSwapInAsynchronious(false); 100 ObjectContact& rObjectContact = GetObjectContact(); 101 102 // only when allowed from configuration 103 if(rObjectContact.IsAsynchronGraphicsLoadingAllowed()) 104 { 105 // direct output or vdev output (PageView buffering) 106 if(rObjectContact.isOutputToWindow() || rObjectContact.isOutputToVirtualDevice()) 107 { 108 // only when no metafile recording 109 if(!rObjectContact.isOutputToRecordingMetaFile()) 110 { 111 // allow asynchronious loading 112 bSwapInAsynchronious = true; 113 } 114 } 115 } 116 117 if(bSwapInAsynchronious) 118 { 119 // maybe it's on the way, then do nothing 120 if(!mpAsynchLoadEvent) 121 { 122 // Trigger asynchronious SwapIn. 123 sdr::event::TimerEventHandler& rEventHandler = rObjectContact.GetEventHandler(); 124 125 mpAsynchLoadEvent = new sdr::event::AsynchGraphicLoadingEvent(rEventHandler, *this); 126 } 127 } 128 else 129 { 130 if(rObjectContact.isOutputToPrinter()) 131 { 132 // #i76395# preview mechanism is only active if 133 // swapin is called from inside paint preparation, so mbInsidePaint 134 // has to be false to be able to print with high resolution 135 rGrafObj.ForceSwapIn(); 136 } 137 else 138 { 139 // SwapIn direct 140 rGrafObj.mbInsidePaint = sal_True; 141 rGrafObj.ForceSwapIn(); 142 rGrafObj.mbInsidePaint = sal_False; 143 } 144 145 bRetval = true; 146 } 147 } 148 } 149 else 150 { 151 // it is not swapped out, somehow it was loaded. In that case, forget 152 // about an existing triggered event 153 if(mpAsynchLoadEvent) 154 { 155 // just delete it, this will remove it from the EventHandler and 156 // will trigger forgetAsynchGraphicLoadingEvent from the destructor 157 delete mpAsynchLoadEvent; 158 } 159 } 160 161 return bRetval; 162 } 163 164 // Test graphics state and eventually trigger a SwapIn event. Return value 165 // gives info if SwapIn was triggered or not impPrepareGraphicWithSynchroniousLoading()166 bool ViewObjectContactOfGraphic::impPrepareGraphicWithSynchroniousLoading() 167 { 168 bool bRetval(false); 169 SdrGrafObj& rGrafObj = getSdrGrafObj(); 170 171 if(rGrafObj.IsSwappedOut()) 172 { 173 if(rGrafObj.IsLinkedGraphic()) 174 { 175 // update graphic link 176 rGrafObj.ImpUpdateGraphicLink( sal_False ); 177 } 178 else 179 { 180 ObjectContact& rObjectContact = GetObjectContact(); 181 182 if(rObjectContact.isOutputToPrinter()) 183 { 184 // #i76395# preview mechanism is only active if 185 // swapin is called from inside paint preparation, so mbInsidePaint 186 // has to be false to be able to print with high resolution 187 rGrafObj.ForceSwapIn(); 188 } 189 else 190 { 191 // SwapIn direct 192 rGrafObj.mbInsidePaint = sal_True; 193 rGrafObj.ForceSwapIn(); 194 rGrafObj.mbInsidePaint = sal_False; 195 } 196 197 bRetval = true; 198 } 199 } 200 201 return bRetval; 202 } 203 204 // This is the call from the asynch graphic loading. This may only be called from 205 // AsynchGraphicLoadingEvent::ExecuteEvent(). Do load the graphics. The event will 206 // be deleted (consumed) and forgetAsynchGraphicLoadingEvent will be called. doAsynchGraphicLoading()207 void ViewObjectContactOfGraphic::doAsynchGraphicLoading() 208 { 209 DBG_ASSERT(mpAsynchLoadEvent, "ViewObjectContactOfGraphic::doAsynchGraphicLoading: I did not trigger a event, why am i called (?)"); 210 211 // swap it in 212 SdrGrafObj& rGrafObj = getSdrGrafObj(); 213 rGrafObj.ForceSwapIn(); 214 215 // #i103720# forget event to avoid possible deletion by the following ActionChanged call 216 // which may use createPrimitive2DSequence/impPrepareGraphicWithAsynchroniousLoading again. 217 // Deletion is actally done by the scheduler who leaded to coming here 218 mpAsynchLoadEvent = 0; 219 220 // Invalidate all paint areas and check existing animation (which may have changed). 221 GetViewContact().ActionChanged(); 222 } 223 224 // This is the call from the destructor of the asynch graphic loading event. 225 // No one else has to call this. It is needed to let this object forget about 226 // the event. The parameter allows checking for the correct event. forgetAsynchGraphicLoadingEvent(sdr::event::AsynchGraphicLoadingEvent * pEvent)227 void ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent(sdr::event::AsynchGraphicLoadingEvent* pEvent) 228 { 229 (void) pEvent; // suppress warning 230 231 if(mpAsynchLoadEvent) 232 { 233 OSL_ENSURE(!pEvent || mpAsynchLoadEvent == pEvent, 234 "ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent: Forced to forget another event then i have scheduled (?)"); 235 236 // forget event 237 mpAsynchLoadEvent = 0; 238 } 239 } 240 getSdrGrafObj()241 SdrGrafObj& ViewObjectContactOfGraphic::getSdrGrafObj() 242 { 243 return static_cast< ViewContactOfGraphic& >(GetViewContact()).GetGrafObject(); 244 } 245 createPrimitive2DSequence(const DisplayInfo & rDisplayInfo) const246 drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfGraphic::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const 247 { 248 // prepare primitive generation with evtl. loading the graphic when it's swapped out 249 SdrGrafObj& rGrafObj = const_cast< ViewObjectContactOfGraphic* >(this)->getSdrGrafObj(); 250 bool bDoAsynchronGraphicLoading(rGrafObj.GetModel() && rGrafObj.GetModel()->IsSwapGraphics()); 251 bool bSwapInDone(false); 252 bool bSwapInExclusive(false); 253 254 if( bDoAsynchronGraphicLoading && rGrafObj.IsSwappedOut() ) 255 { 256 // sometimes it is needed that each graphic is completely available and swapped in 257 // for these cases a ForceSwapIn is called later at the graphic object 258 if ( rGrafObj.GetPage() && rGrafObj.GetPage()->IsMasterPage() ) 259 { 260 // #i102380# force Swap-In for GraphicObjects on MasterPage to have a nicer visualisation 261 bDoAsynchronGraphicLoading = false; 262 } 263 else if ( GetObjectContact().isOutputToPrinter() 264 || GetObjectContact().isOutputToRecordingMetaFile() 265 || GetObjectContact().isOutputToPDFFile() ) 266 { 267 bDoAsynchronGraphicLoading = false; 268 bSwapInExclusive = true; 269 } 270 } 271 if( bDoAsynchronGraphicLoading ) 272 { 273 bSwapInDone = const_cast< ViewObjectContactOfGraphic* >(this)->impPrepareGraphicWithAsynchroniousLoading(); 274 } 275 else 276 { 277 bSwapInDone = const_cast< ViewObjectContactOfGraphic* >(this)->impPrepareGraphicWithSynchroniousLoading(); 278 } 279 280 // get return value by calling parent 281 drawinglayer::primitive2d::Primitive2DSequence xRetval = ViewObjectContactOfSdrObj::createPrimitive2DSequence(rDisplayInfo); 282 283 if(xRetval.hasElements()) 284 { 285 // #i103255# suppress when graphic needs draft visualisation and output 286 // is for PDF export/Printer 287 const ViewContactOfGraphic& rVCOfGraphic = static_cast< const ViewContactOfGraphic& >(GetViewContact()); 288 289 if(rVCOfGraphic.visualisationUsesDraft()) 290 { 291 const ObjectContact& rObjectContact = GetObjectContact(); 292 293 if(rObjectContact.isOutputToPDFFile() || rObjectContact.isOutputToPrinter()) 294 { 295 xRetval = drawinglayer::primitive2d::Primitive2DSequence(); 296 } 297 } 298 } 299 300 // if swap in was forced only for printing metafile and pdf, swap out again 301 if( bSwapInDone && bSwapInExclusive ) 302 { 303 rGrafObj.ForceSwapOut(); 304 } 305 306 return xRetval; 307 } 308 ViewObjectContactOfGraphic(ObjectContact & rObjectContact,ViewContact & rViewContact)309 ViewObjectContactOfGraphic::ViewObjectContactOfGraphic(ObjectContact& rObjectContact, ViewContact& rViewContact) 310 : ViewObjectContactOfSdrObj(rObjectContact, rViewContact), 311 mpAsynchLoadEvent(0) 312 { 313 } 314 ~ViewObjectContactOfGraphic()315 ViewObjectContactOfGraphic::~ViewObjectContactOfGraphic() 316 { 317 // evtl. delete the asynch loading event 318 if(mpAsynchLoadEvent) 319 { 320 // just delete it, this will remove it from the EventHandler and 321 // will trigger forgetAsynchGraphicLoadingEvent from the destructor 322 delete mpAsynchLoadEvent; 323 } 324 } 325 } // end of namespace contact 326 } // end of namespace sdr 327 328 ////////////////////////////////////////////////////////////////////////////// 329 // eof 330