LibreOffice Module svx (master)  1
viewobjectcontactofpageobj.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 <vcl/idle.hxx>
23 #include <svx/svdopage.hxx>
25 #include <svtools/colorcfg.hxx>
31 #include <svx/svdpage.hxx>
32 #include <svx/unoapi.hxx>
35 #include <vcl/canvastools.hxx>
36 
37 using namespace com::sun::star;
38 
39 namespace sdr::contact {
40 
42 {
43 private:
44  // the ViewObjectContactOfPageObj using this painter
46 
47 public:
48  // basic constructor/destructor
50  virtual ~PagePrimitiveExtractor() override;
51 
52  // LazyInvalidate request. Supported here to not automatically
53  // invalidate the second interaction state all the time at the
54  // original OC
55  virtual void setLazyInvalidate(ViewObjectContact& rVOC) override;
56 
57  // From baseclass Timer, the timeout call triggered by the LazyInvalidate mechanism
58  virtual void Invoke() final override;
59 
60  // get primitive visualization
61  drawinglayer::primitive2d::Primitive2DContainer createPrimitive2DSequenceForPage();
62 
63  // Own reaction on changes which will be forwarded to the OC of the owner-VOC
64  virtual void InvalidatePartOfView(const basegfx::B2DRange& rRange) const override;
65 
66  // forward access to SdrPageView of ViewObjectContactOfPageObj
67  virtual bool isOutputToPrinter() const override;
68  virtual bool isOutputToRecordingMetaFile() const override;
69  virtual bool isOutputToPDFFile() const override;
70  virtual bool isDrawModeGray() const override;
71  virtual bool isDrawModeHighContrast() const override;
72  virtual SdrPageView* TryToGetSdrPageView() const override;
73  virtual OutputDevice* TryToGetOutputDevice() const override;
74 };
75 
78 : ObjectContactOfPagePainter(rVOC.GetObjectContact()),
79  mrViewObjectContactOfPageObj(rVOC)
80 {
81  // make this renderer a preview renderer
82  setPreviewRenderer(true);
83 
84  // init timer
85  SetPriority(TaskPriority::HIGH_IDLE);
86  Stop();
87 }
88 
89 PagePrimitiveExtractor::~PagePrimitiveExtractor()
90 {
91  // execute missing LazyInvalidates and stop timer
92  Invoke();
93 }
94 
95 void PagePrimitiveExtractor::setLazyInvalidate(ViewObjectContact& /*rVOC*/)
96 {
97  // do NOT call parent, but remember that something is to do by
98  // starting the LazyInvalidateTimer
99  Start();
100 }
101 
102 // From baseclass Timer, the timeout call triggered by the LazyInvalidate mechanism
103 void PagePrimitiveExtractor::Invoke()
104 {
105  // stop the timer
106  Stop();
107 
108  // invalidate all LazyInvalidate VOCs new situations
109  const sal_uInt32 nVOCCount(getViewObjectContactCount());
110 
111  for(sal_uInt32 a(0); a < nVOCCount; a++)
112  {
113  ViewObjectContact* pCandidate = getViewObjectContact(a);
114  pCandidate->triggerLazyInvalidate();
115  }
116 }
117 
118 drawinglayer::primitive2d::Primitive2DContainer PagePrimitiveExtractor::createPrimitive2DSequenceForPage()
119 {
121  SdrPage* pStartPage = GetStartPage();
122 
123  if(pStartPage)
124  {
125  // update own ViewInformation2D for visualized page
126  const drawinglayer::geometry::ViewInformation2D& rOriginalViewInformation = mrViewObjectContactOfPageObj.GetObjectContact().getViewInformation2D();
127  const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
128  rOriginalViewInformation.getObjectTransformation(),
129  rOriginalViewInformation.getViewTransformation(),
130 
131  // #i101075# use empty range for page content here to force
132  // the content not to be physically clipped in any way. This
133  // would be possible, but would require the internal transformation
134  // which maps between the page visualisation object and the page
135  // content, including the aspect ratios (for details see in
136  // PagePreviewPrimitive2D::create2DDecomposition)
138 
139  GetXDrawPageForSdrPage(pStartPage),
140  0.0, // no time; page previews are not animated
141  rOriginalViewInformation.getExtendedInformationSequence());
142  updateViewInformation2D(aNewViewInformation2D);
143 
144  // create copy of DisplayInfo to set PagePainting
145  DisplayInfo aDisplayInfo;
146 
147  // get page's VOC
148  ViewObjectContact& rDrawPageVOContact = pStartPage->GetViewContact().GetViewObjectContact(*this);
149 
150  // get whole Primitive2DContainer
151  xRetval = rDrawPageVOContact.getPrimitive2DSequenceHierarchy(aDisplayInfo);
152  }
153 
154  return xRetval;
155 }
156 
157 void PagePrimitiveExtractor::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
158 {
159  // an invalidate is called at this view, this needs to be translated to an invalidate
160  // for the using VOC. Coordinates are in page coordinate system.
161  const SdrPage* pStartPage = GetStartPage();
162 
163  if(pStartPage && !rRange.isEmpty())
164  {
165  const basegfx::B2DRange aPageRange(0.0, 0.0, static_cast<double>(pStartPage->GetWidth()), static_cast<double>(pStartPage->GetHeight()));
166 
167  if(rRange.overlaps(aPageRange))
168  {
169  // if object on the page is inside or overlapping with page, create ActionChanged() for
170  // involved VOC
171  mrViewObjectContactOfPageObj.ActionChanged();
172  }
173  }
174 }
175 
176 // forward access to SdrPageView to VOCOfPageObj
177 bool PagePrimitiveExtractor::isOutputToPrinter() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPrinter(); }
178 bool PagePrimitiveExtractor::isOutputToRecordingMetaFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToRecordingMetaFile(); }
179 bool PagePrimitiveExtractor::isOutputToPDFFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPDFFile(); }
180 bool PagePrimitiveExtractor::isDrawModeGray() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeGray(); }
181 bool PagePrimitiveExtractor::isDrawModeHighContrast() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeHighContrast(); }
182 SdrPageView* PagePrimitiveExtractor::TryToGetSdrPageView() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetSdrPageView(); }
183 OutputDevice* PagePrimitiveExtractor::TryToGetOutputDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetOutputDevice(); }
184 
185 drawinglayer::primitive2d::Primitive2DContainer ViewObjectContactOfPageObj::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/) const
186 {
188  const SdrPageObj& rPageObject(static_cast< ViewContactOfPageObj& >(GetViewContact()).GetPageObj());
189  const SdrPage* pPage = rPageObject.GetReferencedPage();
190  const svtools::ColorConfig aColorConfig;
191 
192  // get PageObject's geometry
193  basegfx::B2DHomMatrix aPageObjectTransform;
194  {
195  const tools::Rectangle aPageObjectModelData(rPageObject.GetLastBoundRect());
196  const basegfx::B2DRange aPageObjectBound = vcl::unotools::b2DRectangleFromRectangle(aPageObjectModelData);
197 
198  aPageObjectTransform.set(0, 0, aPageObjectBound.getWidth());
199  aPageObjectTransform.set(1, 1, aPageObjectBound.getHeight());
200  aPageObjectTransform.set(0, 2, aPageObjectBound.getMinX());
201  aPageObjectTransform.set(1, 2, aPageObjectBound.getMinY());
202  }
203 
204  // #i102637# add gray frame also when printing and page exists (handout pages)
205  const bool bCreateGrayFrame(!GetObjectContact().isOutputToPrinter() || pPage);
206 
207  // get displayed page's content. This is the unscaled page content
208  if(mpExtractor && pPage)
209  {
210  // get displayed page's geometry
212  const Size aPageSize(pPage->GetSize());
213  const double fPageWidth(aPageSize.getWidth());
214  const double fPageHeight(aPageSize.getHeight());
215 
216  // The case that a PageObject contains another PageObject which visualizes the
217  // same page again would lead to a recursion. Limit that recursion depth to one
218  // by using a local static bool
219  static bool bInCreatePrimitive2D(false);
220 
221  if(bInCreatePrimitive2D)
222  {
223  // Recursion is possible. Create a replacement primitive
224  xPageContent.resize(2);
225  const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
226  svtools::ColorConfigValue aBorderConfig = aColorConfig.GetColorValue(svtools::DOCBOUNDARIES);
227  const Color aBorderColor = aBorderConfig.bIsVisible ? aBorderConfig.nColor : aDocColor;
228  const basegfx::B2DRange aPageBound(0.0, 0.0, fPageWidth, fPageHeight);
230 
231  // add replacement fill
234 
235  // add replacement border
238  }
239  else
240  {
241  // set recursion flag
242  bInCreatePrimitive2D = true;
243 
244  // init extractor, guarantee existence, set page there
245  mpExtractor->SetStartPage(pPage);
246 
247  // #i105548# also need to copy the VOCRedirector for sub-content creation
248  mpExtractor->SetViewObjectContactRedirector(GetObjectContact().GetViewObjectContactRedirector());
249 
250  // create page content
251  xPageContent = mpExtractor->createPrimitive2DSequenceForPage();
252 
253  // #i105548# reset VOCRedirector to not accidentally have a pointer to a
254  // temporary class, so calls to it are avoided safely
255  mpExtractor->SetViewObjectContactRedirector(nullptr);
256 
257  // reset recursion flag
258  bInCreatePrimitive2D = false;
259  }
260 
261  // prepare retval
262  if(!xPageContent.empty())
263  {
264  const uno::Reference< drawing::XDrawPage > xDrawPage(GetXDrawPageForSdrPage(const_cast< SdrPage*>(pPage)));
266  xDrawPage, aPageObjectTransform, fPageWidth, fPageHeight, xPageContent));
267  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xPagePreview };
268  }
269  }
270  else if(bCreateGrayFrame)
271  {
272  // #i105146# no content, but frame display. To make hitting the page preview objects
273  // on the handout page more simple, add hidden fill geometry
276  aPageObjectTransform));
277  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xFrameHit };
278  }
279 
280  // add a gray outline frame, except not when printing
281  if(bCreateGrayFrame)
282  {
283  const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor);
285  aOwnOutline.transform(aPageObjectTransform);
286 
288  new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOwnOutline, aFrameColor.getBColor()));
289 
290  xRetval.push_back(xGrayFrame);
291  }
292 
293  return xRetval;
294 }
295 
296 ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
297 : ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
298  mpExtractor(new PagePrimitiveExtractor(*this))
299 {
300 }
301 
303 {
304  // delete the helper OC
305  if(mpExtractor)
306  {
307  // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence()
308  // would be called for any reason
309  std::unique_ptr<PagePrimitiveExtractor> pCandidate = std::move(mpExtractor);
310 
311  // also reset the StartPage to avoid ActionChanged() forwardings in the
312  // PagePrimitiveExtractor::InvalidatePartOfView() implementation
313  pCandidate->SetStartPage(nullptr);
314  }
315 }
316 
317 }
318 
319 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual bool isDrawModeHighContrast() const
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
std::unique_ptr< PagePrimitiveExtractor > mpExtractor
sal_Int32 GetHeight() const
Definition: svdpage.cxx:1393
B2DPolygon const & createUnitPolygon()
virtual drawinglayer::primitive2d::Primitive2DContainer getPrimitive2DSequenceHierarchy(DisplayInfo &rDisplayInfo) const
ViewObjectContact & GetViewObjectContact(ObjectContact &rObjectContact)
Definition: viewcontact.cxx:71
const css::uno::Sequence< css::beans::PropertyValue > & getExtendedInformationSequence() const
const basegfx::B2DHomMatrix & getObjectTransformation() const
virtual bool isOutputToPrinter() const
ObjectContact & GetObjectContact() const
bool isEmpty() const
virtual bool isOutputToPDFFile() const
uno_Any a
const drawinglayer::geometry::ViewInformation2D & getViewInformation2D() const
Size GetSize() const
Definition: svdpage.cxx:1362
const basegfx::B2DHomMatrix & getViewTransformation() const
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
ViewObjectContactOfPageObj & mrViewObjectContactOfPageObj
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
virtual bool isOutputToRecordingMetaFile() const
virtual const tools::Rectangle & GetLastBoundRect() const
Definition: svdobj.cxx:868
css::uno::Reference< css::graphic::XPrimitive2D > Primitive2DReference
ColorConfigValue GetColorValue(ColorConfigEntry eEntry, bool bSmart=true) const
SdrPage * GetReferencedPage() const
Definition: svdopage.hxx:54
const sdr::contact::ViewContact & GetViewContact() const
Definition: svdpage.cxx:1100
Primitive2DReference createHiddenGeometryPrimitives2D(const basegfx::B2DHomMatrix &rMatrix)
uno::Reference< drawing::XDrawPage > GetXDrawPageForSdrPage(SdrPage *pPage)
returns a StarOffice API wrapper for the given SdrPage
Definition: unopage.cxx:875
virtual OutputDevice * TryToGetOutputDevice() const
access to OutputDevice. May return 0L like the default implementations do. Override as needed...
basegfx::BColor getBColor() const
aCursorMoveIdle Stop()
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:365
sal_Int32 GetWidth() const
Definition: svdpage.cxx:1367
virtual bool isDrawModeGray() const
bool overlaps(const B2DRange &rRange) const
virtual SdrPageView * TryToGetSdrPageView() const
access to SdrPageView. May return 0L like the default implementations do. Override as needed...