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