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  : ObjectContact()
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;
154  pOutDev->Push(PushFlags::CLIPREGION);
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 aLogicClipRange = vcl::unotools::b2DRectangleFromRectangle(aLogicClipRectangle);
191  basegfx::B2DRange aDiscreteClipRange(aLogicClipRange);
192  aDiscreteClipRange.transform(rTargetOutDev.GetViewTransformation());
193 
194  // align the discrete one to discrete boundaries (pixel bounds). Also
195  // expand X and Y max by one due to Rectangle definition source
196  aDiscreteClipRange.expand(basegfx::B2DTuple(
197  floor(aDiscreteClipRange.getMinX()),
198  floor(aDiscreteClipRange.getMinY())));
199  aDiscreteClipRange.expand(basegfx::B2DTuple(
200  1.0 + ceil(aDiscreteClipRange.getMaxX()),
201  1.0 + ceil(aDiscreteClipRange.getMaxY())));
202 
203  // intersect current ViewRange with ClipRange
204  aViewRange.intersect(aDiscreteClipRange);
205  }
206 
207  // transform to world coordinates
208  aViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
209  }
210 
211  // update local ViewInformation2D
212  const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
214  rTargetOutDev.GetViewTransformation(),
215  aViewRange,
217  fCurrentTime,
218  uno::Sequence<beans::PropertyValue>());
219  updateViewInformation2D(aNewViewInformation2D);
220 
222 #if HAVE_FEATURE_DESKTOP || defined( ANDROID )
223  // get whole Primitive2DContainer; this will already make use of updated ViewInformation2D
224  // and may use the MapMode from the Target OutDev in the DisplayInfo
225  xPrimitiveSequence = rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo);
226 #else
227  // Hmm, !HAVE_FEATURE_DESKTOP && !ANDROID means iOS,
228  // right? But does it makes sense to use a different code
229  // path for iOS than for Android; both use tiled rendering
230  // etc now.
231 
232  // HACK: this only works when we are drawing sdr shapes via
233  // drawinglayer; but it can happen that the hierarchy contains
234  // more than just the shapes, and then it fails.
235  //
236  // This is good enough for the tiled rendering for the moment, but
237  // we need to come up with the real solution shortly.
238 
239  // Only get the expensive hierarchy if we can be sure that the
240  // returned sequence won't be empty anyway.
241  bool bGetHierarchy = rRedrawArea.IsEmpty();
242  if (!bGetHierarchy)
243  {
244  // Not empty? Then not doing a full redraw, check if
245  // getPrimitive2DSequenceHierarchy() is still needed.
246  sal_Int32 nObjCount = GetSdrPage()->GetObjCount();
247  for (sal_Int32 i = 0; i < nObjCount; ++i)
248  {
250  if (rRedrawArea.IsOver(pObject->GetCurrentBoundRect()))
251  {
252  bGetHierarchy = true;
253  break;
254  }
255  }
256  }
257 
258  if (bGetHierarchy)
259  // get whole Primitive2DContainer; this will already make use of updated ViewInformation2D
260  // and may use the MapMode from the Target OutDev in the DisplayInfo
261  xPrimitiveSequence = rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo);
262 #endif
263 
264  // if there is something to show, use a primitive processor to render it. There
265  // is a choice between VCL and Canvas processors currently. The decision is made in
266  // createProcessor2DFromOutputDevice and takes into account things like the
267  // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered
268  // currently using the shown boolean. Canvas is not yet the default.
269  if(!xPrimitiveSequence.empty())
270  {
271  // prepare OutputDevice (historical stuff, maybe soon removed)
272  rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing
273  pOutDev->SetLayoutMode(ComplexTextLayoutFlags::Default); // reset, default is no BiDi/RTL
274 
275  // create renderer
276  std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
278  rTargetOutDev, getViewInformation2D()));
279 
280  if(pProcessor2D)
281  {
282  pProcessor2D->process(xPrimitiveSequence);
283  }
284  }
285 
286  // #114359# restore old ClipReghion
287  if(bClipRegionPushed)
288  {
289  pOutDev->Pop();
290  }
291 
292  // Visualize entered groups: Reset to original DrawMode
293  if(bVisualizeEnteredGroup)
294  {
295  rDisplayInfo.ClearGhostedDrawMode();
296  }
297  }
298 
299  // test if visualizing of entered groups is switched on at all
301  {
302  return true;
303  }
304 
305  // get active group's (the entered group) ViewContact
307  {
308  SdrObjList* pActiveGroupList = GetPageWindow().GetPageView().GetObjList();
309 
310  if(pActiveGroupList)
311  {
312  if(nullptr != pActiveGroupList->getSdrPageFromSdrObjList())
313  {
314  // It's a Page itself
315  return &(pActiveGroupList->getSdrPageFromSdrObjList()->GetViewContact());
316  }
317  else if(pActiveGroupList->getSdrObjectFromSdrObjList())
318  {
319  // Group object
320  return &(pActiveGroupList->getSdrObjectFromSdrObjList()->GetViewContact());
321  }
322  }
323  else if(GetSdrPage())
324  {
325  // use page of associated SdrPageView
326  return &(GetSdrPage()->GetViewContact());
327  }
328 
329  return nullptr;
330  }
331 
332  // Invalidate given rectangle at the window/output which is represented by
333  // this ObjectContact.
335  {
336  // invalidate at associated PageWindow
338  }
339 
340  // Get info about the need to visualize GluePoints
342  {
344  }
345 
346  // check if text animation is allowed.
348  {
350  return true;
351  SdrView& rView = GetPageWindow().GetPageView().GetView();
352  const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
353  return rOpt.GetIsAllowAnimatedText();
354  }
355 
356  // check if graphic animation is allowed.
358  {
360  return true;
361  SdrView& rView = GetPageWindow().GetPageView().GetView();
362  const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
363  return rOpt.GetIsAllowAnimatedGraphics();
364  }
365 
366  // print?
368  {
370  }
371 
372  // recording MetaFile?
374  {
376  return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
377  }
378 
379  // pdf export?
381  {
383  }
384 
385  // gray display mode
387  {
389  return (nDrawMode == (DrawModeFlags::GrayLine|DrawModeFlags::GrayFill|DrawModeFlags::BlackText|DrawModeFlags::GrayBitmap|DrawModeFlags::GrayGradient));
390  }
391 
392  // high contrast display mode
394  {
396  return (nDrawMode == (DrawModeFlags::SettingsLine|DrawModeFlags::SettingsFill|DrawModeFlags::SettingsText|DrawModeFlags::SettingsGradient));
397  }
398 
399  // access to SdrPageView
401  {
402  return &(mrPageWindow.GetPageView());
403  }
404 
405 
406  // access to OutputDevice
408  {
410 
411  if(pPreRenderDevice)
412  {
413  return &(pPreRenderDevice->GetPreRenderDevice());
414  }
415  else
416  {
418  }
419  }
420 
421  // set all UNO controls displayed in the view to design/alive mode
423  {
424  const sal_uInt32 nCount(getViewObjectContactCount());
425 
426  for(sal_uInt32 a(0); a < nCount; a++)
427  {
429  const ViewObjectContactOfUnoControl* pUnoObjectVOC = dynamic_cast< const ViewObjectContactOfUnoControl* >(pVOC);
430 
431  if(pUnoObjectVOC)
432  {
433  pUnoObjectVOC->setControlDesignMode(_bDesignMode);
434  }
435  }
436  }
437 
438 } // end of namespace
439 
440 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
basegfx::B2DHomMatrix GetInverseViewTransformation() const
OutDevType GetOutDevType() const
void expand(const B2DTuple &rTuple)
SdrPreRenderDevice * GetPreRenderDevice() const
const vcl::Region & GetRedrawArea() const
Definition: displayinfo.hxx:79
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:853
DrawModeFlags
virtual bool AreGluePointsVisible() const override
void setControlDesignMode(bool _bDesignMode) const
sets the design/alive mode of the control
SdrView & GetView()
Definition: svdpagv.hxx:135
OutputDevice & GetPreRenderDevice()
virtual bool isDrawModeHighContrast() const override
SdrObject * GetObj(size_t nNum) const
Definition: svdpage.cxx:766
Any GetTime(const OUString &val)
virtual drawinglayer::primitive2d::Primitive2DContainer getPrimitive2DSequenceHierarchy(DisplayInfo &rDisplayInfo) const
size_t GetObjCount() const
Definition: svdpage.cxx:760
bool IsEmpty() const
Definition: svdlayer.cxx:25
ViewObjectContact & GetViewObjectContact(ObjectContact &rObjectContact)
Definition: viewcontact.cxx:71
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
double getMaxX() const
void setPreviewRenderer(bool bNew)
std::unique_ptr< BaseProcessor2D > createProcessor2DFromOutputDevice(OutputDevice &rTargetOutDev, const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
sdr::contact::ViewContact & GetViewContact() const
Definition: svdobj.cxx:244
bool IsActive() const
void updateViewInformation2D(const drawinglayer::geometry::ViewInformation2D &rViewInformation2D)
BASEGFX_DLLPUBLIC void transform(const B2DHomMatrix &rMatrix)
OutputDevice & GetTargetOutputDevice()
static bool IsFuzzing()
int nCount
virtual void Start() override
const SdrLayerIDSet & GetProcessLayers() const
Definition: displayinfo.hxx:75
double getMaxY() const
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:174
OUTDEV_PRINTER
bool IsEmpty() const
virtual void setLazyInvalidate(ViewObjectContact &rVOC) override
int i
uno_Any a
const drawinglayer::geometry::ViewInformation2D & getViewInformation2D() const
bool ImpIsGlueVisible()
Definition: svdpntv.hxx:250
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:312
void DoProcessDisplay(DisplayInfo &rDisplayInfo)
void intersect(const B2DRange &rRange)
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
bool IsPause() const
virtual sal_uInt32 GetObjectCount() const
double getMinY() const
void Stop()
sal_uInt32 getViewObjectContactCount() const
const sdr::contact::ViewContact & GetViewContact() const
Definition: svdpage.cxx:1117
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:139
uno::Reference< drawing::XDrawPage > GetXDrawPageForSdrPage(SdrPage *pPage)
returns a StarOffice API wrapper for the given SdrPage
Definition: unopage.cxx:883
virtual bool isOutputToPrinter() const override
virtual bool IsTextAnimationAllowed() const override
virtual const ViewContact * getActiveViewContact() const override
double getMinX() const
void SetPriority(TaskPriority ePriority)
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:366
virtual bool isDrawModeGray() const override
SvtAccessibilityOptions & getAccessibilityOptions()
Definition: svdview.hxx:235
void Push(PushFlags nFlags=PushFlags::ALL)
basegfx::B2DHomMatrix GetViewTransformation() const
virtual SdrObject * getSdrObjectFromSdrObjList() const
Definition: svdpage.cxx:145
OutputDevice & GetOutputDevice() const
SdrPageView & GetPageView() const