Update ooo320-m1
[ooovba.git] / svx / source / sdr / overlay / overlaymanagerbuffered.cxx
blob91393a4047eb31f0d27e25ecfab08729b41e1f9e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: overlaymanagerbuffered.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/sdr/overlay/overlaymanagerbuffered.hxx>
34 #include <vcl/outdev.hxx>
35 #include <basegfx/point/b2dpoint.hxx>
36 #include <basegfx/range/b2drange.hxx>
37 #include <vcl/salbtype.hxx>
38 #include <vcl/window.hxx>
39 #include <vcl/bitmap.hxx>
40 #include <tools/stream.hxx>
41 #include <basegfx/matrix/b2dhommatrix.hxx>
42 #include <vcl/cursor.hxx>
44 //////////////////////////////////////////////////////////////////////////////
46 namespace sdr
48 namespace overlay
50 void OverlayManagerBuffered::ImpPrepareBufferDevice()
52 // compare size of maBufferDevice with size of visible area
53 if(maBufferDevice.GetOutputSizePixel() != getOutputDevice().GetOutputSizePixel())
55 // set new buffer size, copy as much content as possible (use bool parameter for vcl).
56 // Newly uncovered regions will be repainted.
57 maBufferDevice.SetOutputSizePixel(getOutputDevice().GetOutputSizePixel(), false);
60 // compare the MapModes for zoom/scroll changes
61 if(maBufferDevice.GetMapMode() != getOutputDevice().GetMapMode())
63 const bool bZoomed(
64 maBufferDevice.GetMapMode().GetScaleX() != getOutputDevice().GetMapMode().GetScaleX()
65 || maBufferDevice.GetMapMode().GetScaleY() != getOutputDevice().GetMapMode().GetScaleY());
67 if(!bZoomed)
69 const Point& rOriginOld = maBufferDevice.GetMapMode().GetOrigin();
70 const Point& rOriginNew = getOutputDevice().GetMapMode().GetOrigin();
71 const bool bScrolled(rOriginOld != rOriginNew);
73 if(bScrolled)
75 // get pixel bounds
76 const Point aOriginOldPixel(maBufferDevice.LogicToPixel(rOriginOld));
77 const Point aOriginNewPixel(maBufferDevice.LogicToPixel(rOriginNew));
78 const Size aOutputSizePixel(maBufferDevice.GetOutputSizePixel());
80 // remember and switch off MapMode
81 const bool bMapModeWasEnabled(maBufferDevice.IsMapModeEnabled());
82 maBufferDevice.EnableMapMode(false);
84 // scroll internally buffered stuff
85 const Point aDestinationOffsetPixel(aOriginNewPixel - aOriginOldPixel);
86 maBufferDevice.DrawOutDev(
87 aDestinationOffsetPixel, aOutputSizePixel, // destination
88 Point(), aOutputSizePixel); // source
90 // restore MapMode
91 maBufferDevice.EnableMapMode(bMapModeWasEnabled);
93 // scroll remembered region, too.
94 if(!maBufferRememberedRangePixel.isEmpty())
96 const basegfx::B2IPoint aIPointDestinationOffsetPixel(aDestinationOffsetPixel.X(), aDestinationOffsetPixel.Y());
97 const basegfx::B2IPoint aNewMinimum(maBufferRememberedRangePixel.getMinimum() + aIPointDestinationOffsetPixel);
98 const basegfx::B2IPoint aNewMaximum(maBufferRememberedRangePixel.getMaximum() + aIPointDestinationOffsetPixel);
99 maBufferRememberedRangePixel = basegfx::B2IRange(aNewMinimum, aNewMaximum);
104 // copy new MapMode
105 maBufferDevice.SetMapMode(getOutputDevice().GetMapMode());
108 // #i29186#
109 maBufferDevice.SetDrawMode(getOutputDevice().GetDrawMode());
110 maBufferDevice.SetSettings(getOutputDevice().GetSettings());
111 maBufferDevice.SetAntialiasing(getOutputDevice().GetAntialiasing());
114 void OverlayManagerBuffered::ImpRestoreBackground() const
116 const Rectangle aRegionRectanglePixel(
117 maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
118 maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
119 const Region aRegionPixel(aRegionRectanglePixel);
121 ImpRestoreBackground(aRegionPixel);
124 void OverlayManagerBuffered::ImpRestoreBackground(const Region& rRegionPixel) const
126 // local region
127 Region aRegionPixel(rRegionPixel);
128 RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
129 Rectangle aRegionRectanglePixel;
131 // MapModes off
132 const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
133 const bool bMapModeWasEnabledSource(maBufferDevice.IsMapModeEnabled());
134 getOutputDevice().EnableMapMode(false);
135 ((OverlayManagerBuffered*)this)->maBufferDevice.EnableMapMode(false);
137 while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
139 #ifdef DBG_UTIL
140 // #i72754# possible graphical region test only with non-pro
141 static bool bDoPaintForVisualControl(false);
142 if(bDoPaintForVisualControl)
144 getOutputDevice().SetLineColor(COL_LIGHTGREEN);
145 getOutputDevice().SetFillColor();
146 getOutputDevice().DrawRect(aRegionRectanglePixel);
148 #endif
150 // restore the area
151 const Point aTopLeft(aRegionRectanglePixel.TopLeft());
152 const Size aSize(aRegionRectanglePixel.GetSize());
154 getOutputDevice().DrawOutDev(
155 aTopLeft, aSize, // destination
156 aTopLeft, aSize, // source
157 maBufferDevice);
160 aRegionPixel.EndEnumRects(aRegionHandle);
162 // restore MapModes
163 getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
164 ((OverlayManagerBuffered*)this)->maBufferDevice.EnableMapMode(bMapModeWasEnabledSource);
167 void OverlayManagerBuffered::ImpSaveBackground(const Region& rRegion, OutputDevice* pPreRenderDevice)
169 // prepare source
170 OutputDevice& rSource = (pPreRenderDevice) ? *pPreRenderDevice : getOutputDevice();
172 // Ensure buffer is valid
173 ImpPrepareBufferDevice();
175 // build region which needs to be copied
176 Region aRegion(rSource.LogicToPixel(rRegion));
178 // limit to PaintRegion if it's a window. This will be evtl. the expanded one,
179 // but always the exact redraw area
180 if(OUTDEV_WINDOW == rSource.GetOutDevType())
182 Window& rWindow = (Window&)rSource;
183 Region aPaintRegionPixel = rWindow.LogicToPixel(rWindow.GetPaintRegion());
184 aRegion.Intersect(aPaintRegionPixel);
186 // #i72754# Make sure content is completetly rendered, the window
187 // will be used as source of a DrawOutDev soon
188 rWindow.Flush();
191 // also limit to buffer size
192 const Rectangle aBufferDeviceRectanglePixel = Rectangle(Point(), maBufferDevice.GetOutputSizePixel());
193 aRegion.Intersect(aBufferDeviceRectanglePixel);
195 // prepare to iterate over the rectangles from the region in pixels
196 RegionHandle aRegionHandle(aRegion.BeginEnumRects());
197 Rectangle aRegionRectanglePixel;
199 // MapModes off
200 const bool bMapModeWasEnabledDest(rSource.IsMapModeEnabled());
201 const bool bMapModeWasEnabledSource(maBufferDevice.IsMapModeEnabled());
202 rSource.EnableMapMode(false);
203 maBufferDevice.EnableMapMode(false);
205 while(aRegion.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
207 // for each rectangle, save the area
208 Point aTopLeft(aRegionRectanglePixel.TopLeft());
209 Size aSize(aRegionRectanglePixel.GetSize());
211 maBufferDevice.DrawOutDev(
212 aTopLeft, aSize, // destination
213 aTopLeft, aSize, // source
214 rSource);
216 #ifdef DBG_UTIL
217 // #i72754# possible graphical region test only with non-pro
218 static bool bDoPaintForVisualControl(false);
219 if(bDoPaintForVisualControl)
221 const bool bMapModeWasEnabledTest(getOutputDevice().IsMapModeEnabled());
222 getOutputDevice().EnableMapMode(false);
223 getOutputDevice().SetLineColor(COL_LIGHTRED);
224 getOutputDevice().SetFillColor();
225 getOutputDevice().DrawRect(aRegionRectanglePixel);
226 getOutputDevice().EnableMapMode(bMapModeWasEnabledTest);
229 static bool bDoSaveForVisualControl(false);
230 if(bDoSaveForVisualControl)
232 const Bitmap aBitmap(maBufferDevice.GetBitmap(aTopLeft, aSize));
233 SvFileStream aNew((const String&)String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
234 aNew << aBitmap;
236 #endif
239 aRegion.EndEnumRects(aRegionHandle);
241 // restore MapModes
242 rSource.EnableMapMode(bMapModeWasEnabledDest);
243 maBufferDevice.EnableMapMode(bMapModeWasEnabledSource);
246 IMPL_LINK(OverlayManagerBuffered, ImpBufferTimerHandler, AutoTimer*, /*pTimer*/)
248 // stop timer
249 maBufferTimer.Stop();
251 if(!maBufferRememberedRangePixel.isEmpty())
253 // logic size for impDrawMember call
254 basegfx::B2DRange aBufferRememberedRangeLogic(
255 maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
256 maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
257 aBufferRememberedRangeLogic.transform(getOutputDevice().GetInverseViewTransformation());
259 // prepare cursor handling
260 const bool bTargetIsWindow(OUTDEV_WINDOW == rmOutputDevice.GetOutDevType());
261 bool bCursorWasEnabled(false);
263 // #i80730# switch off VCL cursor during overlay refresh
264 if(bTargetIsWindow)
266 Window& rWindow = static_cast< Window& >(rmOutputDevice);
267 Cursor* pCursor = rWindow.GetCursor();
269 if(pCursor && pCursor->IsVisible())
271 pCursor->Hide();
272 bCursorWasEnabled = true;
276 if(DoRefreshWithPreRendering())
278 // #i73602# ensure valid and sized maOutputBufferDevice
279 const Size aDestinationSizePixel(maBufferDevice.GetOutputSizePixel());
280 const Size aOutputBufferSizePixel(maOutputBufferDevice.GetOutputSizePixel());
282 if(aDestinationSizePixel != aOutputBufferSizePixel)
284 maOutputBufferDevice.SetOutputSizePixel(aDestinationSizePixel);
287 maOutputBufferDevice.SetMapMode(getOutputDevice().GetMapMode());
288 maOutputBufferDevice.EnableMapMode(false);
289 maOutputBufferDevice.SetDrawMode(maBufferDevice.GetDrawMode());
290 maOutputBufferDevice.SetSettings(maBufferDevice.GetSettings());
291 maOutputBufferDevice.SetAntialiasing(maBufferDevice.GetAntialiasing());
293 // calculate sizes
294 Rectangle aRegionRectanglePixel(
295 maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
296 maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
298 // truncate aRegionRectanglePixel to destination pixel size, more does
299 // not need to be prepared since destination is a buffer for a window. So,
300 // maximum size indirectly shall be limited to getOutputDevice().GetOutputSizePixel()
301 if(aRegionRectanglePixel.Left() < 0L)
303 aRegionRectanglePixel.Left() = 0L;
306 if(aRegionRectanglePixel.Top() < 0L)
308 aRegionRectanglePixel.Top() = 0L;
311 if(aRegionRectanglePixel.Right() > aDestinationSizePixel.getWidth())
313 aRegionRectanglePixel.Right() = aDestinationSizePixel.getWidth();
316 if(aRegionRectanglePixel.Bottom() > aDestinationSizePixel.getHeight())
318 aRegionRectanglePixel.Bottom() = aDestinationSizePixel.getHeight();
321 // get sizes
322 const Point aTopLeft(aRegionRectanglePixel.TopLeft());
323 const Size aSize(aRegionRectanglePixel.GetSize());
326 const bool bMapModeWasEnabledDest(maBufferDevice.IsMapModeEnabled());
327 maBufferDevice.EnableMapMode(false);
329 maOutputBufferDevice.DrawOutDev(
330 aTopLeft, aSize, // destination
331 aTopLeft, aSize, // source
332 maBufferDevice);
334 // restore MapModes
335 maBufferDevice.EnableMapMode(bMapModeWasEnabledDest);
338 // paint overlay content for remembered region, use
339 // method from base class directly
340 maOutputBufferDevice.EnableMapMode(true);
341 OverlayManager::ImpDrawMembers(aBufferRememberedRangeLogic, maOutputBufferDevice);
342 maOutputBufferDevice.EnableMapMode(false);
344 // copy to output
346 const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
347 getOutputDevice().EnableMapMode(false);
349 getOutputDevice().DrawOutDev(
350 aTopLeft, aSize, // destination
351 aTopLeft, aSize, // source
352 maOutputBufferDevice);
354 // debug
355 /*getOutputDevice().SetLineColor(COL_RED);
356 getOutputDevice().SetFillColor();
357 getOutputDevice().DrawRect(Rectangle(aTopLeft, aSize));*/
359 // restore MapModes
360 getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
363 else
365 // Restore all rectangles for remembered region from buffer
366 ImpRestoreBackground();
368 // paint overlay content for remembered region, use
369 // method from base class directly
370 OverlayManager::ImpDrawMembers(aBufferRememberedRangeLogic, getOutputDevice());
373 // #i80730# restore visibility of VCL cursor
374 if(bCursorWasEnabled)
376 Window& rWindow = static_cast< Window& >(rmOutputDevice);
377 Cursor* pCursor = rWindow.GetCursor();
379 if(pCursor)
381 // check if cursor still exists. It may have been deleted from someone
382 pCursor->Show();
386 // forget remembered Region
387 maBufferRememberedRangePixel.reset();
390 return 0;
393 OverlayManagerBuffered::OverlayManagerBuffered(
394 OutputDevice& rOutputDevice,
395 OverlayManager* pOldOverlayManager,
396 bool bRefreshWithPreRendering)
397 : OverlayManager(rOutputDevice, pOldOverlayManager),
398 mbRefreshWithPreRendering(bRefreshWithPreRendering)
400 // Init timer
401 maBufferTimer.SetTimeout(1);
402 maBufferTimer.SetTimeoutHdl(LINK(this, OverlayManagerBuffered, ImpBufferTimerHandler));
405 OverlayManagerBuffered::~OverlayManagerBuffered()
407 // Clear timer
408 maBufferTimer.Stop();
410 if(!maBufferRememberedRangePixel.isEmpty())
412 // Restore all rectangles for remembered region from buffer
413 ImpRestoreBackground();
417 void OverlayManagerBuffered::completeRedraw(const Region& rRegion, OutputDevice* pPreRenderDevice) const
419 if(!rRegion.IsEmpty())
421 // save new background
422 ((OverlayManagerBuffered*)this)->ImpSaveBackground(rRegion, pPreRenderDevice);
425 // call parent
426 OverlayManager::completeRedraw(rRegion, pPreRenderDevice);
429 void OverlayManagerBuffered::flush()
431 // call timer handler direct
432 ImpBufferTimerHandler(0);
435 // #i68597# part of content gets copied, react on it
436 void OverlayManagerBuffered::copyArea(const Point& rDestPt, const Point& rSrcPt, const Size& rSrcSize)
438 // scroll local buffered area
439 maBufferDevice.CopyArea(rDestPt, rSrcPt, rSrcSize);
442 void OverlayManagerBuffered::restoreBackground(const Region& rRegion) const
444 // restore
445 const Region aRegionPixel(getOutputDevice().LogicToPixel(rRegion));
446 ImpRestoreBackground(aRegionPixel);
448 // call parent
449 OverlayManager::restoreBackground(rRegion);
452 void OverlayManagerBuffered::invalidateRange(const basegfx::B2DRange& rRange)
454 if(!rRange.isEmpty())
456 // buffered output, do not invalidate but use the timer
457 // to trigger a timer event for refresh
458 maBufferTimer.Start();
460 // add the discrete range to the remembered region
461 // #i75163# use double precision and floor/ceil rounding to get overlapped pixel region, even
462 // when the given logic region has a width/height of 0.0. This does NOT work with LogicToPixel
463 // since it just transforms the top left and bottom right points equally without taking
464 // discrete pixel coverage into account. An empty B2DRange and thus empty logic Rectangle translated
465 // to an also empty discrete pixel rectangle - what is wrong.
466 basegfx::B2DRange aDiscreteRange(rRange);
467 aDiscreteRange.transform(getOutputDevice().GetViewTransformation());
469 if(maDrawinglayerOpt.IsAntiAliasing())
471 // assume AA needs one pixel more and invalidate one pixel more
472 const double fDiscreteOne(getDiscreteOne());
473 const basegfx::B2IPoint aTopLeft(
474 (sal_Int32)floor(aDiscreteRange.getMinX() - fDiscreteOne),
475 (sal_Int32)floor(aDiscreteRange.getMinY() - fDiscreteOne));
476 const basegfx::B2IPoint aBottomRight(
477 (sal_Int32)ceil(aDiscreteRange.getMaxX() + fDiscreteOne),
478 (sal_Int32)ceil(aDiscreteRange.getMaxY() + fDiscreteOne));
480 maBufferRememberedRangePixel.expand(aTopLeft);
481 maBufferRememberedRangePixel.expand(aBottomRight);
483 else
485 const basegfx::B2IPoint aTopLeft((sal_Int32)floor(aDiscreteRange.getMinX()), (sal_Int32)floor(aDiscreteRange.getMinY()));
486 const basegfx::B2IPoint aBottomRight((sal_Int32)ceil(aDiscreteRange.getMaxX()), (sal_Int32)ceil(aDiscreteRange.getMaxY()));
488 maBufferRememberedRangePixel.expand(aTopLeft);
489 maBufferRememberedRangePixel.expand(aBottomRight);
494 void OverlayManagerBuffered::SetRefreshWithPreRendering(bool bNew)
496 if((bool)mbRefreshWithPreRendering != bNew)
498 mbRefreshWithPreRendering = bNew;
501 } // end of namespace overlay
502 } // end of namespace sdr
504 //////////////////////////////////////////////////////////////////////////////
505 // eof