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