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  updateViewInformation2D(aNewViewInformation2D);
142 
143  // create copy of DisplayInfo to set PagePainting
144  DisplayInfo aDisplayInfo;
145 
146  // get page's VOC
147  ViewObjectContact& rDrawPageVOContact = pStartPage->GetViewContact().GetViewObjectContact(*this);
148 
149  // get whole Primitive2DContainer
150  rDrawPageVOContact.getPrimitive2DSequenceHierarchy(aDisplayInfo, xRetval);
151  }
152 
153  return xRetval;
154 }
155 
156 void PagePrimitiveExtractor::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
157 {
158  // an invalidate is called at this view, this needs to be translated to an invalidate
159  // for the using VOC. Coordinates are in page coordinate system.
160  const SdrPage* pStartPage = GetStartPage();
161 
162  if(pStartPage && !rRange.isEmpty())
163  {
164  const basegfx::B2DRange aPageRange(0.0, 0.0, static_cast<double>(pStartPage->GetWidth()), static_cast<double>(pStartPage->GetHeight()));
165 
166  if(rRange.overlaps(aPageRange))
167  {
168  // if object on the page is inside or overlapping with page, create ActionChanged() for
169  // involved VOC
170  mrViewObjectContactOfPageObj.ActionChanged();
171  }
172  }
173 }
174 
175 // forward access to SdrPageView to VOCOfPageObj
176 bool PagePrimitiveExtractor::isOutputToPrinter() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPrinter(); }
177 bool PagePrimitiveExtractor::isOutputToRecordingMetaFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToRecordingMetaFile(); }
178 bool PagePrimitiveExtractor::isOutputToPDFFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPDFFile(); }
179 bool PagePrimitiveExtractor::isDrawModeGray() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeGray(); }
180 bool PagePrimitiveExtractor::isDrawModeHighContrast() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeHighContrast(); }
181 SdrPageView* PagePrimitiveExtractor::TryToGetSdrPageView() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetSdrPageView(); }
182 OutputDevice* PagePrimitiveExtractor::TryToGetOutputDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetOutputDevice(); }
183 
184 drawinglayer::primitive2d::Primitive2DContainer ViewObjectContactOfPageObj::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/) const
185 {
187  const SdrPageObj& rPageObject(static_cast< ViewContactOfPageObj& >(GetViewContact()).GetPageObj());
188  const SdrPage* pPage = rPageObject.GetReferencedPage();
189  const svtools::ColorConfig aColorConfig;
190 
191  // get PageObject's geometry
192  basegfx::B2DHomMatrix aPageObjectTransform;
193  {
194  const tools::Rectangle aPageObjectModelData(rPageObject.GetLastBoundRect());
195  const basegfx::B2DRange aPageObjectBound = vcl::unotools::b2DRectangleFromRectangle(aPageObjectModelData);
196 
197  aPageObjectTransform.set(0, 0, aPageObjectBound.getWidth());
198  aPageObjectTransform.set(1, 1, aPageObjectBound.getHeight());
199  aPageObjectTransform.set(0, 2, aPageObjectBound.getMinX());
200  aPageObjectTransform.set(1, 2, aPageObjectBound.getMinY());
201  }
202 
203  // #i102637# add gray frame also when printing and page exists (handout pages)
204  const bool bCreateGrayFrame(!GetObjectContact().isOutputToPrinter() || pPage);
205 
206  // get displayed page's content. This is the unscaled page content
207  if(mpExtractor && pPage)
208  {
209  // get displayed page's geometry
211  const Size aPageSize(pPage->GetSize());
212  const double fPageWidth(aPageSize.getWidth());
213  const double fPageHeight(aPageSize.getHeight());
214 
215  // The case that a PageObject contains another PageObject which visualizes the
216  // same page again would lead to a recursion. Limit that recursion depth to one
217  // by using a local static bool
218  static bool bInCreatePrimitive2D(false);
219 
220  if(bInCreatePrimitive2D)
221  {
222  // Recursion is possible. Create a replacement primitive
223  xPageContent.resize(2);
224  const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
225  svtools::ColorConfigValue aBorderConfig = aColorConfig.GetColorValue(svtools::DOCBOUNDARIES);
226  const Color aBorderColor = aBorderConfig.bIsVisible ? aBorderConfig.nColor : aDocColor;
227  const basegfx::B2DRange aPageBound(0.0, 0.0, fPageWidth, fPageHeight);
229 
230  // add replacement fill
233 
234  // add replacement border
237  }
238  else
239  {
240  // set recursion flag
241  bInCreatePrimitive2D = true;
242 
243  // init extractor, guarantee existence, set page there
244  mpExtractor->SetStartPage(pPage);
245 
246  // #i105548# also need to copy the VOCRedirector for sub-content creation
247  mpExtractor->SetViewObjectContactRedirector(GetObjectContact().GetViewObjectContactRedirector());
248 
249  // create page content
250  xPageContent = mpExtractor->createPrimitive2DSequenceForPage();
251 
252  // #i105548# reset VOCRedirector to not accidentally have a pointer to a
253  // temporary class, so calls to it are avoided safely
254  mpExtractor->SetViewObjectContactRedirector(nullptr);
255 
256  // reset recursion flag
257  bInCreatePrimitive2D = false;
258  }
259 
260  // prepare retval
261  if(!xPageContent.empty())
262  {
263  const uno::Reference< drawing::XDrawPage > xDrawPage(GetXDrawPageForSdrPage(const_cast< SdrPage*>(pPage)));
265  xDrawPage, aPageObjectTransform, fPageWidth, fPageHeight, xPageContent));
266  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xPagePreview };
267  }
268  }
269  else if(bCreateGrayFrame)
270  {
271  // #i105146# no content, but frame display. To make hitting the page preview objects
272  // on the handout page more simple, add hidden fill geometry
275  aPageObjectTransform));
276  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xFrameHit };
277  }
278 
279  // add a gray outline frame, except not when printing
280  if(bCreateGrayFrame)
281  {
282  const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor);
284  aOwnOutline.transform(aPageObjectTransform);
285 
287  new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOwnOutline, aFrameColor.getBColor()));
288 
289  xRetval.push_back(xGrayFrame);
290  }
291 
292  return xRetval;
293 }
294 
295 ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
296 : ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
297  mpExtractor(new PagePrimitiveExtractor(*this))
298 {
299 }
300 
302 {
303  // delete the helper OC
304  if(mpExtractor)
305  {
306  // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence()
307  // would be called for any reason
308  std::unique_ptr<PagePrimitiveExtractor> pCandidate = std::move(mpExtractor);
309 
310  // also reset the StartPage to avoid ActionChanged() forwardings in the
311  // PagePrimitiveExtractor::InvalidatePartOfView() implementation
312  pCandidate->SetStartPage(nullptr);
313  }
314 }
315 
316 }
317 
318 /* 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:1454
B2DPolygon const & createUnitPolygon()
ViewObjectContact & GetViewObjectContact(ObjectContact &rObjectContact)
Definition: viewcontact.cxx:64
const basegfx::B2DHomMatrix & getObjectTransformation() const
virtual bool isOutputToPrinter() const
ObjectContact & GetObjectContact() const
bool isEmpty() const
virtual bool isOutputToPDFFile() const
virtual void getPrimitive2DSequenceHierarchy(DisplayInfo &rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor &rVisitor) const
uno_Any a
const drawinglayer::geometry::ViewInformation2D & getViewInformation2D() const
Size GetSize() const
Definition: svdpage.cxx:1423
const basegfx::B2DHomMatrix & getViewTransformation() const
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
ViewObjectContactOfPageObj & mrViewObjectContactOfPageObj
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
virtual bool isOutputToRecordingMetaFile() const
virtual const tools::Rectangle & GetLastBoundRect() const
Definition: svdobj.cxx:971
css::uno::Reference< css::graphic::XPrimitive2D > Primitive2DReference
ColorConfigValue GetColorValue(ColorConfigEntry eEntry, bool bSmart=true) const
SdrPage * GetReferencedPage() const
Definition: svdopage.hxx:55
const sdr::contact::ViewContact & GetViewContact() const
Definition: svdpage.cxx:1165
Primitive2DReference createHiddenGeometryPrimitives2D(const basegfx::B2DHomMatrix &rMatrix)
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:1428
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...