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