LibreOffice Module svx (master)  1
objectcontactofpageview.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <config_feature_desktop.h>
21 
24 #include <svx/svdpagv.hxx>
25 #include <svx/svdpage.hxx>
28 #include <svx/svdview.hxx>
31 #include <svx/sdrpagewindow.hxx>
32 #include <svx/sdrpaintwindow.hxx>
36 #include <svx/unoapi.hxx>
37 #include <unotools/configmgr.hxx>
38 #include <vcl/canvastools.hxx>
39 #include <comphelper/lok.hxx>
40 
41 #include <memory>
42 
43 using namespace com::sun::star;
44 
45 namespace sdr::contact
46 {
47  // internal access to SdrPage of SdrPageView
48  SdrPage* ObjectContactOfPageView::GetSdrPage() const
49  {
50  return GetPageWindow().GetPageView().GetPage();
51  }
52 
53  ObjectContactOfPageView::ObjectContactOfPageView(
54  SdrPageWindow& rPageWindow, const char *pDebugName)
55  : Idle(pDebugName)
56  , mrPageWindow(rPageWindow)
57  {
58  // init PreviewRenderer flag
59  setPreviewRenderer(static_cast<SdrPaintView&>(rPageWindow.GetPageView().GetView()).IsPreviewRenderer());
60 
61  // init timer
62  SetPriority(TaskPriority::HIGH_IDLE);
63  Stop();
64  }
65 
67  {
68  // execute missing LazyInvalidates and stop timer
69  Invoke();
70  }
71 
72  // LazyInvalidate request. Take action.
74  {
75  // do NOT call parent, but remember that something is to do by
76  // starting the LazyInvalidateTimer
77  Start();
78  }
79 
80  // call this to support evtl. preparations for repaint
82  {
83  if(IsActive())
84  // there are still non-triggered LazyInvalidate events, trigger these
85  Invoke();
86  }
87 
88  // From baseclass Timer, the timeout call triggered by the LazyInvalidate mechanism
90  {
91  // stop the timer
92  Stop();
93 
94  // invalidate all LazyInvalidate VOCs new situations
95  const sal_uInt32 nVOCCount(getViewObjectContactCount());
96 
97  for(sal_uInt32 a(0); a < nVOCCount; a++)
98  {
100  pCandidate->triggerLazyInvalidate();
101  }
102  }
103 
104  // Process the whole displaying
106  {
107  const SdrPage* pStartPage = GetSdrPage();
108 
109  if(pStartPage && !rDisplayInfo.GetProcessLayers().IsEmpty())
110  {
111  const ViewContact& rDrawPageVC = pStartPage->GetViewContact();
112 
113  if(rDrawPageVC.GetObjectCount())
114  {
115  DoProcessDisplay(rDisplayInfo);
116  }
117  }
118  }
119 
120  // Process the whole displaying. Only use given DisplayInfo, do not access other
121  // OutputDevices then the given ones.
123  {
125  const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel());
126  if (!isOutputToRecordingMetaFile() // do those have outdev too?
127  && (0 == aOutputSizePixel.getWidth() ||
128  0 == aOutputSizePixel.getHeight()))
129  {
130  return;
131  }
132 
133  // visualize entered group when that feature is switched on and it's not
134  // a print output. #i29129# No ghosted display for printing.
135  bool bVisualizeEnteredGroup(DoVisualizeEnteredGroup() && !isOutputToPrinter());
136 
137  // Visualize entered groups: Set to ghosted as default
138  // start. Do this only for the DrawPage, not for MasterPages
139  if(bVisualizeEnteredGroup)
140  {
141  rDisplayInfo.SetGhostedDrawMode();
142  }
143 
144  // #114359# save old and set clip region
145  OutputDevice* pOutDev = TryToGetOutputDevice();
146  OSL_ENSURE(nullptr != pOutDev, "ObjectContactOfPageView without OutDev, someone has overridden TryToGetOutputDevice wrong (!)");
147  bool bClipRegionPushed(false);
148  const vcl::Region& rRedrawArea(rDisplayInfo.GetRedrawArea());
149 
150  if(!rRedrawArea.IsEmpty() && !comphelper::LibreOfficeKit::isActive())
151  {
152  bClipRegionPushed = true;
153  pOutDev->Push(PushFlags::CLIPREGION);
154  pOutDev->IntersectClipRegion(rRedrawArea);
155  }
156 
157  // Get start node and process DrawPage contents
158  const ViewObjectContact& rDrawPageVOContact = GetSdrPage()->GetViewContact().GetViewObjectContact(*this);
159 
160  // update current ViewInformation2D at the ObjectContact
161  const double fCurrentTime(getPrimitiveAnimator().GetTime());
162  basegfx::B2DRange aViewRange;
163 
164  // create ViewRange
166  {
167  if (!rDisplayInfo.GetRedrawArea().IsEmpty())
168  {
169  // #i98402# if it's a PDF export, set the ClipRegion as ViewRange. This is
170  // mainly because SW does not use DrawingLayer Page-Oriented and if not doing this,
171  // all existing objects will be collected as primitives and processed.
172  // OD 2009-03-05 #i99876# perform the same also for SW on printing.
173  // fdo#78149 same thing also needed for plain MetaFile
174  // export, so why not do it always
175  const tools::Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
176 
177  aViewRange = vcl::unotools::b2DRectangleFromRectangle(aLogicClipRectangle);
178  }
179  }
180  else
181  {
182  // use visible pixels, but transform to world coordinates
183  aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
184  // if a clip region is set, use it
185  if(!rDisplayInfo.GetRedrawArea().IsEmpty())
186  {
187  // get logic clip range and create discrete one
188  const tools::Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
189  basegfx::B2DRange aDiscreteClipRange = vcl::unotools::b2DRectangleFromRectangle(aLogicClipRectangle);
190  aDiscreteClipRange.transform(rTargetOutDev.GetViewTransformation());
191 
192  // align the discrete one to discrete boundaries (pixel bounds). Also
193  // expand X and Y max by one due to Rectangle definition source
194  aDiscreteClipRange.expand(basegfx::B2DTuple(
195  floor(aDiscreteClipRange.getMinX()),
196  floor(aDiscreteClipRange.getMinY())));
197  aDiscreteClipRange.expand(basegfx::B2DTuple(
198  1.0 + ceil(aDiscreteClipRange.getMaxX()),
199  1.0 + ceil(aDiscreteClipRange.getMaxY())));
200 
201  // intersect current ViewRange with ClipRange
202  aViewRange.intersect(aDiscreteClipRange);
203  }
204 
205  // transform to world coordinates
206  aViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
207  }
208 
209  // update local ViewInformation2D
210  const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
212  rTargetOutDev.GetViewTransformation(),
213  aViewRange,
215  fCurrentTime);
216  updateViewInformation2D(aNewViewInformation2D);
217 
218  // if there is something to show, use a primitive processor to render it. There
219  // is a choice between VCL and Canvas processors currently. The decision is made in
220  // createProcessor2DFromOutputDevice and takes into account things like the
221  // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered
222  // currently using the shown boolean. Canvas is not yet the default.
223 
224  // prepare OutputDevice (historical stuff, maybe soon removed)
225  rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing
226  pOutDev->SetLayoutMode(ComplexTextLayoutFlags::Default); // reset, default is no BiDi/RTL
227 
228  // create renderer
229  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
231  rTargetOutDev, getViewInformation2D()));
232 
233 #if HAVE_FEATURE_DESKTOP || defined( ANDROID )
234  // get whole Primitive2DContainer; this will already make use of updated ViewInformation2D
235  // and may use the MapMode from the Target OutDev in the DisplayInfo
236  rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo, *pProcessor2D);
237 #else
238  // Hmm, !HAVE_FEATURE_DESKTOP && !ANDROID means iOS,
239  // right? But does it makes sense to use a different code
240  // path for iOS than for Android; both use tiled rendering
241  // etc now.
242 
243  // HACK: this only works when we are drawing sdr shapes via
244  // drawinglayer; but it can happen that the hierarchy contains
245  // more than just the shapes, and then it fails.
246  //
247  // This is good enough for the tiled rendering for the moment, but
248  // we need to come up with the real solution shortly.
249 
250  // Only get the expensive hierarchy if we can be sure that the
251  // returned sequence won't be empty anyway.
252  bool bGetHierarchy = rRedrawArea.IsEmpty();
253  if (!bGetHierarchy)
254  {
255  // Not empty? Then not doing a full redraw, check if
256  // getPrimitive2DSequenceHierarchy() is still needed.
257  sal_Int32 nObjCount = GetSdrPage()->GetObjCount();
258  for (sal_Int32 i = 0; i < nObjCount; ++i)
259  {
261  if (rRedrawArea.IsOver(pObject->GetCurrentBoundRect()))
262  {
263  bGetHierarchy = true;
264  break;
265  }
266  }
267  }
268 
269  if (bGetHierarchy)
270  // get whole Primitive2DContainer; this will already make use of updated ViewInformation2D
271  // and may use the MapMode from the Target OutDev in the DisplayInfo
272  rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo, *pProcessor2D);
273 #endif
274 
275  // #114359# restore old ClipReghion
276  if(bClipRegionPushed)
277  {
278  pOutDev->Pop();
279  }
280 
281  // Visualize entered groups: Reset to original DrawMode
282  if(bVisualizeEnteredGroup)
283  {
284  rDisplayInfo.ClearGhostedDrawMode();
285  }
286  }
287 
288  // test if visualizing of entered groups is switched on at all
290  {
291  return true;
292  }
293 
294  // get active group's (the entered group) ViewContact
296  {
297  SdrObjList* pActiveGroupList = GetPageWindow().GetPageView().GetObjList();
298 
299  if(pActiveGroupList)
300  {
301  if(nullptr != pActiveGroupList->getSdrPageFromSdrObjList())
302  {
303  // It's a Page itself
304  return &(pActiveGroupList->getSdrPageFromSdrObjList()->GetViewContact());
305  }
306  else if(pActiveGroupList->getSdrObjectFromSdrObjList())
307  {
308  // Group object
309  return &(pActiveGroupList->getSdrObjectFromSdrObjList()->GetViewContact());
310  }
311  }
312  else if(GetSdrPage())
313  {
314  // use page of associated SdrPageView
315  return &(GetSdrPage()->GetViewContact());
316  }
317 
318  return nullptr;
319  }
320 
321  // Invalidate given rectangle at the window/output which is represented by
322  // this ObjectContact.
324  {
325  // invalidate at associated PageWindow
327  }
328 
329  // Get info about the need to visualize GluePoints
331  {
332  bool bTiledRendering = comphelper::LibreOfficeKit::isActive();
333  return !bTiledRendering && GetPageWindow().GetPageView().GetView().ImpIsGlueVisible();
334  }
335 
336  // check if text animation is allowed.
338  {
340  return true;
341  SdrView& rView = GetPageWindow().GetPageView().GetView();
342  const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
343  return rOpt.GetIsAllowAnimatedText();
344  }
345 
346  // check if graphic animation is allowed.
348  {
350  return true;
351  SdrView& rView = GetPageWindow().GetPageView().GetView();
352  const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
353  return rOpt.GetIsAllowAnimatedGraphics();
354  }
355 
356  // print?
358  {
360  }
361 
362  // recording MetaFile?
364  {
366  return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
367  }
368 
369  // pdf export?
371  {
373  }
374 
375  // gray display mode
377  {
379  return (nDrawMode == (DrawModeFlags::GrayLine|DrawModeFlags::GrayFill|DrawModeFlags::BlackText|DrawModeFlags::GrayBitmap|DrawModeFlags::GrayGradient));
380  }
381 
382  // high contrast display mode
384  {
386  return (nDrawMode == (DrawModeFlags::SettingsLine|DrawModeFlags::SettingsFill|DrawModeFlags::SettingsText|DrawModeFlags::SettingsGradient));
387  }
388 
389  // access to SdrPageView
391  {
392  return &(mrPageWindow.GetPageView());
393  }
394 
395 
396  // access to OutputDevice
398  {
400 
401  if(pPreRenderDevice)
402  {
403  return &(pPreRenderDevice->GetPreRenderDevice());
404  }
405  else
406  {
408  }
409  }
410 
411  // set all UNO controls displayed in the view to design/alive mode
413  {
414  const sal_uInt32 nCount(getViewObjectContactCount());
415 
416  for(sal_uInt32 a(0); a < nCount; a++)
417  {
419  const ViewObjectContactOfUnoControl* pUnoObjectVOC = dynamic_cast< const ViewObjectContactOfUnoControl* >(pVOC);
420 
421  if(pUnoObjectVOC)
422  {
423  pUnoObjectVOC->setControlDesignMode(_bDesignMode);
424  }
425  }
426  }
427 
428 } // end of namespace
429 
430 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
basegfx::B2DHomMatrix GetInverseViewTransformation() const
OutDevType GetOutDevType() const
SdrPreRenderDevice * GetPreRenderDevice() const
const vcl::Region & GetRedrawArea() const
Definition: displayinfo.hxx:77
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:957
virtual bool AreGluePointsVisible() const override
void setControlDesignMode(bool _bDesignMode) const
sets the design/alive mode of the control
SdrView & GetView()
Definition: svdpagv.hxx:130
OutputDevice & GetPreRenderDevice()
virtual bool isDrawModeHighContrast() const override
SdrObject * GetObj(size_t nNum) const
Definition: svdpage.cxx:822
Any GetTime(const OUString &val)
size_t GetObjCount() const
Definition: svdpage.cxx:816
bool IsEmpty() const
Definition: svdlayer.cxx:25
ViewObjectContact & GetViewObjectContact(ObjectContact &rObjectContact)
Definition: viewcontact.cxx:64
void SetLayoutMode(ComplexTextLayoutFlags nTextLayoutMode)
void IntersectClipRegion(const tools::Rectangle &rRect)
GDIMetaFile * GetConnectMetaFile() const
bool IsRecord() const
virtual bool isOutputToPDFFile() const override
tools::Rectangle GetBoundRect() const
EmbeddedObjectRef * pObject
void setPreviewRenderer(bool bNew)
std::unique_ptr< BaseProcessor2D > createProcessor2DFromOutputDevice(OutputDevice &rTargetOutDev, const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
sdr::contact::ViewContact & GetViewContact() const
Definition: svdobj.cxx:251
bool IsActive() const
void updateViewInformation2D(const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
BASEGFX_DLLPUBLIC void transform(const B2DHomMatrix &rMatrix)
OutputDevice & GetTargetOutputDevice()
static bool IsFuzzing()
int nCount
const SdrLayerIDSet & GetProcessLayers() const
Definition: displayinfo.hxx:73
void SetUNOControlsDesignMode(bool _bDesignMode) const
sets all UNO controls which are associated with this ObjectContact to design or alive mode...
virtual bool IsGraphicAnimationAllowed() const override
bool GetIsAllowAnimatedGraphics() const
sdr::animation::primitiveAnimator & getPrimitiveAnimator()
SdrObjList * GetObjList() const
Return current List.
Definition: svdpagv.hxx:169
OUTDEV_PRINTER
bool IsEmpty() const
virtual void setLazyInvalidate(ViewObjectContact &rVOC) override
int i
virtual void getPrimitive2DSequenceHierarchy(DisplayInfo &rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor &rVisitor) const
uno_Any a
const drawinglayer::geometry::ViewInformation2D & getViewInformation2D() const
bool ImpIsGlueVisible()
Definition: svdpntv.hxx:239
OUTDEV_PDF
virtual bool DoVisualizeEnteredGroup() const override
virtual SdrPageView * TryToGetSdrPageView() const override
access to SdrPageView. May return 0L like the default implementations do. Override as needed...
virtual void InvalidatePartOfView(const basegfx::B2DRange &rRange) const override
ViewObjectContact * getViewObjectContact(sal_uInt32 a) const
Size GetOutputSizePixel() const
DrawModeFlags GetDrawMode() const
Abstract DrawObject.
Definition: svdobj.hxx:259
void DoProcessDisplay(DisplayInfo &rDisplayInfo)
void intersect(const B2DRange &rRange)
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
uno::Reference< drawing::XDrawPage > GetXDrawPageForSdrPage(SdrPage *pPage) noexcept
returns a StarOffice API wrapper for the given SdrPage
Definition: unopage.cxx:870
bool IsPause() const
virtual sal_uInt32 GetObjectCount() const
void Stop()
sal_uInt32 getViewObjectContactCount() const
const sdr::contact::ViewContact & GetViewContact() const
Definition: svdpage.cxx:1165
virtual bool isOutputToRecordingMetaFile() const override
SdrPaintWindow & GetPaintWindow() const
bool GetIsAllowAnimatedText() const
virtual void ProcessDisplay(DisplayInfo &rDisplayInfo) override
void InvalidatePageWindow(const basegfx::B2DRange &rRange)
virtual OutputDevice * TryToGetOutputDevice() const override
access to OutputDevice. May return 0L like the default implementations do. Override as needed...
virtual SdrPage * getSdrPageFromSdrObjList() const
Definition: svdpage.cxx:122
virtual bool isOutputToPrinter() const override
virtual bool IsTextAnimationAllowed() const override
virtual const ViewContact * getActiveViewContact() const override
virtual void Start(bool bStartTimer=true) override
void SetPriority(TaskPriority ePriority)
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:365
virtual bool isDrawModeGray() const override
SvtAccessibilityOptions & getAccessibilityOptions()
Definition: svdview.hxx:234
void Push(PushFlags nFlags=PushFlags::ALL)
basegfx::B2DHomMatrix GetViewTransformation() const
virtual SdrObject * getSdrObjectFromSdrObjList() const
Definition: svdpage.cxx:128
OutputDevice & GetOutputDevice() const
DrawModeFlags
SdrPageView & GetPageView() const