Bump version to 6.4-15
[LibreOffice.git] / svx / source / sdr / overlay / overlaymanager.cxx
blob26671f8fb1e2d637be7cc23cf61f4e8cfc160bd8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/sdr/overlay/overlaymanager.hxx>
21 #include <basegfx/point/b2dpoint.hxx>
22 #include <basegfx/range/b2drange.hxx>
23 #include <tools/gen.hxx>
24 #include <vcl/canvastools.hxx>
25 #include <vcl/outdev.hxx>
26 #include <vcl/window.hxx>
27 #include <svx/sdr/overlay/overlayobject.hxx>
28 #include <basegfx/matrix/b2dhommatrix.hxx>
29 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
30 #include <drawinglayer/processor2d/processor2dtools.hxx>
31 #include <memory>
34 using namespace com::sun::star;
37 namespace sdr
39 namespace overlay
41 void OverlayManager::ImpDrawMembers(const basegfx::B2DRange& rRange, OutputDevice& rDestinationDevice) const
43 const sal_uInt32 nSize(maOverlayObjects.size());
45 if(nSize)
47 const AntialiasingFlags nOriginalAA(rDestinationDevice.GetAntialiasing());
48 const bool bIsAntiAliasing(getDrawinglayerOpt().IsAntiAliasing());
50 // create processor
51 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice(
52 rDestinationDevice,
53 getCurrentViewInformation2D()));
55 if(pProcessor)
57 for(const auto& rpOverlayObject : maOverlayObjects)
59 OSL_ENSURE(rpOverlayObject, "Corrupted OverlayObject List (!)");
60 const OverlayObject& rCandidate = *rpOverlayObject;
62 if(rCandidate.isVisible())
64 const drawinglayer::primitive2d::Primitive2DContainer& rSequence = rCandidate.getOverlayObjectPrimitive2DSequence();
66 if(!rSequence.empty())
68 if(rRange.overlaps(rCandidate.getBaseRange()))
70 if(bIsAntiAliasing && rCandidate.allowsAntiAliase())
72 rDestinationDevice.SetAntialiasing(nOriginalAA | AntialiasingFlags::EnableB2dDraw);
74 else
76 rDestinationDevice.SetAntialiasing(nOriginalAA & ~AntialiasingFlags::EnableB2dDraw);
79 pProcessor->process(rSequence);
85 pProcessor.reset();
88 // restore AA settings
89 rDestinationDevice.SetAntialiasing(nOriginalAA);
93 void OverlayManager::ImpStripeDefinitionChanged()
95 const sal_uInt32 nSize(maOverlayObjects.size());
97 if(nSize)
99 for(const auto& rpOverlayObject : maOverlayObjects)
101 OSL_ENSURE(rpOverlayObject, "Corrupted OverlayObject List (!)");
102 OverlayObject& rCandidate = *rpOverlayObject;
103 rCandidate.stripeDefinitionHasChanged();
108 double OverlayManager::getDiscreteOne() const
110 if(basegfx::fTools::equalZero(mfDiscreteOne))
112 const basegfx::B2DVector aDiscreteInLogic(getOutputDevice().GetInverseViewTransformation() * basegfx::B2DVector(1.0, 0.0));
113 const_cast< OverlayManager* >(this)->mfDiscreteOne = aDiscreteInLogic.getLength();
116 return mfDiscreteOne;
119 OverlayManager::OverlayManager(OutputDevice& rOutputDevice)
120 : Scheduler(),
121 mrOutputDevice(rOutputDevice),
122 maOverlayObjects(),
123 maStripeColorA(COL_BLACK),
124 maStripeColorB(COL_WHITE),
125 mnStripeLengthPixel(5),
126 maDrawinglayerOpt(),
127 maViewTransformation(),
128 maViewInformation2D(),
129 mfDiscreteOne(0.0)
131 // set Property 'ReducedDisplayQuality' to true to allow simpler interaction
132 // visualisations
133 uno::Sequence< beans::PropertyValue > xProperties(1);
134 xProperties[0].Name = "ReducedDisplayQuality";
135 xProperties[0].Value <<= true;
136 maViewInformation2D = drawinglayer::geometry::ViewInformation2D(xProperties);
139 rtl::Reference<OverlayManager> OverlayManager::create(OutputDevice& rOutputDevice)
141 return rtl::Reference<OverlayManager>(new OverlayManager(rOutputDevice));
144 drawinglayer::geometry::ViewInformation2D const & OverlayManager::getCurrentViewInformation2D() const
146 if(getOutputDevice().GetViewTransformation() != maViewTransformation)
148 basegfx::B2DRange aViewRange(maViewInformation2D.getViewport());
150 if(OUTDEV_WINDOW == getOutputDevice().GetOutDevType())
152 const Size aOutputSizePixel(getOutputDevice().GetOutputSizePixel());
154 // only set when we *have* an output size, else let aViewRange
155 // stay on empty
156 if(aOutputSizePixel.Width() && aOutputSizePixel.Height())
158 aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
159 aViewRange.transform(getOutputDevice().GetInverseViewTransformation());
163 OverlayManager* pThis = const_cast< OverlayManager* >(this);
165 pThis->maViewTransformation = getOutputDevice().GetViewTransformation();
166 pThis->maViewInformation2D = drawinglayer::geometry::ViewInformation2D(
167 maViewInformation2D.getObjectTransformation(),
168 maViewTransformation,
169 aViewRange,
170 maViewInformation2D.getVisualizedPage(),
171 maViewInformation2D.getViewTime(),
172 maViewInformation2D.getExtendedInformationSequence());
173 pThis->mfDiscreteOne = 0.0;
176 return maViewInformation2D;
179 void OverlayManager::impApplyRemoveActions(OverlayObject& rTarget)
181 // handle evtl. animation
182 if(rTarget.allowsAnimation())
184 // remove from event chain
185 RemoveEvent(&rTarget);
188 // make invisible
189 invalidateRange(rTarget.getBaseRange());
191 // clear manager
192 rTarget.mpOverlayManager = nullptr;
195 void OverlayManager::impApplyAddActions(OverlayObject& rTarget)
197 // set manager
198 rTarget.mpOverlayManager = this;
200 // make visible
201 invalidateRange(rTarget.getBaseRange());
203 // handle evtl. animation
204 if(rTarget.allowsAnimation())
206 // Trigger at current time to get alive. This will do the
207 // object-specific next time calculation and hand over adding
208 // again to the scheduler to the animated object, too. This works for
209 // a paused or non-paused animator.
210 rTarget.Trigger(GetTime());
214 OverlayManager::~OverlayManager()
216 // The OverlayManager is not the owner of the OverlayObjects
217 // and thus will not delete them, but remove them. Profit here
218 // from knowing that all will be removed
219 const sal_uInt32 nSize(maOverlayObjects.size());
221 if(nSize)
223 for(const auto& rpOverlayObject : maOverlayObjects)
225 OSL_ENSURE(rpOverlayObject, "Corrupted OverlayObject List (!)");
226 OverlayObject& rCandidate = *rpOverlayObject;
227 impApplyRemoveActions(rCandidate);
230 // erase vector
231 maOverlayObjects.clear();
235 void OverlayManager::completeRedraw(const vcl::Region& rRegion, OutputDevice* pPreRenderDevice) const
237 if(!rRegion.IsEmpty() && !maOverlayObjects.empty())
239 // check for changed MapModes. That may influence the
240 // logical size of pixel based OverlayObjects (like BitmapHandles)
241 //ImpCheckMapModeChange();
243 // paint members
244 const tools::Rectangle aRegionBoundRect(rRegion.GetBoundRect());
245 const basegfx::B2DRange aRegionRange = vcl::unotools::b2DRectangleFromRectangle(aRegionBoundRect);
247 OutputDevice& rTarget = pPreRenderDevice ? *pPreRenderDevice : getOutputDevice();
248 ImpDrawMembers(aRegionRange, rTarget);
252 void OverlayManager::flush()
254 // default has nothing to do
257 void OverlayManager::add(OverlayObject& rOverlayObject)
259 OSL_ENSURE(nullptr == rOverlayObject.mpOverlayManager, "OverlayObject is added twice to an OverlayManager (!)");
261 // add to the end of chain to preserve display order in paint
262 maOverlayObjects.push_back(&rOverlayObject);
264 // execute add actions
265 impApplyAddActions(rOverlayObject);
268 void OverlayManager::remove(OverlayObject& rOverlayObject)
270 OSL_ENSURE(rOverlayObject.mpOverlayManager == this, "OverlayObject is removed from wrong OverlayManager (!)");
272 // execute remove actions
273 impApplyRemoveActions(rOverlayObject);
275 // remove from vector
276 const OverlayObjectVector::iterator aFindResult = ::std::find(maOverlayObjects.begin(), maOverlayObjects.end(), &rOverlayObject);
277 const bool bFound(aFindResult != maOverlayObjects.end());
278 OSL_ENSURE(bFound, "OverlayObject NOT found at OverlayManager (!)");
280 if(bFound)
282 maOverlayObjects.erase(aFindResult);
286 tools::Rectangle OverlayManager::RangeToInvalidateRectangle(const basegfx::B2DRange& rRange) const
288 if (getDrawinglayerOpt().IsAntiAliasing())
290 // assume AA needs one pixel more and invalidate one pixel more
291 const double fDiscreteOne(getDiscreteOne());
292 const tools::Rectangle aInvalidateRectangle(
293 static_cast<sal_Int32>(floor(rRange.getMinX() - fDiscreteOne)),
294 static_cast<sal_Int32>(floor(rRange.getMinY() - fDiscreteOne)),
295 static_cast<sal_Int32>(ceil(rRange.getMaxX() + fDiscreteOne)),
296 static_cast<sal_Int32>(ceil(rRange.getMaxY() + fDiscreteOne)));
297 return aInvalidateRectangle;
299 else
301 // #i77674# transform to rectangle. Use floor/ceil to get all covered
302 // discrete pixels, see #i75163# and OverlayManagerBuffered::invalidateRange
303 const tools::Rectangle aInvalidateRectangle(
304 static_cast<sal_Int32>(floor(rRange.getMinX())), static_cast<sal_Int32>(floor(rRange.getMinY())),
305 static_cast<sal_Int32>(ceil(rRange.getMaxX())), static_cast<sal_Int32>(ceil(rRange.getMaxY())));
306 return aInvalidateRectangle;
310 void OverlayManager::invalidateRange(const basegfx::B2DRange& rRange)
312 if (OUTDEV_WINDOW == getOutputDevice().GetOutDevType())
314 tools::Rectangle aInvalidateRectangle(RangeToInvalidateRectangle(rRange));
315 // simply invalidate
316 static_cast<vcl::Window&>(getOutputDevice()).Invalidate(aInvalidateRectangle, InvalidateFlags::NoErase);
320 // stripe support ColA
321 void OverlayManager::setStripeColorA(Color aNew)
323 if(aNew != maStripeColorA)
325 maStripeColorA = aNew;
326 ImpStripeDefinitionChanged();
330 // stripe support ColB
331 void OverlayManager::setStripeColorB(Color aNew)
333 if(aNew != maStripeColorB)
335 maStripeColorB = aNew;
336 ImpStripeDefinitionChanged();
340 // stripe support StripeLengthPixel
341 void OverlayManager::setStripeLengthPixel(sal_uInt32 nNew)
343 if(nNew != mnStripeLengthPixel)
345 mnStripeLengthPixel = nNew;
346 ImpStripeDefinitionChanged();
350 } // end of namespace overlay
351 } // end of namespace sdr
353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */