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