Line data Source code
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 :
21 : #include <svx/sdr/contact/viewobjectcontactofpageobj.hxx>
22 : #include <svx/sdr/contact/viewcontactofpageobj.hxx>
23 : #include <svx/svdopage.hxx>
24 : #include <svx/sdr/contact/displayinfo.hxx>
25 : #include <basegfx/polygon/b2dpolygontools.hxx>
26 : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
27 : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
28 : #include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
29 : #include <basegfx/matrix/b2dhommatrix.hxx>
30 : #include <svx/svdpage.hxx>
31 : #include <svx/unoapi.hxx>
32 : #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
33 : #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
34 :
35 : //////////////////////////////////////////////////////////////////////////////
36 :
37 : using namespace com::sun::star;
38 :
39 : //////////////////////////////////////////////////////////////////////////////
40 :
41 : namespace sdr
42 : {
43 : namespace contact
44 : {
45 : class PagePrimitiveExtractor : public ObjectContactOfPagePainter, public Timer
46 : {
47 : private:
48 : // the ViewObjectContactOfPageObj using this painter
49 : ViewObjectContactOfPageObj& mrViewObjectContactOfPageObj;
50 :
51 : public:
52 : // basic constructor/destructor
53 : explicit PagePrimitiveExtractor(ViewObjectContactOfPageObj& rVOC);
54 : virtual ~PagePrimitiveExtractor();
55 :
56 : // LazyInvalidate request. Supported here to not automatically
57 : // invalidate the second interaction state all the time at the
58 : // original OC
59 : virtual void setLazyInvalidate(ViewObjectContact& rVOC);
60 :
61 : // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
62 : virtual void Timeout();
63 :
64 : // get primitive visualization
65 : drawinglayer::primitive2d::Primitive2DSequence createPrimitive2DSequenceForPage(const DisplayInfo& rDisplayInfo);
66 :
67 : // Own reaction on changes which will be forwarded to the OC of the owner-VOC
68 : virtual void InvalidatePartOfView(const basegfx::B2DRange& rRange) const;
69 :
70 : // forward access to SdrPageView of ViewObjectContactOfPageObj
71 : virtual bool isOutputToPrinter() const;
72 : virtual bool isOutputToWindow() const;
73 : virtual bool isOutputToVirtualDevice() const;
74 : virtual bool isOutputToRecordingMetaFile() const;
75 : virtual bool isOutputToPDFFile() const;
76 : virtual bool isDrawModeGray() const;
77 : virtual bool isDrawModeBlackWhite() const;
78 : virtual bool isDrawModeHighContrast() const;
79 : virtual SdrPageView* TryToGetSdrPageView() const;
80 : virtual OutputDevice* TryToGetOutputDevice() const;
81 : };
82 :
83 0 : PagePrimitiveExtractor::PagePrimitiveExtractor(
84 : ViewObjectContactOfPageObj& rVOC)
85 0 : : ObjectContactOfPagePainter(0, rVOC.GetObjectContact()),
86 0 : mrViewObjectContactOfPageObj(rVOC)
87 : {
88 : // make this renderer a preview renderer
89 0 : setPreviewRenderer(true);
90 :
91 : // init timer
92 0 : SetTimeout(1);
93 0 : Stop();
94 0 : }
95 :
96 0 : PagePrimitiveExtractor::~PagePrimitiveExtractor()
97 : {
98 : // execute missing LazyInvalidates and stop timer
99 0 : Timeout();
100 0 : }
101 :
102 0 : void PagePrimitiveExtractor::setLazyInvalidate(ViewObjectContact& /*rVOC*/)
103 : {
104 : // do NOT call parent, but remember that something is to do by
105 : // starting the LazyInvalidateTimer
106 0 : Start();
107 0 : }
108 :
109 : // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
110 0 : void PagePrimitiveExtractor::Timeout()
111 : {
112 : // stop the timer
113 0 : Stop();
114 :
115 : // invalidate all LazyInvalidate VOCs new situations
116 0 : const sal_uInt32 nVOCCount(getViewObjectContactCount());
117 :
118 0 : for(sal_uInt32 a(0); a < nVOCCount; a++)
119 : {
120 0 : ViewObjectContact* pCandidate = getViewObjectContact(a);
121 0 : pCandidate->triggerLazyInvalidate();
122 : }
123 0 : }
124 :
125 0 : drawinglayer::primitive2d::Primitive2DSequence PagePrimitiveExtractor::createPrimitive2DSequenceForPage(const DisplayInfo& /*rDisplayInfo*/)
126 : {
127 0 : drawinglayer::primitive2d::Primitive2DSequence xRetval;
128 0 : const SdrPage* pStartPage = GetStartPage();
129 :
130 0 : if(pStartPage)
131 : {
132 : // update own ViewInformation2D for visualized page
133 0 : const drawinglayer::geometry::ViewInformation2D& rOriginalViewInformation = mrViewObjectContactOfPageObj.GetObjectContact().getViewInformation2D();
134 : const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
135 0 : rOriginalViewInformation.getObjectTransformation(),
136 0 : rOriginalViewInformation.getViewTransformation(),
137 :
138 : // #i101075# use empty range for page content here to force
139 : // the content not to be physically clipped in any way. This
140 : // would be possible, but would require the internal transformation
141 : // which maps between the page visualisation object and the page
142 : // content, including the aspect ratios (for details see in
143 : // PagePreviewPrimitive2D::create2DDecomposition)
144 : basegfx::B2DRange(),
145 :
146 : GetXDrawPageForSdrPage(const_cast< SdrPage* >(pStartPage)),
147 : 0.0, // no time; page previews are not animated
148 0 : rOriginalViewInformation.getExtendedInformationSequence());
149 0 : updateViewInformation2D(aNewViewInformation2D);
150 :
151 : // create copy of DisplayInfo to set PagePainting
152 0 : DisplayInfo aDisplayInfo;
153 :
154 : // get page's VOC
155 0 : ViewObjectContact& rDrawPageVOContact = pStartPage->GetViewContact().GetViewObjectContact(*this);
156 :
157 : // get whole Primitive2DSequence
158 0 : xRetval = rDrawPageVOContact.getPrimitive2DSequenceHierarchy(aDisplayInfo);
159 : }
160 :
161 0 : return xRetval;
162 : }
163 :
164 0 : void PagePrimitiveExtractor::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
165 : {
166 : // an invalidate is called at this view, this needs to be translated to an invalidate
167 : // for the using VOC. Coordinates are in page coordinate system.
168 0 : const SdrPage* pStartPage = GetStartPage();
169 :
170 0 : if(pStartPage && !rRange.isEmpty())
171 : {
172 0 : const basegfx::B2DRange aPageRange(0.0, 0.0, (double)pStartPage->GetWdt(), (double)pStartPage->GetHgt());
173 :
174 0 : if(rRange.overlaps(aPageRange))
175 : {
176 : // if object on the page is inside or overlapping with page, create ActionChanged() for
177 : // involved VOC
178 0 : mrViewObjectContactOfPageObj.ActionChanged();
179 : }
180 : }
181 0 : }
182 :
183 : // forward access to SdrPageView to VOCOfPageObj
184 0 : bool PagePrimitiveExtractor::isOutputToPrinter() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPrinter(); }
185 0 : bool PagePrimitiveExtractor::isOutputToWindow() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToWindow(); }
186 0 : bool PagePrimitiveExtractor::isOutputToVirtualDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToVirtualDevice(); }
187 0 : bool PagePrimitiveExtractor::isOutputToRecordingMetaFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToRecordingMetaFile(); }
188 0 : bool PagePrimitiveExtractor::isOutputToPDFFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPDFFile(); }
189 0 : bool PagePrimitiveExtractor::isDrawModeGray() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeGray(); }
190 0 : bool PagePrimitiveExtractor::isDrawModeBlackWhite() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeBlackWhite(); }
191 0 : bool PagePrimitiveExtractor::isDrawModeHighContrast() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeHighContrast(); }
192 0 : SdrPageView* PagePrimitiveExtractor::TryToGetSdrPageView() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetSdrPageView(); }
193 0 : OutputDevice* PagePrimitiveExtractor::TryToGetOutputDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetOutputDevice(); }
194 : } // end of namespace contact
195 : } // end of namespace sdr
196 :
197 : //////////////////////////////////////////////////////////////////////////////
198 :
199 : namespace sdr
200 : {
201 : namespace contact
202 : {
203 0 : drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfPageObj::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
204 : {
205 0 : drawinglayer::primitive2d::Primitive2DSequence xRetval;
206 0 : const SdrPageObj& rPageObject((static_cast< ViewContactOfPageObj& >(GetViewContact())).GetPageObj());
207 0 : const SdrPage* pPage = rPageObject.GetReferencedPage();
208 0 : const svtools::ColorConfig aColorConfig;
209 :
210 : // get PageObject's geometry
211 0 : basegfx::B2DHomMatrix aPageObjectTransform;
212 : {
213 0 : const Rectangle aPageObjectModelData(rPageObject.GetLastBoundRect());
214 : const basegfx::B2DRange aPageObjectBound(
215 0 : aPageObjectModelData.Left(), aPageObjectModelData.Top(),
216 0 : aPageObjectModelData.Right(), aPageObjectModelData.Bottom());
217 :
218 0 : aPageObjectTransform.set(0, 0, aPageObjectBound.getWidth());
219 0 : aPageObjectTransform.set(1, 1, aPageObjectBound.getHeight());
220 0 : aPageObjectTransform.set(0, 2, aPageObjectBound.getMinX());
221 0 : aPageObjectTransform.set(1, 2, aPageObjectBound.getMinY());
222 : }
223 :
224 : // #i102637# add gray frame also when printing and page exists (handout pages)
225 0 : const bool bCreateGrayFrame(!GetObjectContact().isOutputToPrinter() || pPage);
226 :
227 : // get displayed page's content. This is the uscaled page content
228 0 : if(mpExtractor && pPage)
229 : {
230 : // get displayed page's geometry
231 0 : drawinglayer::primitive2d::Primitive2DSequence xPageContent;
232 0 : const Size aPageSize(pPage->GetSize());
233 0 : const double fPageWidth(aPageSize.getWidth());
234 0 : const double fPageHeight(aPageSize.getHeight());
235 :
236 : // The case that a PageObject contains another PageObject which visualizes the
237 : // same page again would lead to a recursion. Limit that recursion depth to one
238 : // by using a local static bool
239 : static bool bInCreatePrimitive2D(false);
240 :
241 0 : if(bInCreatePrimitive2D)
242 : {
243 : // Recursion is possible. Create a replacement primitive
244 0 : xPageContent.realloc(2);
245 0 : const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
246 0 : const Color aBorderColor(aColorConfig.GetColorValue(svtools::DOCBOUNDARIES).nColor);
247 0 : const basegfx::B2DRange aPageBound(0.0, 0.0, fPageWidth, fPageHeight);
248 0 : const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aPageBound));
249 :
250 : // add replacement fill
251 0 : xPageContent[0L] = drawinglayer::primitive2d::Primitive2DReference(
252 0 : new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), aDocColor.getBColor()));
253 :
254 : // add replacement border
255 0 : xPageContent[1L] = drawinglayer::primitive2d::Primitive2DReference(
256 0 : new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aBorderColor.getBColor()));
257 : }
258 : else
259 : {
260 : // set recursion flag
261 0 : bInCreatePrimitive2D = true;
262 :
263 : // init extractor, guarantee existance, set page there
264 0 : mpExtractor->SetStartPage(pPage);
265 :
266 : // #i105548# also need to copy the VOCRedirector for sub-content creation
267 0 : mpExtractor->SetViewObjectContactRedirector(GetObjectContact().GetViewObjectContactRedirector());
268 :
269 : // create page content
270 0 : xPageContent = mpExtractor->createPrimitive2DSequenceForPage(rDisplayInfo);
271 :
272 : // #i105548# reset VOCRedirector to not accidentially have a pointer to a
273 : // temporary class, so calls to it are avoided safely
274 0 : mpExtractor->SetViewObjectContactRedirector(0);
275 :
276 : // reset recursion flag
277 0 : bInCreatePrimitive2D = false;
278 : }
279 :
280 : // prepare retval
281 0 : if(xPageContent.hasElements())
282 : {
283 0 : const uno::Reference< drawing::XDrawPage > xDrawPage(GetXDrawPageForSdrPage(const_cast< SdrPage*>(pPage)));
284 : const drawinglayer::primitive2d::Primitive2DReference xPagePreview(new drawinglayer::primitive2d::PagePreviewPrimitive2D(
285 0 : xDrawPage, aPageObjectTransform, fPageWidth, fPageHeight, xPageContent, true));
286 0 : xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPagePreview, 1);
287 0 : }
288 : }
289 0 : else if(bCreateGrayFrame)
290 : {
291 : // #i105146# no content, but frame display. To make hitting the page preview objects
292 : // on the handout page more simple, add hidden fill geometry
293 : const drawinglayer::primitive2d::Primitive2DReference xFrameHit(
294 : drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
295 : false,
296 0 : aPageObjectTransform));
297 0 : xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xFrameHit, 1);
298 : }
299 :
300 : // add a gray outline frame, except not when printing
301 0 : if(bCreateGrayFrame)
302 : {
303 0 : const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor);
304 0 : basegfx::B2DPolygon aOwnOutline(basegfx::tools::createUnitPolygon());
305 0 : aOwnOutline.transform(aPageObjectTransform);
306 :
307 : const drawinglayer::primitive2d::Primitive2DReference xGrayFrame(
308 0 : new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOwnOutline, aFrameColor.getBColor()));
309 :
310 0 : drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xGrayFrame);
311 : }
312 :
313 0 : return xRetval;
314 : }
315 :
316 0 : ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
317 : : ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
318 0 : mpExtractor(new PagePrimitiveExtractor(*this))
319 : {
320 0 : }
321 :
322 0 : ViewObjectContactOfPageObj::~ViewObjectContactOfPageObj()
323 : {
324 : // delete the helper OC
325 0 : if(mpExtractor)
326 : {
327 : // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence()
328 : // would be called for any reason
329 0 : PagePrimitiveExtractor* pCandidate = mpExtractor;
330 0 : mpExtractor = 0;
331 :
332 : // also reset the StartPage to avoid ActionChanged() forwardings in the
333 : // PagePrimitiveExtractor::InvalidatePartOfView() implementation
334 0 : pCandidate->SetStartPage(0);
335 0 : delete pCandidate;
336 : }
337 0 : }
338 : } // end of namespace contact
339 : } // end of namespace sdr
340 :
341 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|