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