bump product version to 7.6.3.2-android
[LibreOffice.git] / svx / source / sdr / contact / viewobjectcontactofpageobj.cxx
blobd66d3852791fc6bf7afea75f000f486e1ea592f5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/idle.hxx>
21 #include <sdr/contact/viewobjectcontactofpageobj.hxx>
22 #include <sdr/contact/viewcontactofpageobj.hxx>
23 #include <svx/svdopage.hxx>
24 #include <svx/sdr/contact/displayinfo.hxx>
25 #include <svtools/colorcfg.hxx>
26 #include <basegfx/polygon/b2dpolygontools.hxx>
27 #include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
28 #include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
29 #include <sdr/contact/objectcontactofobjlistpainter.hxx>
30 #include <basegfx/matrix/b2dhommatrix.hxx>
31 #include <svx/svdpage.hxx>
32 #include <svx/unoapi.hxx>
33 #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
34 #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
35 #include <vcl/canvastools.hxx>
37 using namespace com::sun::star;
39 namespace sdr::contact {
41 class PagePrimitiveExtractor : public ObjectContactOfPagePainter, public Idle
43 private:
44 // the ViewObjectContactOfPageObj using this painter
45 ViewObjectContactOfPageObj& mrViewObjectContactOfPageObj;
47 public:
48 // basic constructor/destructor
49 explicit PagePrimitiveExtractor(ViewObjectContactOfPageObj& rVOC);
50 virtual ~PagePrimitiveExtractor() override;
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;
57 // From baseclass Timer, the timeout call triggered by the LazyInvalidate mechanism
58 virtual void Invoke() final override;
60 // get primitive visualization
61 drawinglayer::primitive2d::Primitive2DContainer createPrimitive2DSequenceForPage();
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;
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 isExportTaggedPDF() const override;
71 virtual ::vcl::PDFExtOutDevData const* GetPDFExtOutDevData() const override;
72 virtual bool isDrawModeGray() const override;
73 virtual bool isDrawModeHighContrast() const override;
74 virtual SdrPageView* TryToGetSdrPageView() const override;
75 virtual OutputDevice* TryToGetOutputDevice() const override;
78 PagePrimitiveExtractor::PagePrimitiveExtractor(
79 ViewObjectContactOfPageObj& rVOC)
80 : ObjectContactOfPagePainter(rVOC.GetObjectContact()), Idle("svx PagePrimitiveExtractor"),
81 mrViewObjectContactOfPageObj(rVOC)
83 // make this renderer a preview renderer
84 setPreviewRenderer(true);
86 // init timer
87 SetPriority(TaskPriority::HIGH_IDLE);
88 Stop();
91 PagePrimitiveExtractor::~PagePrimitiveExtractor()
93 // execute missing LazyInvalidates and stop timer
94 Invoke();
97 void PagePrimitiveExtractor::setLazyInvalidate(ViewObjectContact& /*rVOC*/)
99 // do NOT call parent, but remember that something is to do by
100 // starting the LazyInvalidateTimer
101 Start();
104 // From baseclass Timer, the timeout call triggered by the LazyInvalidate mechanism
105 void PagePrimitiveExtractor::Invoke()
107 // stop the timer
108 Stop();
110 // invalidate all LazyInvalidate VOCs new situations
111 const sal_uInt32 nVOCCount(getViewObjectContactCount());
113 for(sal_uInt32 a(0); a < nVOCCount; a++)
115 ViewObjectContact* pCandidate = getViewObjectContact(a);
116 pCandidate->triggerLazyInvalidate();
120 drawinglayer::primitive2d::Primitive2DContainer PagePrimitiveExtractor::createPrimitive2DSequenceForPage()
122 drawinglayer::primitive2d::Primitive2DContainer xRetval;
123 SdrPage* pStartPage = GetStartPage();
125 if(pStartPage)
127 // update own ViewInformation2D for visualized page
128 const drawinglayer::geometry::ViewInformation2D& rOriginalViewInformation = mrViewObjectContactOfPageObj.GetObjectContact().getViewInformation2D();
129 drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(rOriginalViewInformation);
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)
137 aNewViewInformation2D.setViewport(basegfx::B2DRange());
139 aNewViewInformation2D.setVisualizedPage(GetXDrawPageForSdrPage(pStartPage));
141 // no time; page previews are not animated
142 aNewViewInformation2D.setViewTime(0.0);
144 updateViewInformation2D(aNewViewInformation2D);
146 // create copy of DisplayInfo to set PagePainting
147 DisplayInfo aDisplayInfo;
149 // get page's VOC
150 ViewObjectContact& rDrawPageVOContact = pStartPage->GetViewContact().GetViewObjectContact(*this);
152 // get whole Primitive2DContainer
153 rDrawPageVOContact.getPrimitive2DSequenceHierarchy(aDisplayInfo, xRetval);
156 return xRetval;
159 void PagePrimitiveExtractor::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
161 // an invalidate is called at this view, this needs to be translated to an invalidate
162 // for the using VOC. Coordinates are in page coordinate system.
163 const SdrPage* pStartPage = GetStartPage();
165 if(pStartPage && !rRange.isEmpty())
167 const basegfx::B2DRange aPageRange(0.0, 0.0, static_cast<double>(pStartPage->GetWidth()), static_cast<double>(pStartPage->GetHeight()));
169 if(rRange.overlaps(aPageRange))
171 // if object on the page is inside or overlapping with page, create ActionChanged() for
172 // involved VOC
173 mrViewObjectContactOfPageObj.ActionChanged();
178 // forward access to SdrPageView to VOCOfPageObj
179 bool PagePrimitiveExtractor::isOutputToPrinter() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPrinter(); }
180 bool PagePrimitiveExtractor::isOutputToRecordingMetaFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToRecordingMetaFile(); }
181 bool PagePrimitiveExtractor::isOutputToPDFFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPDFFile(); }
182 bool PagePrimitiveExtractor::isExportTaggedPDF() const { return mrViewObjectContactOfPageObj.GetObjectContact().isExportTaggedPDF(); }
183 ::vcl::PDFExtOutDevData const* PagePrimitiveExtractor::GetPDFExtOutDevData() const { return mrViewObjectContactOfPageObj.GetObjectContact().GetPDFExtOutDevData(); }
184 bool PagePrimitiveExtractor::isDrawModeGray() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeGray(); }
185 bool PagePrimitiveExtractor::isDrawModeHighContrast() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeHighContrast(); }
186 SdrPageView* PagePrimitiveExtractor::TryToGetSdrPageView() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetSdrPageView(); }
187 OutputDevice* PagePrimitiveExtractor::TryToGetOutputDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetOutputDevice(); }
189 void ViewObjectContactOfPageObj::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/, drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const
191 const SdrPageObj& rPageObject(static_cast< ViewContactOfPageObj& >(GetViewContact()).GetPageObj());
192 const SdrPage* pPage = rPageObject.GetReferencedPage();
193 const svtools::ColorConfig aColorConfig;
195 // get PageObject's geometry
196 basegfx::B2DHomMatrix aPageObjectTransform;
198 const tools::Rectangle aPageObjectModelData(rPageObject.GetLastBoundRect());
199 const basegfx::B2DRange aPageObjectBound = vcl::unotools::b2DRectangleFromRectangle(aPageObjectModelData);
201 aPageObjectTransform.set(0, 0, aPageObjectBound.getWidth());
202 aPageObjectTransform.set(1, 1, aPageObjectBound.getHeight());
203 aPageObjectTransform.set(0, 2, aPageObjectBound.getMinX());
204 aPageObjectTransform.set(1, 2, aPageObjectBound.getMinY());
207 // #i102637# add gray frame also when printing and page exists (handout pages)
208 const bool bCreateGrayFrame(!GetObjectContact().isOutputToPrinter() || pPage);
210 // get displayed page's content. This is the unscaled page content
211 if(mpExtractor && pPage)
213 // get displayed page's geometry
214 drawinglayer::primitive2d::Primitive2DContainer xPageContent;
215 const Size aPageSize(pPage->GetSize());
216 const double fPageWidth(aPageSize.getWidth());
217 const double fPageHeight(aPageSize.getHeight());
219 // The case that a PageObject contains another PageObject which visualizes the
220 // same page again would lead to a recursion. Limit that recursion depth to one
221 // by using a local static bool
222 static bool bInCreatePrimitive2D(false);
224 if(bInCreatePrimitive2D)
226 // Recursion is possible. Create a replacement primitive
227 xPageContent.resize(2);
228 const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
229 svtools::ColorConfigValue aBorderConfig = aColorConfig.GetColorValue(svtools::DOCBOUNDARIES);
230 const Color aBorderColor = aBorderConfig.bIsVisible ? aBorderConfig.nColor : aDocColor;
231 const basegfx::B2DRange aPageBound(0.0, 0.0, fPageWidth, fPageHeight);
232 basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aPageBound));
234 // add replacement fill
235 xPageContent[0] = drawinglayer::primitive2d::Primitive2DReference(
236 new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), aDocColor.getBColor()));
238 // add replacement border
239 xPageContent[1] = drawinglayer::primitive2d::Primitive2DReference(
240 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(std::move(aOutline), aBorderColor.getBColor()));
242 else
244 // set recursion flag
245 bInCreatePrimitive2D = true;
247 // init extractor, guarantee existence, set page there
248 mpExtractor->SetStartPage(pPage);
250 // #i105548# also need to copy the VOCRedirector for sub-content creation
251 mpExtractor->SetViewObjectContactRedirector(GetObjectContact().GetViewObjectContactRedirector());
253 // create page content
254 xPageContent = mpExtractor->createPrimitive2DSequenceForPage();
256 // #i105548# reset VOCRedirector to not accidentally have a pointer to a
257 // temporary class, so calls to it are avoided safely
258 mpExtractor->SetViewObjectContactRedirector(nullptr);
260 // reset recursion flag
261 bInCreatePrimitive2D = false;
264 // prepare retval
265 if(!xPageContent.empty())
267 const uno::Reference< drawing::XDrawPage > xDrawPage(GetXDrawPageForSdrPage(const_cast< SdrPage*>(pPage)));
268 const drawinglayer::primitive2d::Primitive2DReference xPagePreview(new drawinglayer::primitive2d::PagePreviewPrimitive2D(
269 xDrawPage, aPageObjectTransform, fPageWidth, fPageHeight, std::move(xPageContent)));
270 rVisitor.visit(xPagePreview);
273 else if(bCreateGrayFrame)
275 // #i105146# no content, but frame display. To make hitting the page preview objects
276 // on the handout page more simple, add hidden fill geometry
277 const drawinglayer::primitive2d::Primitive2DReference xFrameHit(
278 drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
279 aPageObjectTransform));
280 rVisitor.visit(xFrameHit);
283 // add a gray outline frame, except not when printing
284 if(bCreateGrayFrame)
286 const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor);
287 basegfx::B2DPolygon aOwnOutline(basegfx::utils::createUnitPolygon());
288 aOwnOutline.transform(aPageObjectTransform);
290 const drawinglayer::primitive2d::Primitive2DReference xGrayFrame(
291 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(std::move(aOwnOutline), aFrameColor.getBColor()));
293 rVisitor.visit(xGrayFrame);
297 ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
298 : ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
299 mpExtractor(new PagePrimitiveExtractor(*this))
303 ViewObjectContactOfPageObj::~ViewObjectContactOfPageObj()
305 // delete the helper OC
306 if(mpExtractor)
308 // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence()
309 // would be called for any reason
310 std::unique_ptr<PagePrimitiveExtractor> pCandidate = std::move(mpExtractor);
312 // also reset the StartPage to avoid ActionChanged() forwardings in the
313 // PagePrimitiveExtractor::InvalidatePartOfView() implementation
314 pCandidate->SetStartPage(nullptr);
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */