xref: /trunk/main/svx/source/sdr/contact/objectcontactofpageview.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 #include <svx/sdr/contact/objectcontactofpageview.hxx>
31 #include <svx/sdr/contact/viewobjectcontactofunocontrol.hxx>
32 #include <svx/svdpagv.hxx>
33 #include <svx/svdpage.hxx>
34 #include <svx/sdr/contact/displayinfo.hxx>
35 #include <svx/sdr/contact/viewobjectcontact.hxx>
36 #include <svx/svdview.hxx>
37 #include <svx/sdr/contact/viewcontact.hxx>
38 #include <svx/sdr/animation/objectanimator.hxx>
39 #include <svx/sdr/event/eventhandler.hxx>
40 #include <svx/sdrpagewindow.hxx>
41 #include <svx/sdrpaintwindow.hxx>
42 #include <drawinglayer/processor2d/vclprocessor2d.hxx>
43 #include <basegfx/matrix/b2dhommatrix.hxx>
44 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
45 #include <svx/sdr/contact/objectcontacttools.hxx>
46 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
47 #include <svx/unoapi.hxx>
48 
49 //////////////////////////////////////////////////////////////////////////////
50 
51 using namespace com::sun::star;
52 
53 //////////////////////////////////////////////////////////////////////////////
54 
55 namespace sdr
56 {
57     namespace contact
58     {
59         // internal access to SdrPage of SdrPageView
60         SdrPage* ObjectContactOfPageView::GetSdrPage() const
61         {
62             return GetPageWindow().GetPageView().GetPage();
63         }
64 
65         ObjectContactOfPageView::ObjectContactOfPageView(SdrPageWindow& rPageWindow)
66         :   ObjectContact(),
67             mrPageWindow(rPageWindow)
68         {
69             // init PreviewRenderer flag
70             setPreviewRenderer(((SdrPaintView&)rPageWindow.GetPageView().GetView()).IsPreviewRenderer());
71 
72             // init timer
73             SetTimeout(1);
74             Stop();
75         }
76 
77         ObjectContactOfPageView::~ObjectContactOfPageView()
78         {
79             // execute missing LazyInvalidates and stop timer
80             Timeout();
81         }
82 
83         // LazyInvalidate request. Take action.
84         void ObjectContactOfPageView::setLazyInvalidate(ViewObjectContact& /*rVOC*/)
85         {
86             // do NOT call parent, but remember that something is to do by
87             // starting the LazyInvalidateTimer
88             Start();
89         }
90 
91         // call this to support evtl. preparations for repaint
92         void ObjectContactOfPageView::PrepareProcessDisplay()
93         {
94             if(IsActive())
95             {
96                 static bool bInvalidateDuringPaint(true);
97 
98                 if(bInvalidateDuringPaint)
99                 {
100                     // there are still non-triggered LazyInvalidate events, trigger these
101                     Timeout();
102                 }
103             }
104         }
105 
106         // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
107         void ObjectContactOfPageView::Timeout()
108         {
109             // stop the timer
110             Stop();
111 
112             // invalidate all LazyInvalidate VOCs new situations
113             const sal_uInt32 nVOCCount(getViewObjectContactCount());
114 
115             for(sal_uInt32 a(0); a < nVOCCount; a++)
116             {
117                 ViewObjectContact* pCandidate = getViewObjectContact(a);
118                 pCandidate->triggerLazyInvalidate();
119             }
120         }
121 
122         // Process the whole displaying
123         void ObjectContactOfPageView::ProcessDisplay(DisplayInfo& rDisplayInfo)
124         {
125             const SdrPage* pStartPage = GetSdrPage();
126 
127             if(pStartPage && !rDisplayInfo.GetProcessLayers().IsEmpty())
128             {
129                 const ViewContact& rDrawPageVC = pStartPage->GetViewContact();
130 
131                 if(rDrawPageVC.GetObjectCount())
132                 {
133                     DoProcessDisplay(rDisplayInfo);
134                 }
135             }
136 
137             // after paint take care of the evtl. scheduled asynchronious commands.
138             // Do this by resetting the timer contained there. Thus, after the paint
139             // that timer will be triggered and the events will be executed.
140             if(HasEventHandler())
141             {
142                 sdr::event::TimerEventHandler& rEventHandler = GetEventHandler();
143 
144                 if(!rEventHandler.IsEmpty())
145                 {
146                     rEventHandler.Restart();
147                 }
148             }
149         }
150 
151         // Process the whole displaying. Only use given DsiplayInfo, do not access other
152         // OutputDevices then the given ones.
153         void ObjectContactOfPageView::DoProcessDisplay(DisplayInfo& rDisplayInfo)
154         {
155             // visualize entered group when that feature is switched on and it's not
156             // a print output. #i29129# No ghosted display for printing.
157             sal_Bool bVisualizeEnteredGroup(DoVisualizeEnteredGroup() && !isOutputToPrinter());
158 
159             // Visualize entered groups: Set to ghosted as default
160             // start. Do this only for the DrawPage, not for MasterPages
161             if(bVisualizeEnteredGroup)
162             {
163                 rDisplayInfo.SetGhostedDrawMode();
164             }
165 
166             // #114359# save old and set clip region
167             OutputDevice* pOutDev = TryToGetOutputDevice();
168             OSL_ENSURE(0 != pOutDev, "ObjectContactOfPageView without OutDev, someone has overloaded TryToGetOutputDevice wrong (!)");
169             sal_Bool bClipRegionPushed(sal_False);
170             const Region& rRedrawArea(rDisplayInfo.GetRedrawArea());
171 
172             if(!rRedrawArea.IsEmpty())
173             {
174                 bClipRegionPushed = sal_True;
175                 pOutDev->Push(PUSH_CLIPREGION);
176                 pOutDev->IntersectClipRegion(rRedrawArea);
177             }
178 
179             // Get start node and process DrawPage contents
180             const ViewObjectContact& rDrawPageVOContact = GetSdrPage()->GetViewContact().GetViewObjectContact(*this);
181 
182             // update current ViewInformation2D at the ObjectContact
183             const double fCurrentTime(getPrimitiveAnimator().GetTime());
184             OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice();
185             basegfx::B2DRange aViewRange;
186 
187             // create ViewRange
188             if(isOutputToRecordingMetaFile())
189             {
190                 if(isOutputToPDFFile() || isOutputToPrinter())
191                 {
192                     // #i98402# if it's a PDF export, set the ClipRegion as ViewRange. This is
193                     // mainly because SW does not use DrawingLayer Page-Oriented and if not doing this,
194                     // all existing objects will be collected as primitives and processed.
195                     // OD 2009-03-05 #i99876# perform the same also for SW on printing.
196                     const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
197 
198                     aViewRange = basegfx::B2DRange(
199                         aLogicClipRectangle.Left(), aLogicClipRectangle.Top(),
200                         aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom());
201                 }
202             }
203             else
204             {
205                 // use visible pixels, but transform to world coordinates
206                 const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel());
207                 aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
208 
209                 // if a clip region is set, use it
210                 if(!rDisplayInfo.GetRedrawArea().IsEmpty())
211                 {
212                     // get logic clip range and create discrete one
213                     const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
214                     basegfx::B2DRange aLogicClipRange(
215                         aLogicClipRectangle.Left(), aLogicClipRectangle.Top(),
216                         aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom());
217                     basegfx::B2DRange aDiscreteClipRange(aLogicClipRange);
218                     aDiscreteClipRange.transform(rTargetOutDev.GetViewTransformation());
219 
220                     // align the discrete one to discrete boundaries (pixel bounds). Also
221                     // expand X and Y max by one due to Rectangle definition source
222                     aDiscreteClipRange.expand(basegfx::B2DTuple(
223                         floor(aDiscreteClipRange.getMinX()),
224                         floor(aDiscreteClipRange.getMinY())));
225                     aDiscreteClipRange.expand(basegfx::B2DTuple(
226                         1.0 + ceil(aDiscreteClipRange.getMaxX()),
227                         1.0 + ceil(aDiscreteClipRange.getMaxY())));
228 
229                     // intersect current ViewRange with ClipRange
230                     aViewRange.intersect(aDiscreteClipRange);
231                 }
232 
233                 // transform to world coordinates
234                 aViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
235             }
236 
237             // update local ViewInformation2D
238             const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
239                 basegfx::B2DHomMatrix(),
240                 rTargetOutDev.GetViewTransformation(),
241                 aViewRange,
242                 GetXDrawPageForSdrPage(GetSdrPage()),
243                 fCurrentTime,
244                 uno::Sequence<beans::PropertyValue>());
245             updateViewInformation2D(aNewViewInformation2D);
246 
247             // get whole Primitive2DSequence; this will already make use of updated ViewInformation2D
248             // and may use the MapMode from the Target OutDev in the DisplayInfo
249             drawinglayer::primitive2d::Primitive2DSequence xPrimitiveSequence(rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo));
250 
251             // if there is something to show, use a primitive processor to render it. There
252             // is a choice between VCL and Canvas processors currently. The decision is made in
253             // createBaseProcessor2DFromOutputDevice and takes into accout things like the
254             // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered
255             // currently using the shown boolean. Canvas is not yet the default.
256             if(xPrimitiveSequence.hasElements())
257             {
258                 // prepare OutputDevice (historical stuff, maybe soon removed)
259                 rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing
260                 pOutDev->SetLayoutMode(0); // reset, default is no BiDi/RTL
261 
262                 // create renderer
263                 drawinglayer::processor2d::BaseProcessor2D* pProcessor2D = createBaseProcessor2DFromOutputDevice(
264                     rTargetOutDev, getViewInformation2D());
265 
266                 if(pProcessor2D)
267                 {
268                     pProcessor2D->process(xPrimitiveSequence);
269                     delete pProcessor2D;
270                 }
271             }
272 
273             // #114359# restore old ClipReghion
274             if(bClipRegionPushed)
275             {
276                 pOutDev->Pop();
277             }
278 
279             // Visualize entered groups: Reset to original DrawMode
280             if(bVisualizeEnteredGroup)
281             {
282                 rDisplayInfo.ClearGhostedDrawMode();
283             }
284         }
285 
286         // test if visualizing of entered groups is switched on at all
287         bool ObjectContactOfPageView::DoVisualizeEnteredGroup() const
288         {
289             SdrView& rView = GetPageWindow().GetPageView().GetView();
290             return rView.DoVisualizeEnteredGroup();
291         }
292 
293         // get active group's (the entered group) ViewContact
294         const ViewContact* ObjectContactOfPageView::getActiveViewContact() const
295         {
296             SdrObjList* pActiveGroupList = GetPageWindow().GetPageView().GetObjList();
297 
298             if(pActiveGroupList)
299             {
300                 if(pActiveGroupList->ISA(SdrPage))
301                 {
302                     // It's a Page itself
303                     return &(((SdrPage*)pActiveGroupList)->GetViewContact());
304                 }
305                 else if(pActiveGroupList->GetOwnerObj())
306                 {
307                     // Group object
308                     return &(pActiveGroupList->GetOwnerObj()->GetViewContact());
309                 }
310             }
311             else if(GetSdrPage())
312             {
313                 // use page of associated SdrPageView
314                 return &(GetSdrPage()->GetViewContact());
315             }
316 
317             return 0;
318         }
319 
320         // Invalidate given rectangle at the window/output which is represented by
321         // this ObjectContact.
322         void ObjectContactOfPageView::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
323         {
324             // invalidate at associated PageWindow
325             GetPageWindow().InvalidatePageWindow(rRange);
326         }
327 
328         // Get info if given Rectangle is visible in this view
329         bool ObjectContactOfPageView::IsAreaVisible(const basegfx::B2DRange& rRange) const
330         {
331             // compare with the visible rectangle
332             if(rRange.isEmpty())
333             {
334                 // no range -> not visible
335                 return false;
336             }
337             else
338             {
339                 const OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice();
340                 const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel());
341                 basegfx::B2DRange aLogicViewRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
342 
343                 aLogicViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
344 
345                 if(!aLogicViewRange.isEmpty() && !aLogicViewRange.overlaps(rRange))
346                 {
347                     return false;
348                 }
349             }
350 
351             // call parent
352             return ObjectContact::IsAreaVisible(rRange);
353         }
354 
355         // Get info about the need to visualize GluePoints
356         bool ObjectContactOfPageView::AreGluePointsVisible() const
357         {
358             return GetPageWindow().GetPageView().GetView().ImpIsGlueVisible();
359         }
360 
361         // check if text animation is allowed.
362         bool ObjectContactOfPageView::IsTextAnimationAllowed() const
363         {
364             SdrView& rView = GetPageWindow().GetPageView().GetView();
365             const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
366             return rOpt.GetIsAllowAnimatedText();
367         }
368 
369         // check if graphic animation is allowed.
370         bool ObjectContactOfPageView::IsGraphicAnimationAllowed() const
371         {
372             SdrView& rView = GetPageWindow().GetPageView().GetView();
373             const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
374             return rOpt.GetIsAllowAnimatedGraphics();
375         }
376 
377         // check if asynchronious graphis loading is allowed. Default is sal_False.
378         bool ObjectContactOfPageView::IsAsynchronGraphicsLoadingAllowed() const
379         {
380             SdrView& rView = GetPageWindow().GetPageView().GetView();
381             return rView.IsSwapAsynchron();
382         }
383 
384         // check if buffering of MasterPages is allowed. Default is sal_False.
385         bool ObjectContactOfPageView::IsMasterPageBufferingAllowed() const
386         {
387             SdrView& rView = GetPageWindow().GetPageView().GetView();
388             return rView.IsMasterPagePaintCaching();
389         }
390 
391         // print?
392         bool ObjectContactOfPageView::isOutputToPrinter() const
393         {
394             return (OUTDEV_PRINTER == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType());
395         }
396 
397         // window?
398         bool ObjectContactOfPageView::isOutputToWindow() const
399         {
400             return (OUTDEV_WINDOW == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType());
401         }
402 
403         // VirtualDevice?
404         bool ObjectContactOfPageView::isOutputToVirtualDevice() const
405         {
406             return (OUTDEV_VIRDEV == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType());
407         }
408 
409         // recording MetaFile?
410         bool ObjectContactOfPageView::isOutputToRecordingMetaFile() const
411         {
412             GDIMetaFile* pMetaFile = mrPageWindow.GetPaintWindow().GetOutputDevice().GetConnectMetaFile();
413             return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
414         }
415 
416         // pdf export?
417         bool ObjectContactOfPageView::isOutputToPDFFile() const
418         {
419             return (0 != mrPageWindow.GetPaintWindow().GetOutputDevice().GetPDFWriter());
420         }
421 
422         // gray display mode
423         bool ObjectContactOfPageView::isDrawModeGray() const
424         {
425             const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode());
426             return (nDrawMode == (DRAWMODE_GRAYLINE|DRAWMODE_GRAYFILL|DRAWMODE_BLACKTEXT|DRAWMODE_GRAYBITMAP|DRAWMODE_GRAYGRADIENT));
427         }
428 
429         // gray display mode
430         bool ObjectContactOfPageView::isDrawModeBlackWhite() const
431         {
432             const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode());
433             return (nDrawMode == (DRAWMODE_BLACKLINE|DRAWMODE_BLACKTEXT|DRAWMODE_WHITEFILL|DRAWMODE_GRAYBITMAP|DRAWMODE_WHITEGRADIENT));
434         }
435 
436         // high contrast display mode
437         bool ObjectContactOfPageView::isDrawModeHighContrast() const
438         {
439             const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode());
440             return (nDrawMode == (DRAWMODE_SETTINGSLINE|DRAWMODE_SETTINGSFILL|DRAWMODE_SETTINGSTEXT|DRAWMODE_SETTINGSGRADIENT));
441         }
442 
443         // access to SdrPageView
444         SdrPageView* ObjectContactOfPageView::TryToGetSdrPageView() const
445         {
446             return &(mrPageWindow.GetPageView());
447         }
448 
449 
450         // access to OutputDevice
451         OutputDevice* ObjectContactOfPageView::TryToGetOutputDevice() const
452         {
453             SdrPreRenderDevice* pPreRenderDevice = mrPageWindow.GetPaintWindow().GetPreRenderDevice();
454 
455             if(pPreRenderDevice)
456             {
457                 return &(pPreRenderDevice->GetPreRenderDevice());
458             }
459             else
460             {
461                 return &(mrPageWindow.GetPaintWindow().GetOutputDevice());
462             }
463         }
464 
465         // set all UNO controls displayed in the view to design/alive mode
466         void ObjectContactOfPageView::SetUNOControlsDesignMode( bool _bDesignMode ) const
467         {
468             const sal_uInt32 nCount(getViewObjectContactCount());
469 
470             for(sal_uInt32 a(0); a < nCount; a++)
471             {
472                 const ViewObjectContact* pVOC = getViewObjectContact(a);
473                 const ViewObjectContactOfUnoControl* pUnoObjectVOC = dynamic_cast< const ViewObjectContactOfUnoControl* >(pVOC);
474 
475                 if(pUnoObjectVOC)
476                 {
477                     pUnoObjectVOC->setControlDesignMode(_bDesignMode);
478                 }
479             }
480         }
481     } // end of namespace contact
482 } // end of namespace sdr
483 
484 //////////////////////////////////////////////////////////////////////////////
485 // eof
486