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