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