Branch data 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 : 11 : PagePrimitiveExtractor::PagePrimitiveExtractor(
84 : : ViewObjectContactOfPageObj& rVOC)
85 : 11 : : ObjectContactOfPagePainter(0, rVOC.GetObjectContact()),
86 [ + - ]: 11 : mrViewObjectContactOfPageObj(rVOC)
87 : : {
88 : : // make this renderer a preview renderer
89 : 11 : setPreviewRenderer(true);
90 : :
91 : : // init timer
92 [ + - ]: 11 : SetTimeout(1);
93 [ + - ]: 11 : Stop();
94 : 11 : }
95 : :
96 [ + - ]: 11 : PagePrimitiveExtractor::~PagePrimitiveExtractor()
97 : : {
98 : : // execute missing LazyInvalidates and stop timer
99 [ + - ]: 11 : Timeout();
100 [ - + ]: 22 : }
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 : 11 : void PagePrimitiveExtractor::Timeout()
111 : : {
112 : : // stop the timer
113 : 11 : Stop();
114 : :
115 : : // invalidate all LazyInvalidate VOCs new situations
116 : 11 : const sal_uInt32 nVOCCount(getViewObjectContactCount());
117 : :
118 [ - + ]: 11 : for(sal_uInt32 a(0); a < nVOCCount; a++)
119 : : {
120 : 0 : ViewObjectContact* pCandidate = getViewObjectContact(a);
121 : 0 : pCandidate->triggerLazyInvalidate();
122 : : }
123 : 11 : }
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 : 11 : ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
317 : : : ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
318 [ + - ][ + - ]: 11 : mpExtractor(new PagePrimitiveExtractor(*this))
319 : : {
320 : 11 : }
321 : :
322 : 11 : ViewObjectContactOfPageObj::~ViewObjectContactOfPageObj()
323 : : {
324 : : // delete the helper OC
325 [ + - ]: 11 : if(mpExtractor)
326 : : {
327 : : // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence()
328 : : // would be called for any reason
329 : 11 : PagePrimitiveExtractor* pCandidate = mpExtractor;
330 : 11 : mpExtractor = 0;
331 : :
332 : : // also reset the StartPage to avoid ActionChanged() forwardings in the
333 : : // PagePrimitiveExtractor::InvalidatePartOfView() implementation
334 [ + - ]: 11 : pCandidate->SetStartPage(0);
335 [ + - ][ + - ]: 11 : delete pCandidate;
336 : : }
337 [ - + ]: 22 : }
338 : : } // end of namespace contact
339 : : } // end of namespace sdr
340 : :
341 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|