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