xref: /AOO41X/main/svx/source/sdr/overlay/overlaymanagerbuffered.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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svx.hxx"
24 #include <svx/sdr/overlay/overlaymanagerbuffered.hxx>
25 #include <vcl/outdev.hxx>
26 #include <basegfx/point/b2dpoint.hxx>
27 #include <basegfx/range/b2drange.hxx>
28 #include <vcl/salbtype.hxx>
29 #include <vcl/window.hxx>
30 #include <vcl/bitmap.hxx>
31 #include <tools/stream.hxx>
32 #include <basegfx/matrix/b2dhommatrix.hxx>
33 #include <vcl/cursor.hxx>
34 #include <vcl/dibtools.hxx>
35 
36 //////////////////////////////////////////////////////////////////////////////
37 
38 namespace sdr
39 {
40     namespace overlay
41     {
ImpPrepareBufferDevice()42         void OverlayManagerBuffered::ImpPrepareBufferDevice()
43         {
44             // compare size of maBufferDevice with size of visible area
45             if(maBufferDevice.GetOutputSizePixel() != getOutputDevice().GetOutputSizePixel())
46             {
47                 // set new buffer size, copy as much content as possible (use bool parameter for vcl).
48                 // Newly uncovered regions will be repainted.
49                 maBufferDevice.SetOutputSizePixel(getOutputDevice().GetOutputSizePixel(), false);
50             }
51 
52             // compare the MapModes for zoom/scroll changes
53             if(maBufferDevice.GetMapMode() != getOutputDevice().GetMapMode())
54             {
55                 const bool bZoomed(
56                     maBufferDevice.GetMapMode().GetScaleX() != getOutputDevice().GetMapMode().GetScaleX()
57                     || maBufferDevice.GetMapMode().GetScaleY() != getOutputDevice().GetMapMode().GetScaleY());
58 
59                 if(!bZoomed)
60                 {
61                     const Point& rOriginOld = maBufferDevice.GetMapMode().GetOrigin();
62                     const Point& rOriginNew = getOutputDevice().GetMapMode().GetOrigin();
63                     const bool bScrolled(rOriginOld != rOriginNew);
64 
65                     if(bScrolled)
66                     {
67                         // get pixel bounds
68                         const Point aOriginOldPixel(maBufferDevice.LogicToPixel(rOriginOld));
69                         const Point aOriginNewPixel(maBufferDevice.LogicToPixel(rOriginNew));
70                         const Size aOutputSizePixel(maBufferDevice.GetOutputSizePixel());
71 
72                         // remember and switch off MapMode
73                         const bool bMapModeWasEnabled(maBufferDevice.IsMapModeEnabled());
74                         maBufferDevice.EnableMapMode(false);
75 
76                         // scroll internally buffered stuff
77                         const Point aDestinationOffsetPixel(aOriginNewPixel - aOriginOldPixel);
78                         maBufferDevice.DrawOutDev(
79                             aDestinationOffsetPixel, aOutputSizePixel, // destination
80                             Point(), aOutputSizePixel); // source
81 
82                         // restore MapMode
83                         maBufferDevice.EnableMapMode(bMapModeWasEnabled);
84 
85                         // scroll remembered region, too.
86                         if(!maBufferRememberedRangePixel.isEmpty())
87                         {
88                             const basegfx::B2IPoint aIPointDestinationOffsetPixel(aDestinationOffsetPixel.X(), aDestinationOffsetPixel.Y());
89                             const basegfx::B2IPoint aNewMinimum(maBufferRememberedRangePixel.getMinimum() + aIPointDestinationOffsetPixel);
90                             const basegfx::B2IPoint aNewMaximum(maBufferRememberedRangePixel.getMaximum() + aIPointDestinationOffsetPixel);
91                             maBufferRememberedRangePixel = basegfx::B2IRange(aNewMinimum, aNewMaximum);
92                         }
93                     }
94                 }
95 
96                 // copy new MapMode
97                 maBufferDevice.SetMapMode(getOutputDevice().GetMapMode());
98             }
99 
100             // #i29186#
101             maBufferDevice.SetDrawMode(getOutputDevice().GetDrawMode());
102             maBufferDevice.SetSettings(getOutputDevice().GetSettings());
103             maBufferDevice.SetAntialiasing(getOutputDevice().GetAntialiasing());
104         }
105 
ImpRestoreBackground() const106         void OverlayManagerBuffered::ImpRestoreBackground() const
107         {
108             const Rectangle aRegionRectanglePixel(
109                 maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
110                 maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
111             const Region aRegionPixel(aRegionRectanglePixel);
112 
113             ImpRestoreBackground(aRegionPixel);
114         }
115 
ImpRestoreBackground(const Region & rRegionPixel) const116         void OverlayManagerBuffered::ImpRestoreBackground(const Region& rRegionPixel) const
117         {
118             // MapModes off
119             const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
120             const bool bMapModeWasEnabledSource(maBufferDevice.IsMapModeEnabled());
121             getOutputDevice().EnableMapMode(false);
122             ((OverlayManagerBuffered*)this)->maBufferDevice.EnableMapMode(false);
123 
124             // local region
125             RectangleVector aRectangles;
126             rRegionPixel.GetRegionRectangles(aRectangles);
127 
128             for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
129             {
130 #ifdef DBG_UTIL
131                 // #i72754# possible graphical region test only with non-pro
132                 static bool bDoPaintForVisualControl(false);
133 
134                 if(bDoPaintForVisualControl)
135                 {
136                     getOutputDevice().SetLineColor(COL_LIGHTGREEN);
137                     getOutputDevice().SetFillColor();
138                     getOutputDevice().DrawRect(*aRectIter);
139                 }
140 #endif
141 
142                 // restore the area
143                 const Point aTopLeft(aRectIter->TopLeft());
144                 const Size aSize(aRectIter->GetSize());
145 
146                 getOutputDevice().DrawOutDev(
147                     aTopLeft, aSize, // destination
148                     aTopLeft, aSize, // source
149                     maBufferDevice);
150             }
151 
152             //Region aRegionPixel(rRegionPixel);
153             //RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
154             //Rectangle aRegionRectanglePixel;
155             //
156             //while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
157             //{
158 #ifdef DBG_U//TIL
159             //  // #i72754# possible graphical region test only with non-pro
160             //  static bool bDoPaintForVisualControl(false);
161             //  if(bDoPaintForVisualControl)
162             //  {
163             //      getOutputDevice().SetLineColor(COL_LIGHTGREEN);
164             //      getOutputDevice().SetFillColor();
165             //      getOutputDevice().DrawRect(aRegionRectanglePixel);
166             //  }
167 #endif      //
168             //  // restore the area
169             //  const Point aTopLeft(aRegionRectanglePixel.TopLeft());
170             //  const Size aSize(aRegionRectanglePixel.GetSize());
171             //
172             //  getOutputDevice().DrawOutDev(
173             //      aTopLeft, aSize, // destination
174             //      aTopLeft, aSize, // source
175             //      maBufferDevice);
176             //}
177             //
178             //aRegionPixel.EndEnumRects(aRegionHandle);
179 
180             // restore MapModes
181             getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
182             ((OverlayManagerBuffered*)this)->maBufferDevice.EnableMapMode(bMapModeWasEnabledSource);
183         }
184 
ImpSaveBackground(const Region & rRegion,OutputDevice * pPreRenderDevice)185         void OverlayManagerBuffered::ImpSaveBackground(const Region& rRegion, OutputDevice* pPreRenderDevice)
186         {
187             // prepare source
188             OutputDevice& rSource = (pPreRenderDevice) ? *pPreRenderDevice : getOutputDevice();
189 
190             // Ensure buffer is valid
191             ImpPrepareBufferDevice();
192 
193             // build region which needs to be copied
194             Region aRegion(rSource.LogicToPixel(rRegion));
195 
196             // limit to PaintRegion if it's a window. This will be evtl. the expanded one,
197             // but always the exact redraw area
198             if(OUTDEV_WINDOW == rSource.GetOutDevType())
199             {
200                 Window& rWindow = (Window&)rSource;
201                 Region aPaintRegionPixel = rWindow.LogicToPixel(rWindow.GetPaintRegion());
202                 aRegion.Intersect(aPaintRegionPixel);
203 
204                 // #i72754# Make sure content is completetly rendered, the window
205                 // will be used as source of a DrawOutDev soon
206                 rWindow.Flush();
207             }
208 
209             // also limit to buffer size
210             const Rectangle aBufferDeviceRectanglePixel(Point(), maBufferDevice.GetOutputSizePixel());
211             aRegion.Intersect(aBufferDeviceRectanglePixel);
212 
213             // MapModes off
214             const bool bMapModeWasEnabledDest(rSource.IsMapModeEnabled());
215             const bool bMapModeWasEnabledSource(maBufferDevice.IsMapModeEnabled());
216             rSource.EnableMapMode(false);
217             maBufferDevice.EnableMapMode(false);
218 
219             // prepare to iterate over the rectangles from the region in pixels
220             RectangleVector aRectangles;
221             aRegion.GetRegionRectangles(aRectangles);
222 
223             for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
224             {
225                 // for each rectangle, save the area
226                 const Point aTopLeft(aRectIter->TopLeft());
227                 const Size aSize(aRectIter->GetSize());
228 
229                 maBufferDevice.DrawOutDev(
230                     aTopLeft, aSize, // destination
231                     aTopLeft, aSize, // source
232                     rSource);
233 
234 #ifdef DBG_UTIL
235                 // #i72754# possible graphical region test only with non-pro
236                 static bool bDoPaintForVisualControl(false);
237 
238                 if(bDoPaintForVisualControl)
239                 {
240                     const bool bMapModeWasEnabledTest(getOutputDevice().IsMapModeEnabled());
241 
242                     getOutputDevice().EnableMapMode(false);
243                     getOutputDevice().SetLineColor(COL_LIGHTRED);
244                     getOutputDevice().SetFillColor();
245                     getOutputDevice().DrawRect(*aRectIter);
246                     getOutputDevice().EnableMapMode(bMapModeWasEnabledTest);
247                 }
248 
249                 static bool bDoSaveForVisualControl(false);
250 
251                 if(bDoSaveForVisualControl)
252                 {
253                     const Bitmap aBitmap(maBufferDevice.GetBitmap(aTopLeft, aSize));
254                     SvFileStream aNew((const String&)String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
255                     WriteDIB(aBitmap, aNew, false, true);
256                 }
257 #endif
258             }
259 
260             //RegionHandle aRegionHandle(aRegion.BeginEnumRects());
261             //Rectangle aRegionRectanglePixel;
262             //
263             //while(aRegion.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
264             //{
265             //  // for each rectangle, save the area
266             //  Point aTopLeft(aRegionRectanglePixel.TopLeft());
267             //  Size aSize(aRegionRectanglePixel.GetSize());
268             //
269             //  maBufferDevice.DrawOutDev(
270             //      aTopLeft, aSize, // destination
271             //      aTopLeft, aSize, // source
272             //      rSource);
273             //
274 #ifdef DBG_U//TIL
275             //  // #i72754# possible graphical region test only with non-pro
276             //  static bool bDoPaintForVisualControl(false);
277             //  if(bDoPaintForVisualControl)
278             //  {
279             //      const bool bMapModeWasEnabledTest(getOutputDevice().IsMapModeEnabled());
280             //      getOutputDevice().EnableMapMode(false);
281             //      getOutputDevice().SetLineColor(COL_LIGHTRED);
282             //      getOutputDevice().SetFillColor();
283             //      getOutputDevice().DrawRect(aRegionRectanglePixel);
284             //      getOutputDevice().EnableMapMode(bMapModeWasEnabledTest);
285             //  }
286             //
287             //  static bool bDoSaveForVisualControl(false);
288             //  if(bDoSaveForVisualControl)
289             //  {
290             //      const Bitmap aBitmap(maBufferDevice.GetBitmap(aTopLeft, aSize));
291             //      SvFileStream aNew((const String&)String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
292             //      aNew << aBitmap;
293             //  }
294 #endif      //
295             //}
296             //
297             //aRegion.EndEnumRects(aRegionHandle);
298 
299             // restore MapModes
300             rSource.EnableMapMode(bMapModeWasEnabledDest);
301             maBufferDevice.EnableMapMode(bMapModeWasEnabledSource);
302         }
303 
304         IMPL_LINK(OverlayManagerBuffered, ImpBufferTimerHandler, AutoTimer*, /*pTimer*/)
305         {
306             // stop timer
307             maBufferTimer.Stop();
308 
309             if(!maBufferRememberedRangePixel.isEmpty())
310             {
311                 // logic size for impDrawMember call
312                 basegfx::B2DRange aBufferRememberedRangeLogic(
313                     maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
314                     maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
315                 aBufferRememberedRangeLogic.transform(getOutputDevice().GetInverseViewTransformation());
316 
317                 // prepare cursor handling
318                 const bool bTargetIsWindow(OUTDEV_WINDOW == rmOutputDevice.GetOutDevType());
319                 bool bCursorWasEnabled(false);
320 
321                 // #i80730# switch off VCL cursor during overlay refresh
322                 if(bTargetIsWindow)
323                 {
324                     Window& rWindow = static_cast< Window& >(rmOutputDevice);
325                     Cursor* pCursor = rWindow.GetCursor();
326 
327                     if(pCursor && pCursor->IsVisible())
328                     {
329                         pCursor->Hide();
330                         bCursorWasEnabled = true;
331                     }
332                 }
333 
334                 if(DoRefreshWithPreRendering())
335                 {
336                     // #i73602# ensure valid and sized maOutputBufferDevice
337                     const Size aDestinationSizePixel(maBufferDevice.GetOutputSizePixel());
338                     const Size aOutputBufferSizePixel(maOutputBufferDevice.GetOutputSizePixel());
339 
340                     if(aDestinationSizePixel != aOutputBufferSizePixel)
341                     {
342                         maOutputBufferDevice.SetOutputSizePixel(aDestinationSizePixel);
343                     }
344 
345                     maOutputBufferDevice.SetMapMode(getOutputDevice().GetMapMode());
346                     maOutputBufferDevice.EnableMapMode(false);
347                     maOutputBufferDevice.SetDrawMode(maBufferDevice.GetDrawMode());
348                     maOutputBufferDevice.SetSettings(maBufferDevice.GetSettings());
349                     maOutputBufferDevice.SetAntialiasing(maBufferDevice.GetAntialiasing());
350 
351                     // calculate sizes
352                     Rectangle aRegionRectanglePixel(
353                         maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
354                         maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
355 
356                     // truncate aRegionRectanglePixel to destination pixel size, more does
357                     // not need to be prepared since destination is a buffer for a window. So,
358                     // maximum size indirectly shall be limited to getOutputDevice().GetOutputSizePixel()
359                     if(aRegionRectanglePixel.Left() < 0L)
360                     {
361                         aRegionRectanglePixel.Left() = 0L;
362                     }
363 
364                     if(aRegionRectanglePixel.Top() < 0L)
365                     {
366                         aRegionRectanglePixel.Top() = 0L;
367                     }
368 
369                     if(aRegionRectanglePixel.Right() > aDestinationSizePixel.getWidth())
370                     {
371                         aRegionRectanglePixel.Right() = aDestinationSizePixel.getWidth();
372                     }
373 
374                     if(aRegionRectanglePixel.Bottom() > aDestinationSizePixel.getHeight())
375                     {
376                         aRegionRectanglePixel.Bottom() = aDestinationSizePixel.getHeight();
377                     }
378 
379                     // get sizes
380                     const Point aTopLeft(aRegionRectanglePixel.TopLeft());
381                     const Size aSize(aRegionRectanglePixel.GetSize());
382 
383                     {
384                         const bool bMapModeWasEnabledDest(maBufferDevice.IsMapModeEnabled());
385                         maBufferDevice.EnableMapMode(false);
386 
387                         maOutputBufferDevice.DrawOutDev(
388                             aTopLeft, aSize, // destination
389                             aTopLeft, aSize, // source
390                             maBufferDevice);
391 
392                         // restore MapModes
393                         maBufferDevice.EnableMapMode(bMapModeWasEnabledDest);
394                     }
395 
396                     // paint overlay content for remembered region, use
397                     // method from base class directly
398                     maOutputBufferDevice.EnableMapMode(true);
399                     OverlayManager::ImpDrawMembers(aBufferRememberedRangeLogic, maOutputBufferDevice);
400                     maOutputBufferDevice.EnableMapMode(false);
401 
402                     // copy to output
403                     {
404                         const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
405                         getOutputDevice().EnableMapMode(false);
406 
407                         getOutputDevice().DrawOutDev(
408                             aTopLeft, aSize, // destination
409                             aTopLeft, aSize, // source
410                             maOutputBufferDevice);
411 
412                         // debug
413                         /*getOutputDevice().SetLineColor(COL_RED);
414                         getOutputDevice().SetFillColor();
415                         getOutputDevice().DrawRect(Rectangle(aTopLeft, aSize));*/
416 
417                         // restore MapModes
418                         getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
419                     }
420                 }
421                 else
422                 {
423                     // Restore all rectangles for remembered region from buffer
424                     ImpRestoreBackground();
425 
426                     // paint overlay content for remembered region, use
427                     // method from base class directly
428                     OverlayManager::ImpDrawMembers(aBufferRememberedRangeLogic, getOutputDevice());
429                 }
430 
431                 // VCL hack for transparent child windows
432                 // Problem is e.g. a radiobuttion form control in life mode. The used window
433                 // is a transparence vcl childwindow. This flag only allows the parent window to
434                 // paint into the child windows area, but there is no mechanism which takes
435                 // care for a repaint of the child window. A transparent child window is NOT
436                 // a window which always keeps it's content consistent over the parent, but it's
437                 // more like just a paint flag for the parent.
438                 // To get the update, the windows in question are updated manulally here.
439                 if(bTargetIsWindow)
440                 {
441                     Window& rWindow = static_cast< Window& >(rmOutputDevice);
442 
443                     if(rWindow.IsChildTransparentModeEnabled() && rWindow.GetChildCount())
444                     {
445                         const Rectangle aRegionRectanglePixel(
446                             maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
447                             maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
448 
449                         for(sal_uInt16 a(0); a < rWindow.GetChildCount(); a++)
450                         {
451                             Window* pCandidate = rWindow.GetChild(a);
452 
453                             if(pCandidate && pCandidate->IsPaintTransparent())
454                             {
455                                 const Rectangle aCandidatePosSizePixel(pCandidate->GetPosPixel(), pCandidate->GetSizePixel());
456 
457                                 if(aCandidatePosSizePixel.IsOver(aRegionRectanglePixel))
458                                 {
459                                     pCandidate->Invalidate(INVALIDATE_NOTRANSPARENT|INVALIDATE_CHILDREN);
460                                     pCandidate->Update();
461                                 }
462                             }
463                         }
464                     }
465                 }
466 
467                 // #i80730# restore visibility of VCL cursor
468                 if(bCursorWasEnabled)
469                 {
470                     Window& rWindow = static_cast< Window& >(rmOutputDevice);
471                     Cursor* pCursor = rWindow.GetCursor();
472 
473                     if(pCursor)
474                     {
475                         // check if cursor still exists. It may have been deleted from someone
476                         pCursor->Show();
477                     }
478                 }
479 
480                 // forget remembered Region
481                 maBufferRememberedRangePixel.reset();
482             }
483 
484             return 0;
485         }
486 
OverlayManagerBuffered(OutputDevice & rOutputDevice,bool bRefreshWithPreRendering)487         OverlayManagerBuffered::OverlayManagerBuffered(
488             OutputDevice& rOutputDevice,
489             bool bRefreshWithPreRendering)
490         :   OverlayManager(rOutputDevice),
491             mbRefreshWithPreRendering(bRefreshWithPreRendering)
492         {
493             // Init timer
494             maBufferTimer.SetTimeout(1);
495             maBufferTimer.SetTimeoutHdl(LINK(this, OverlayManagerBuffered, ImpBufferTimerHandler));
496         }
497 
~OverlayManagerBuffered()498         OverlayManagerBuffered::~OverlayManagerBuffered()
499         {
500             // Clear timer
501             maBufferTimer.Stop();
502 
503             if(!maBufferRememberedRangePixel.isEmpty())
504             {
505                 // Restore all rectangles for remembered region from buffer
506                 ImpRestoreBackground();
507             }
508         }
509 
completeRedraw(const Region & rRegion,OutputDevice * pPreRenderDevice) const510         void OverlayManagerBuffered::completeRedraw(const Region& rRegion, OutputDevice* pPreRenderDevice) const
511         {
512             if(!rRegion.IsEmpty())
513             {
514                 // save new background
515                 ((OverlayManagerBuffered*)this)->ImpSaveBackground(rRegion, pPreRenderDevice);
516             }
517 
518             // call parent
519             OverlayManager::completeRedraw(rRegion, pPreRenderDevice);
520         }
521 
flush()522         void OverlayManagerBuffered::flush()
523         {
524             // call timer handler direct
525             ImpBufferTimerHandler(0);
526         }
527 
528         // #i68597# part of content gets copied, react on it
copyArea(const Point & rDestPt,const Point & rSrcPt,const Size & rSrcSize)529         void OverlayManagerBuffered::copyArea(const Point& rDestPt, const Point& rSrcPt, const Size& rSrcSize)
530         {
531             // scroll local buffered area
532             maBufferDevice.CopyArea(rDestPt, rSrcPt, rSrcSize);
533         }
534 
restoreBackground(const Region & rRegion) const535         void OverlayManagerBuffered::restoreBackground(const Region& rRegion) const
536         {
537             // restore
538             const Region aRegionPixel(getOutputDevice().LogicToPixel(rRegion));
539             ImpRestoreBackground(aRegionPixel);
540 
541             // call parent
542             OverlayManager::restoreBackground(rRegion);
543         }
544 
invalidateRange(const basegfx::B2DRange & rRange)545         void OverlayManagerBuffered::invalidateRange(const basegfx::B2DRange& rRange)
546         {
547             if(!rRange.isEmpty())
548             {
549                 // buffered output, do not invalidate but use the timer
550                 // to trigger a timer event for refresh
551                 maBufferTimer.Start();
552 
553                 // add the discrete range to the remembered region
554                 // #i75163# use double precision and floor/ceil rounding to get overlapped pixel region, even
555                 // when the given logic region has a width/height of 0.0. This does NOT work with LogicToPixel
556                 // since it just transforms the top left and bottom right points equally without taking
557                 // discrete pixel coverage into account. An empty B2DRange and thus empty logic Rectangle translated
558                 // to an also empty discrete pixel rectangle - what is wrong.
559                 basegfx::B2DRange aDiscreteRange(rRange);
560                 aDiscreteRange.transform(getOutputDevice().GetViewTransformation());
561 
562                 if(maDrawinglayerOpt.IsAntiAliasing())
563                 {
564                     // assume AA needs one pixel more and invalidate one pixel more
565                     const double fDiscreteOne(getDiscreteOne());
566                     const basegfx::B2IPoint aTopLeft(
567                         (sal_Int32)floor(aDiscreteRange.getMinX() - fDiscreteOne),
568                         (sal_Int32)floor(aDiscreteRange.getMinY() - fDiscreteOne));
569                     const basegfx::B2IPoint aBottomRight(
570                         (sal_Int32)ceil(aDiscreteRange.getMaxX() + fDiscreteOne),
571                         (sal_Int32)ceil(aDiscreteRange.getMaxY() + fDiscreteOne));
572 
573                     maBufferRememberedRangePixel.expand(aTopLeft);
574                     maBufferRememberedRangePixel.expand(aBottomRight);
575                 }
576                 else
577                 {
578                     const basegfx::B2IPoint aTopLeft((sal_Int32)floor(aDiscreteRange.getMinX()), (sal_Int32)floor(aDiscreteRange.getMinY()));
579                     const basegfx::B2IPoint aBottomRight((sal_Int32)ceil(aDiscreteRange.getMaxX()), (sal_Int32)ceil(aDiscreteRange.getMaxY()));
580 
581                     maBufferRememberedRangePixel.expand(aTopLeft);
582                     maBufferRememberedRangePixel.expand(aBottomRight);
583                 }
584             }
585         }
586 
SetRefreshWithPreRendering(bool bNew)587         void OverlayManagerBuffered::SetRefreshWithPreRendering(bool bNew)
588         {
589             if((bool)mbRefreshWithPreRendering != bNew)
590             {
591                 mbRefreshWithPreRendering = bNew;
592             }
593         }
594     } // end of namespace overlay
595 } // end of namespace sdr
596 
597 //////////////////////////////////////////////////////////////////////////////
598 // eof
599