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 <osl/diagnose.h>
37 #include <svx/unoapi.hxx>
38 #include <unotools/configmgr.hxx>
39 #include <vcl/canvastools.hxx>
40 #include <comphelper/lok.hxx>
41 
42 #include <memory>
43 
44 using namespace com::sun::star;
45 
46 namespace sdr::contact
47 {
48  // internal access to SdrPage of SdrPageView
49  SdrPage* ObjectContactOfPageView::GetSdrPage() const
50  {
51  return GetPageWindow().GetPageView().GetPage();
52  }
53 
54  ObjectContactOfPageView::ObjectContactOfPageView(
55  SdrPageWindow& rPageWindow, const char *pDebugName)
56  : Idle(pDebugName)
57  , mrPageWindow(rPageWindow)
58  {
59  // init PreviewRenderer flag
60  setPreviewRenderer(static_cast<SdrPaintView&>(rPageWindow.GetPageView().GetView()).IsPreviewRenderer());
61 
62  // init timer
63  SetPriority(TaskPriority::HIGH_IDLE);
64  Stop();
65  }
66 
68  {
69  // execute missing LazyInvalidates and stop timer
70  Invoke();
71  }
72 
73  // LazyInvalidate request. Take action.
75  {
76  // do NOT call parent, but remember that something is to do by
77  // starting the LazyInvalidateTimer
78  Start();
79  }
80 
81  // call this to support evtl. preparations for repaint
83  {
84  if(IsActive())
85  // there are still non-triggered LazyInvalidate events, trigger these
86  Invoke();
87  }
88 
89  // From baseclass Timer, the timeout call triggered by the LazyInvalidate mechanism
91  {
92  // stop the timer
93  Stop();
94 
95  // invalidate all LazyInvalidate VOCs new situations
96  const sal_uInt32 nVOCCount(getViewObjectContactCount());
97 
98  for(sal_uInt32 a(0); a < nVOCCount; a++)
99  {
101  pCandidate->triggerLazyInvalidate();
102  }
103  }
104 
105  // Process the whole displaying
107  {
108  const SdrPage* pStartPage = GetSdrPage();
109 
110  if(pStartPage && !rDisplayInfo.GetProcessLayers().IsEmpty())
111  {
112  const ViewContact& rDrawPageVC = pStartPage->GetViewContact();
113 
114  if(rDrawPageVC.GetObjectCount())
115  {
116  DoProcessDisplay(rDisplayInfo);
117  }
118  }
119  }
120 
121  // Process the whole displaying. Only use given DisplayInfo, do not access other
122  // OutputDevices then the given ones.
124  {
126  const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel());
127  if (!isOutputToRecordingMetaFile() // do those have outdev too?
128  && (0 == aOutputSizePixel.getWidth() ||
129  0 == aOutputSizePixel.getHeight()))
130  {
131  return;
132  }
133 
134  // visualize entered group when that feature is switched on and it's not
135  // a print output. #i29129# No ghosted display for printing.
136  bool bVisualizeEnteredGroup(DoVisualizeEnteredGroup() && !isOutputToPrinter());
137 
138  // Visualize entered groups: Set to ghosted as default
139  // start. Do this only for the DrawPage, not for MasterPages
140  if(bVisualizeEnteredGroup)
141  {
142  rDisplayInfo.SetGhostedDrawMode();
143  }
144 
145  // #114359# save old and set clip region
146  OutputDevice* pOutDev = TryToGetOutputDevice();
147  OSL_ENSURE(nullptr != pOutDev, "ObjectContactOfPageView without OutDev, someone has overridden TryToGetOutputDevice wrong (!)");
148  bool bClipRegionPushed(false);
149  const vcl::Region& rRedrawArea(rDisplayInfo.GetRedrawArea());
150 
151  if(!rRedrawArea.IsEmpty() && !comphelper::LibreOfficeKit::isActive())
152  {
153  bClipRegionPushed = true;
155  pOutDev->IntersectClipRegion(rRedrawArea);
156  }
157 
158  // Get start node and process DrawPage contents
159  const ViewObjectContact& rDrawPageVOContact = GetSdrPage()->GetViewContact().GetViewObjectContact(*this);
160 
161  // update current ViewInformation2D at the ObjectContact
162  const double fCurrentTime(getPrimitiveAnimator().GetTime());
163  basegfx::B2DRange aViewRange;
164 
165  // create ViewRange
167  {
168  if (!rDisplayInfo.GetRedrawArea().IsEmpty())
169  {
170  // #i98402# if it's a PDF export, set the ClipRegion as ViewRange. This is
171  // mainly because SW does not use DrawingLayer Page-Oriented and if not doing this,
172  // all existing objects will be collected as primitives and processed.
173  // OD 2009-03-05 #i99876# perform the same also for SW on printing.
174  // fdo#78149 same thing also needed for plain MetaFile
175  // export, so why not do it always
176  const tools::Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
177 
178  aViewRange = vcl::unotools::b2DRectangleFromRectangle(aLogicClipRectangle);
179  }
180  }
181  else
182  {
183  // use visible pixels, but transform to world coordinates
184  aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
185  // if a clip region is set, use it
186  if(!rDisplayInfo.GetRedrawArea().IsEmpty())
187  {
188  // get logic clip range and create discrete one
189  const tools::Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
190  basegfx::B2DRange aDiscreteClipRange = vcl::unotools::b2DRectangleFromRectangle(aLogicClipRectangle);
191  aDiscreteClipRange.transform(rTargetOutDev.GetViewTransformation());
192 
193  // align the discrete one to discrete boundaries (pixel bounds). Also
194  // expand X and Y max by one due to Rectangle definition source
195  aDiscreteClipRange.expand(basegfx::B2DTuple(
196  floor(aDiscreteClipRange.getMinX()),
197  floor(aDiscreteClipRange.getMinY())));
198  aDiscreteClipRange.expand(basegfx::B2DTuple(
199  1.0 + ceil(aDiscreteClipRange.getMaxX()),
200  1.0 + ceil(aDiscreteClipRange.getMaxY())));
201 
202  // intersect current ViewRange with ClipRange
203  aViewRange.intersect(aDiscreteClipRange);
204  }
205 
206  // transform to world coordinates
207  aViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
208  }
209 
210  // update local ViewInformation2D
211  const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
213  rTargetOutDev.GetViewTransformation(),
214  aViewRange,
216  fCurrentTime);
217  updateViewInformation2D(aNewViewInformation2D);
218 
219  // if there is something to show, use a primitive processor to render it. There
220  // is a choice between VCL and Canvas processors currently. The decision is made in
221  // createProcessor2DFromOutputDevice and takes into account things like the
222  // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered
223  // currently using the shown boolean. Canvas is not yet the default.
224 
225  // prepare OutputDevice (historical stuff, maybe soon removed)
226  rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing
227  pOutDev->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::Default); // reset, default is no BiDi/RTL
228 
229  // create renderer
230  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
232  rTargetOutDev, getViewInformation2D()));
233 
234 #if HAVE_FEATURE_DESKTOP || defined( ANDROID )
235  // get whole Primitive2DContainer; this will already make use of updated ViewInformation2D
236  // and may use the MapMode from the Target OutDev in the DisplayInfo
237  rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo, *pProcessor2D);
238 #else
239  // Hmm, !HAVE_FEATURE_DESKTOP && !ANDROID means iOS,
240  // right? But does it makes sense to use a different code
241  // path for iOS than for Android; both use tiled rendering
242  // etc now.
243 
244  // HACK: this only works when we are drawing sdr shapes via
245  // drawinglayer; but it can happen that the hierarchy contains
246  // more than just the shapes, and then it fails.
247  //
248  // This is good enough for the tiled rendering for the moment, but
249  // we need to come up with the real solution shortly.
250 
251  // Only get the expensive hierarchy if we can be sure that the
252  // returned sequence won't be empty anyway.
253  bool bGetHierarchy = rRedrawArea.IsEmpty();
254  if (!bGetHierarchy)
255  {
256  // Not empty? Then not doing a full redraw, check if
257  // getPrimitive2DSequenceHierarchy() is still needed.
258  sal_Int32 nObjCount = GetSdrPage()->GetObjCount();
259  for (sal_Int32 i = 0; i < nObjCount; ++i)
260  {
262  if (rRedrawArea.Overlaps(pObject->GetCurrentBoundRect()))
263  {
264  bGetHierarchy = true;
265  break;
266  }
267  }
268  }
269 
270  if (bGetHierarchy)
271  // get whole Primitive2DContainer; this will already make use of updated ViewInformation2D
272  // and may use the MapMode from the Target OutDev in the DisplayInfo
273  rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo, *pProcessor2D);
274 #endif
275 
276  // #114359# restore old ClipReghion
277  if(bClipRegionPushed)
278  {
279  pOutDev->Pop();
280  }
281 
282  // Visualize entered groups: Reset to original DrawMode
283  if(bVisualizeEnteredGroup)
284  {
285  rDisplayInfo.ClearGhostedDrawMode();
286  }
287  }
288 
289  // test if visualizing of entered groups is switched on at all
291  {
292  return true;
293  }
294 
295  // get active group's (the entered group) ViewContact
297  {
298  SdrObjList* pActiveGroupList = GetPageWindow().GetPageView().GetObjList();
299 
300  if(pActiveGroupList)
301  {
302  if(nullptr != pActiveGroupList->getSdrPageFromSdrObjList())
303  {
304  // It's a Page itself
305  return &(pActiveGroupList->getSdrPageFromSdrObjList()->GetViewContact());
306  }
307  else if(pActiveGroupList->getSdrObjectFromSdrObjList())
308  {
309  // Group object
310  return &(pActiveGroupList->getSdrObjectFromSdrObjList()->GetViewContact());
311  }
312  }
313  else if(GetSdrPage())
314  {
315  // use page of associated SdrPageView
316  return &(GetSdrPage()->GetViewContact());
317  }
318 
319  return nullptr;
320  }
321 
322  // Invalidate given rectangle at the window/output which is represented by
323  // this ObjectContact.
325  {
326  // invalidate at associated PageWindow
328  }
329 
330  // Get info about the need to visualize GluePoints
332  {
333  bool bTiledRendering = comphelper::LibreOfficeKit::isActive();
334  return !bTiledRendering && GetPageWindow().GetPageView().GetView().ImpIsGlueVisible();
335  }
336 
337  // check if text animation is allowed.
339  {
341  return true;
342  SdrView& rView = GetPageWindow().GetPageView().GetView();
343  const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
344  return rOpt.GetIsAllowAnimatedText();
345  }
346 
347  // check if graphic animation is allowed.
349  {
351  return true;
352  SdrView& rView = GetPageWindow().GetPageView().GetView();
353  const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
354  return rOpt.GetIsAllowAnimatedGraphics();
355  }
356 
357  // print?
359  {
361  }
362 
363  // recording MetaFile?
365  {
367  return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
368  }
369 
370  // pdf export?
372  {
374  }
375 
376  // gray display mode
378  {
380  return (nDrawMode == (DrawModeFlags::GrayLine|DrawModeFlags::GrayFill|DrawModeFlags::BlackText|DrawModeFlags::GrayBitmap|DrawModeFlags::GrayGradient));
381  }
382 
383  // high contrast display mode
385  {
387  return (nDrawMode == (DrawModeFlags::SettingsLine|DrawModeFlags::SettingsFill|DrawModeFlags::SettingsText|DrawModeFlags::SettingsGradient));
388  }
389 
390  // access to SdrPageView
392  {
393  return &(mrPageWindow.GetPageView());
394  }
395 
396 
397  // access to OutputDevice
399  {
401 
402  if(pPreRenderDevice)
403  {
404  return &(pPreRenderDevice->GetPreRenderDevice());
405  }
406  else
407  {
409  }
410  }
411 
412  // set all UNO controls displayed in the view to design/alive mode
414  {
415  const sal_uInt32 nCount(getViewObjectContactCount());
416 
417  for(sal_uInt32 a(0); a < nCount; a++)
418  {
420  const ViewObjectContactOfUnoControl* pUnoObjectVOC = dynamic_cast< const ViewObjectContactOfUnoControl* >(pVOC);
421 
422  if(pUnoObjectVOC)
423  {
424  pUnoObjectVOC->setControlDesignMode(_bDesignMode);
425  }
426  }
427  }
428 
429 } // end of namespace
430 
431 /* 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:949
virtual bool AreGluePointsVisible() const override
void intersect(const Range2D &rRange)
void setControlDesignMode(bool _bDesignMode) const
sets the design/alive mode of the control
SdrView & GetView()
Definition: svdpagv.hxx:130
OutputDevice & GetPreRenderDevice()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
virtual bool isDrawModeHighContrast() const override
SdrObject * GetObj(size_t nNum) const
Definition: svdpage.cxx:807
Any GetTime(const OUString &val)
size_t GetObjCount() const
Definition: svdpage.cxx:801
bool IsEmpty() const
Definition: svdlayer.cxx:27
ViewObjectContact & GetViewObjectContact(ObjectContact &rObjectContact)
Definition: viewcontact.cxx:65
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
void SetLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode)
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
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
bool ImpIsGlueVisible() const
Definition: svdpntv.hxx:239
Size GetOutputSizePixel() const
DrawModeFlags GetDrawMode() const
Abstract DrawObject.
Definition: svdobj.hxx:259
void DoProcessDisplay(DisplayInfo &rDisplayInfo)
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:1150
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:117
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:373
virtual bool isDrawModeGray() const override
SvtAccessibilityOptions & getAccessibilityOptions()
Definition: svdview.hxx:233
basegfx::B2DHomMatrix GetViewTransformation() const
virtual SdrObject * getSdrObjectFromSdrObjList() const
Definition: svdpage.cxx:123
OutputDevice & GetOutputDevice() const
DrawModeFlags
SdrPageView & GetPageView() const