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