xref: /trunk/main/svx/source/sdr/contact/viewobjectcontactofgraphic.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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