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