1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
34 using namespace com::sun::star
;
41 void OverlayManager::ImpDrawMembers(const basegfx::B2DRange
& rRange
, OutputDevice
& rDestinationDevice
) const
43 const sal_uInt32
nSize(maOverlayObjects
.size());
47 const AntialiasingFlags
nOriginalAA(rDestinationDevice
.GetAntialiasing());
48 const bool bIsAntiAliasing(getDrawinglayerOpt().IsAntiAliasing());
51 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice(
53 getCurrentViewInformation2D()));
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
);
76 rDestinationDevice
.SetAntialiasing(nOriginalAA
& ~AntialiasingFlags::EnableB2dDraw
);
79 pProcessor
->process(rSequence
);
88 // restore AA settings
89 rDestinationDevice
.SetAntialiasing(nOriginalAA
);
93 void OverlayManager::ImpStripeDefinitionChanged()
95 const sal_uInt32
nSize(maOverlayObjects
.size());
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
)
121 mrOutputDevice(rOutputDevice
),
123 maStripeColorA(COL_BLACK
),
124 maStripeColorB(COL_WHITE
),
125 mnStripeLengthPixel(5),
127 maViewTransformation(),
128 maViewInformation2D(),
131 // set Property 'ReducedDisplayQuality' to true to allow simpler interaction
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
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
,
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
);
189 invalidateRange(rTarget
.getBaseRange());
192 rTarget
.mpOverlayManager
= nullptr;
195 void OverlayManager::impApplyAddActions(OverlayObject
& rTarget
)
198 rTarget
.mpOverlayManager
= this;
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());
223 for(const auto& rpOverlayObject
: maOverlayObjects
)
225 OSL_ENSURE(rpOverlayObject
, "Corrupted OverlayObject List (!)");
226 OverlayObject
& rCandidate
= *rpOverlayObject
;
227 impApplyRemoveActions(rCandidate
);
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();
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 (!)");
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
;
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
));
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: */