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