xref: /trunk/main/svx/source/sdr/overlay/overlaymanager.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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