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 #include <svx/sdr/overlay/overlaymanager.hxx> 31 #include <basegfx/point/b2dpoint.hxx> 32 #include <basegfx/range/b2drange.hxx> 33 #include <tools/gen.hxx> 34 #include <vcl/salbtype.hxx> 35 #include <vcl/outdev.hxx> 36 #include <vcl/window.hxx> 37 #include <svx/sdr/overlay/overlayobject.hxx> 38 #include <basegfx/matrix/b2dhommatrix.hxx> 39 #include <drawinglayer/processor2d/baseprocessor2d.hxx> 40 #include <svx/sdr/contact/objectcontacttools.hxx> 41 42 ////////////////////////////////////////////////////////////////////////////// 43 44 using namespace com::sun::star; 45 46 ////////////////////////////////////////////////////////////////////////////// 47 48 namespace sdr 49 { 50 namespace overlay 51 { 52 void OverlayManager::ImpDrawMembers(const basegfx::B2DRange& rRange, OutputDevice& rDestinationDevice) const 53 { 54 const sal_uInt32 nSize(maOverlayObjects.size()); 55 56 if(nSize) 57 { 58 const sal_uInt16 nOriginalAA(rDestinationDevice.GetAntialiasing()); 59 const bool bIsAntiAliasing(getDrawinglayerOpt().IsAntiAliasing()); 60 61 // create processor 62 drawinglayer::processor2d::BaseProcessor2D* pProcessor = ::sdr::contact::createBaseProcessor2DFromOutputDevice( 63 rDestinationDevice, 64 getCurrentViewInformation2D()); 65 66 if(pProcessor) 67 { 68 for(OverlayObjectVector::const_iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++) 69 { 70 OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)"); 71 const OverlayObject& rCandidate = **aIter; 72 73 if(rCandidate.isVisible()) 74 { 75 const drawinglayer::primitive2d::Primitive2DSequence& rSequence = rCandidate.getOverlayObjectPrimitive2DSequence(); 76 77 if(rSequence.hasElements()) 78 { 79 if(rRange.overlaps(rCandidate.getBaseRange())) 80 { 81 if(bIsAntiAliasing && rCandidate.allowsAntiAliase()) 82 { 83 rDestinationDevice.SetAntialiasing(nOriginalAA | ANTIALIASING_ENABLE_B2DDRAW); 84 } 85 else 86 { 87 rDestinationDevice.SetAntialiasing(nOriginalAA & ~ANTIALIASING_ENABLE_B2DDRAW); 88 } 89 90 pProcessor->process(rSequence); 91 } 92 } 93 } 94 } 95 96 delete pProcessor; 97 } 98 99 // restore AA settings 100 rDestinationDevice.SetAntialiasing(nOriginalAA); 101 } 102 } 103 104 void OverlayManager::ImpStripeDefinitionChanged() 105 { 106 const sal_uInt32 nSize(maOverlayObjects.size()); 107 108 if(nSize) 109 { 110 for(OverlayObjectVector::iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++) 111 { 112 OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)"); 113 OverlayObject& rCandidate = **aIter; 114 rCandidate.stripeDefinitionHasChanged(); 115 } 116 } 117 } 118 119 double OverlayManager::getDiscreteOne() const 120 { 121 if(basegfx::fTools::equalZero(mfDiscreteOne)) 122 { 123 const basegfx::B2DVector aDiscreteInLogic(getOutputDevice().GetInverseViewTransformation() * basegfx::B2DVector(1.0, 0.0)); 124 const_cast< OverlayManager* >(this)->mfDiscreteOne = aDiscreteInLogic.getLength(); 125 } 126 127 return mfDiscreteOne; 128 } 129 130 OverlayManager::OverlayManager( 131 OutputDevice& rOutputDevice, 132 OverlayManager* pOldOverlayManager) 133 : Scheduler(), 134 rmOutputDevice(rOutputDevice), 135 maOverlayObjects(), 136 maStripeColorA(Color(COL_BLACK)), 137 maStripeColorB(Color(COL_WHITE)), 138 mnStripeLengthPixel(5), 139 maDrawinglayerOpt(), 140 maViewTransformation(), 141 maViewInformation2D(), 142 mfDiscreteOne(0.0) 143 { 144 // set Property 'ReducedDisplayQuality' to true to allow simpler interaction 145 // visualisations 146 static bool bUseReducedDisplayQualityForDrag(true); 147 148 if(bUseReducedDisplayQualityForDrag) 149 { 150 uno::Sequence< beans::PropertyValue > xProperties(1); 151 xProperties[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedDisplayQuality")); 152 xProperties[0].Value <<= true; 153 maViewInformation2D = drawinglayer::geometry::ViewInformation2D(xProperties); 154 } 155 156 if(pOldOverlayManager) 157 { 158 // take over OverlayObjects from given OverlayManager. Copy 159 // the vector of pointers 160 maOverlayObjects = pOldOverlayManager->maOverlayObjects; 161 const sal_uInt32 nSize(maOverlayObjects.size()); 162 163 if(nSize) 164 { 165 for(OverlayObjectVector::iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++) 166 { 167 OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)"); 168 OverlayObject& rCandidate = **aIter; 169 170 // remove from old and add to new OverlayManager 171 pOldOverlayManager->impApplyRemoveActions(rCandidate); 172 impApplyAddActions(rCandidate); 173 } 174 175 pOldOverlayManager->maOverlayObjects.clear(); 176 } 177 } 178 } 179 180 const drawinglayer::geometry::ViewInformation2D OverlayManager::getCurrentViewInformation2D() const 181 { 182 if(getOutputDevice().GetViewTransformation() != maViewTransformation) 183 { 184 basegfx::B2DRange aViewRange(maViewInformation2D.getViewport()); 185 186 if(OUTDEV_WINDOW == getOutputDevice().GetOutDevType()) 187 { 188 const Size aOutputSizePixel(getOutputDevice().GetOutputSizePixel()); 189 aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight()); 190 aViewRange.transform(getOutputDevice().GetInverseViewTransformation()); 191 } 192 193 OverlayManager* pThis = const_cast< OverlayManager* >(this); 194 195 pThis->maViewTransformation = getOutputDevice().GetViewTransformation(); 196 pThis->maViewInformation2D = drawinglayer::geometry::ViewInformation2D( 197 maViewInformation2D.getObjectTransformation(), 198 maViewTransformation, 199 aViewRange, 200 maViewInformation2D.getVisualizedPage(), 201 maViewInformation2D.getViewTime(), 202 maViewInformation2D.getExtendedInformationSequence()); 203 pThis->mfDiscreteOne = 0.0; 204 } 205 206 return maViewInformation2D; 207 } 208 209 void OverlayManager::impApplyRemoveActions(OverlayObject& rTarget) 210 { 211 // handle evtl. animation 212 if(rTarget.allowsAnimation()) 213 { 214 // remove from event chain 215 RemoveEvent(&rTarget); 216 } 217 218 // make invisible 219 invalidateRange(rTarget.getBaseRange()); 220 221 // clear manager 222 rTarget.mpOverlayManager = 0; 223 } 224 225 void OverlayManager::impApplyAddActions(OverlayObject& rTarget) 226 { 227 // set manager 228 rTarget.mpOverlayManager = this; 229 230 // make visible 231 invalidateRange(rTarget.getBaseRange()); 232 233 // handle evtl. animation 234 if(rTarget.allowsAnimation()) 235 { 236 // Trigger at current time to get alive. This will do the 237 // object-specific next time calculation and hand over adding 238 // again to the scheduler to the animated object, too. This works for 239 // a paused or non-paused animator. 240 rTarget.Trigger(GetTime()); 241 } 242 } 243 244 OverlayManager::~OverlayManager() 245 { 246 // The OverlayManager is not the owner of the OverlayObjects 247 // and thus will not delete them, but remove them. Profit here 248 // from knowing that all will be removed 249 const sal_uInt32 nSize(maOverlayObjects.size()); 250 251 if(nSize) 252 { 253 for(OverlayObjectVector::iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++) 254 { 255 OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)"); 256 OverlayObject& rCandidate = **aIter; 257 impApplyRemoveActions(rCandidate); 258 } 259 260 // erase vector 261 maOverlayObjects.clear(); 262 } 263 } 264 265 void OverlayManager::completeRedraw(const Region& rRegion, OutputDevice* pPreRenderDevice) const 266 { 267 if(!rRegion.IsEmpty() && maOverlayObjects.size()) 268 { 269 // check for changed MapModes. That may influence the 270 // logical size of pixel based OverlayObjects (like BitmapHandles) 271 //ImpCheckMapModeChange(); 272 273 // paint members 274 const Rectangle aRegionBoundRect(rRegion.GetBoundRect()); 275 const basegfx::B2DRange aRegionRange( 276 aRegionBoundRect.Left(), aRegionBoundRect.Top(), 277 aRegionBoundRect.Right(), aRegionBoundRect.Bottom()); 278 279 OutputDevice& rTarget = (pPreRenderDevice) ? *pPreRenderDevice : getOutputDevice(); 280 ImpDrawMembers(aRegionRange, rTarget); 281 } 282 } 283 284 void OverlayManager::flush() 285 { 286 // default has nothing to do 287 } 288 289 // #i68597# part of content gets copied, react on it 290 void OverlayManager::copyArea(const Point& /*rDestPt*/, const Point& /*rSrcPt*/, const Size& /*rSrcSize*/) 291 { 292 // unbuffered versions do nothing here 293 } 294 295 void OverlayManager::restoreBackground(const Region& /*rRegion*/) const 296 { 297 // unbuffered versions do nothing here 298 } 299 300 void OverlayManager::add(OverlayObject& rOverlayObject) 301 { 302 OSL_ENSURE(0 == rOverlayObject.mpOverlayManager, "OverlayObject is added twice to an OverlayManager (!)"); 303 304 // add to the end of chain to preserve display order in paint 305 maOverlayObjects.push_back(&rOverlayObject); 306 307 // execute add actions 308 impApplyAddActions(rOverlayObject); 309 } 310 311 void OverlayManager::remove(OverlayObject& rOverlayObject) 312 { 313 OSL_ENSURE(rOverlayObject.mpOverlayManager == this, "OverlayObject is removed from wrong OverlayManager (!)"); 314 315 // execute remove actions 316 impApplyRemoveActions(rOverlayObject); 317 318 // remove from vector 319 const OverlayObjectVector::iterator aFindResult = ::std::find(maOverlayObjects.begin(), maOverlayObjects.end(), &rOverlayObject); 320 const bool bFound(aFindResult != maOverlayObjects.end()); 321 OSL_ENSURE(bFound, "OverlayObject NOT found at OverlayManager (!)"); 322 323 if(bFound) 324 { 325 maOverlayObjects.erase(aFindResult); 326 } 327 } 328 329 void OverlayManager::invalidateRange(const basegfx::B2DRange& rRange) 330 { 331 if(OUTDEV_WINDOW == getOutputDevice().GetOutDevType()) 332 { 333 if(getDrawinglayerOpt().IsAntiAliasing()) 334 { 335 // assume AA needs one pixel more and invalidate one pixel more 336 const double fDiscreteOne(getDiscreteOne()); 337 const Rectangle aInvalidateRectangle( 338 (sal_Int32)floor(rRange.getMinX() - fDiscreteOne), 339 (sal_Int32)floor(rRange.getMinY() - fDiscreteOne), 340 (sal_Int32)ceil(rRange.getMaxX() + fDiscreteOne), 341 (sal_Int32)ceil(rRange.getMaxY() + fDiscreteOne)); 342 343 // simply invalidate 344 ((Window&)getOutputDevice()).Invalidate(aInvalidateRectangle, INVALIDATE_NOERASE); 345 } 346 else 347 { 348 // #i77674# transform to rectangle. Use floor/ceil to get all covered 349 // discrete pixels, see #i75163# and OverlayManagerBuffered::invalidateRange 350 const Rectangle aInvalidateRectangle( 351 (sal_Int32)floor(rRange.getMinX()), (sal_Int32)floor(rRange.getMinY()), 352 (sal_Int32)ceil(rRange.getMaxX()), (sal_Int32)ceil(rRange.getMaxY())); 353 354 // simply invalidate 355 ((Window&)getOutputDevice()).Invalidate(aInvalidateRectangle, INVALIDATE_NOERASE); 356 } 357 } 358 } 359 360 // stripe support ColA 361 void OverlayManager::setStripeColorA(Color aNew) 362 { 363 if(aNew != maStripeColorA) 364 { 365 maStripeColorA = aNew; 366 ImpStripeDefinitionChanged(); 367 } 368 } 369 370 // stripe support ColB 371 void OverlayManager::setStripeColorB(Color aNew) 372 { 373 if(aNew != maStripeColorB) 374 { 375 maStripeColorB = aNew; 376 ImpStripeDefinitionChanged(); 377 } 378 } 379 380 // stripe support StripeLengthPixel 381 void OverlayManager::setStripeLengthPixel(sal_uInt32 nNew) 382 { 383 if(nNew != mnStripeLengthPixel) 384 { 385 mnStripeLengthPixel = nNew; 386 ImpStripeDefinitionChanged(); 387 } 388 } 389 } // end of namespace overlay 390 } // end of namespace sdr 391 392 ////////////////////////////////////////////////////////////////////////////// 393 // eof 394