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