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