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 existence, 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