fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / sdr / overlay / overlaymanagerbuffered.cxx
blobc8c2db34cf2874fccca6a3627816f73e92386b34
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/sdr/overlay/overlaymanagerbuffered.hxx>
21 #include <svx/sdrpaintwindow.hxx>
22 #include <vcl/outdev.hxx>
23 #include <basegfx/point/b2dpoint.hxx>
24 #include <basegfx/range/b2drange.hxx>
25 #include <vcl/window.hxx>
26 #include <vcl/bitmap.hxx>
27 #include <tools/stream.hxx>
28 #include <basegfx/matrix/b2dhommatrix.hxx>
29 #include <vcl/cursor.hxx>
31 //////////////////////////////////////////////////////////////////////////////
33 namespace sdr
35 namespace overlay
37 void OverlayManagerBuffered::ImpPrepareBufferDevice()
39 // compare size of maBufferDevice with size of visible area
40 if(maBufferDevice.GetOutputSizePixel() != getOutputDevice().GetOutputSizePixel())
42 // set new buffer size, copy as much content as possible (use bool parameter for vcl).
43 // Newly uncovered regions will be repainted.
44 maBufferDevice.SetOutputSizePixel(getOutputDevice().GetOutputSizePixel(), false);
47 // compare the MapModes for zoom/scroll changes
48 if(maBufferDevice.GetMapMode() != getOutputDevice().GetMapMode())
50 const bool bZoomed(
51 maBufferDevice.GetMapMode().GetScaleX() != getOutputDevice().GetMapMode().GetScaleX()
52 || maBufferDevice.GetMapMode().GetScaleY() != getOutputDevice().GetMapMode().GetScaleY());
54 if(!bZoomed)
56 const Point& rOriginOld = maBufferDevice.GetMapMode().GetOrigin();
57 const Point& rOriginNew = getOutputDevice().GetMapMode().GetOrigin();
58 const bool bScrolled(rOriginOld != rOriginNew);
60 if(bScrolled)
62 // get pixel bounds
63 const Point aOriginOldPixel(maBufferDevice.LogicToPixel(rOriginOld));
64 const Point aOriginNewPixel(maBufferDevice.LogicToPixel(rOriginNew));
65 const Size aOutputSizePixel(maBufferDevice.GetOutputSizePixel());
67 // remember and switch off MapMode
68 const bool bMapModeWasEnabled(maBufferDevice.IsMapModeEnabled());
69 maBufferDevice.EnableMapMode(false);
71 // scroll internally buffered stuff
72 const Point aDestinationOffsetPixel(aOriginNewPixel - aOriginOldPixel);
73 maBufferDevice.DrawOutDev(
74 aDestinationOffsetPixel, aOutputSizePixel, // destination
75 Point(), aOutputSizePixel); // source
77 // restore MapMode
78 maBufferDevice.EnableMapMode(bMapModeWasEnabled);
80 // scroll remembered region, too.
81 if(!maBufferRememberedRangePixel.isEmpty())
83 const basegfx::B2IPoint aIPointDestinationOffsetPixel(aDestinationOffsetPixel.X(), aDestinationOffsetPixel.Y());
84 const basegfx::B2IPoint aNewMinimum(maBufferRememberedRangePixel.getMinimum() + aIPointDestinationOffsetPixel);
85 const basegfx::B2IPoint aNewMaximum(maBufferRememberedRangePixel.getMaximum() + aIPointDestinationOffsetPixel);
86 maBufferRememberedRangePixel = basegfx::B2IRange(aNewMinimum, aNewMaximum);
91 // copy new MapMode
92 maBufferDevice.SetMapMode(getOutputDevice().GetMapMode());
95 // #i29186#
96 maBufferDevice.SetDrawMode(getOutputDevice().GetDrawMode());
97 maBufferDevice.SetSettings(getOutputDevice().GetSettings());
98 maBufferDevice.SetAntialiasing(getOutputDevice().GetAntialiasing());
101 void OverlayManagerBuffered::ImpRestoreBackground() const
103 const Rectangle aRegionRectanglePixel(
104 maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
105 maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
106 const Region aRegionPixel(aRegionRectanglePixel);
108 ImpRestoreBackground(aRegionPixel);
111 void OverlayManagerBuffered::ImpRestoreBackground(const Region& rRegionPixel) const
113 // local region
114 Region aRegionPixel(rRegionPixel);
115 RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
116 Rectangle aRegionRectanglePixel;
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);
124 while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
126 #ifdef DBG_UTIL
127 // #i72754# possible graphical region test only with non-pro
128 static bool bDoPaintForVisualControl(false);
129 if(bDoPaintForVisualControl)
131 getOutputDevice().SetLineColor(COL_LIGHTGREEN);
132 getOutputDevice().SetFillColor();
133 getOutputDevice().DrawRect(aRegionRectanglePixel);
135 #endif
137 // restore the area
138 const Point aTopLeft(aRegionRectanglePixel.TopLeft());
139 const Size aSize(aRegionRectanglePixel.GetSize());
141 getOutputDevice().DrawOutDev(
142 aTopLeft, aSize, // destination
143 aTopLeft, aSize, // source
144 maBufferDevice);
147 aRegionPixel.EndEnumRects(aRegionHandle);
149 // restore MapModes
150 getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
151 ((OverlayManagerBuffered*)this)->maBufferDevice.EnableMapMode(bMapModeWasEnabledSource);
154 void OverlayManagerBuffered::ImpSaveBackground(const Region& rRegion, OutputDevice* pPreRenderDevice)
156 // prepare source
157 OutputDevice& rSource = (pPreRenderDevice) ? *pPreRenderDevice : getOutputDevice();
159 // Ensure buffer is valid
160 ImpPrepareBufferDevice();
162 // build region which needs to be copied
163 Region aRegion(rSource.LogicToPixel(rRegion));
165 // limit to PaintRegion if it's a window. This will be evtl. the expanded one,
166 // but always the exact redraw area
167 if(OUTDEV_WINDOW == rSource.GetOutDevType())
169 Window& rWindow = (Window&)rSource;
170 Region aPaintRegionPixel = rWindow.LogicToPixel(rWindow.GetPaintRegion());
171 aRegion.Intersect(aPaintRegionPixel);
173 // #i72754# Make sure content is completetly rendered, the window
174 // will be used as source of a DrawOutDev soon
175 rWindow.Flush();
178 // also limit to buffer size
179 const Rectangle aBufferDeviceRectanglePixel = Rectangle(Point(), maBufferDevice.GetOutputSizePixel());
180 aRegion.Intersect(aBufferDeviceRectanglePixel);
182 // prepare to iterate over the rectangles from the region in pixels
183 RegionHandle aRegionHandle(aRegion.BeginEnumRects());
184 Rectangle aRegionRectanglePixel;
186 // MapModes off
187 const bool bMapModeWasEnabledDest(rSource.IsMapModeEnabled());
188 const bool bMapModeWasEnabledSource(maBufferDevice.IsMapModeEnabled());
189 rSource.EnableMapMode(false);
190 maBufferDevice.EnableMapMode(false);
192 while(aRegion.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
194 // for each rectangle, save the area
195 Point aTopLeft(aRegionRectanglePixel.TopLeft());
196 Size aSize(aRegionRectanglePixel.GetSize());
198 maBufferDevice.DrawOutDev(
199 aTopLeft, aSize, // destination
200 aTopLeft, aSize, // source
201 rSource);
204 aRegion.EndEnumRects(aRegionHandle);
206 // restore MapModes
207 rSource.EnableMapMode(bMapModeWasEnabledDest);
208 maBufferDevice.EnableMapMode(bMapModeWasEnabledSource);
211 IMPL_LINK(OverlayManagerBuffered, ImpBufferTimerHandler, AutoTimer*, /*pTimer*/)
213 //Resolves: fdo#46728 ensure this exists until end of scope
214 rtl::Reference<OverlayManager> xRef(this);
216 // stop timer
217 maBufferTimer.Stop();
219 if(!maBufferRememberedRangePixel.isEmpty())
221 // logic size for impDrawMember call
222 basegfx::B2DRange aBufferRememberedRangeLogic(
223 maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
224 maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
225 aBufferRememberedRangeLogic.transform(getOutputDevice().GetInverseViewTransformation());
227 // prepare cursor handling
228 const bool bTargetIsWindow(OUTDEV_WINDOW == rmOutputDevice.GetOutDevType());
229 bool bCursorWasEnabled(false);
231 // #i80730# switch off VCL cursor during overlay refresh
232 if(bTargetIsWindow)
234 Window& rWindow = static_cast< Window& >(rmOutputDevice);
235 Cursor* pCursor = rWindow.GetCursor();
237 if(pCursor && pCursor->IsVisible())
239 pCursor->Hide();
240 bCursorWasEnabled = true;
244 if(DoRefreshWithPreRendering())
246 // #i73602# ensure valid and sized maOutputBufferDevice
247 const Size aDestinationSizePixel(maBufferDevice.GetOutputSizePixel());
248 const Size aOutputBufferSizePixel(maOutputBufferDevice.GetOutputSizePixel());
250 if(aDestinationSizePixel != aOutputBufferSizePixel)
252 maOutputBufferDevice.SetOutputSizePixel(aDestinationSizePixel);
255 maOutputBufferDevice.SetMapMode(getOutputDevice().GetMapMode());
256 maOutputBufferDevice.EnableMapMode(false);
257 maOutputBufferDevice.SetDrawMode(maBufferDevice.GetDrawMode());
258 maOutputBufferDevice.SetSettings(maBufferDevice.GetSettings());
259 maOutputBufferDevice.SetAntialiasing(maBufferDevice.GetAntialiasing());
261 // calculate sizes
262 Rectangle aRegionRectanglePixel(
263 maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
264 maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
266 // truncate aRegionRectanglePixel to destination pixel size, more does
267 // not need to be prepared since destination is a buffer for a window. So,
268 // maximum size indirectly shall be limited to getOutputDevice().GetOutputSizePixel()
269 if(aRegionRectanglePixel.Left() < 0L)
271 aRegionRectanglePixel.Left() = 0L;
274 if(aRegionRectanglePixel.Top() < 0L)
276 aRegionRectanglePixel.Top() = 0L;
279 if(aRegionRectanglePixel.Right() > aDestinationSizePixel.getWidth())
281 aRegionRectanglePixel.Right() = aDestinationSizePixel.getWidth();
284 if(aRegionRectanglePixel.Bottom() > aDestinationSizePixel.getHeight())
286 aRegionRectanglePixel.Bottom() = aDestinationSizePixel.getHeight();
289 // get sizes
290 const Point aTopLeft(aRegionRectanglePixel.TopLeft());
291 const Size aSize(aRegionRectanglePixel.GetSize());
294 const bool bMapModeWasEnabledDest(maBufferDevice.IsMapModeEnabled());
295 maBufferDevice.EnableMapMode(false);
297 maOutputBufferDevice.DrawOutDev(
298 aTopLeft, aSize, // destination
299 aTopLeft, aSize, // source
300 maBufferDevice);
302 // restore MapModes
303 maBufferDevice.EnableMapMode(bMapModeWasEnabledDest);
306 // paint overlay content for remembered region, use
307 // method from base class directly
308 maOutputBufferDevice.EnableMapMode(true);
309 OverlayManager::ImpDrawMembers(aBufferRememberedRangeLogic, maOutputBufferDevice);
310 maOutputBufferDevice.EnableMapMode(false);
312 // copy to output
314 const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
315 getOutputDevice().EnableMapMode(false);
317 getOutputDevice().DrawOutDev(
318 aTopLeft, aSize, // destination
319 aTopLeft, aSize, // source
320 maOutputBufferDevice);
322 // debug
323 /*getOutputDevice().SetLineColor(COL_RED);
324 getOutputDevice().SetFillColor();
325 getOutputDevice().DrawRect(Rectangle(aTopLeft, aSize));*/
327 // restore MapModes
328 getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
331 else
333 // Restore all rectangles for remembered region from buffer
334 ImpRestoreBackground();
336 // paint overlay content for remembered region, use
337 // method from base class directly
338 OverlayManager::ImpDrawMembers(aBufferRememberedRangeLogic, getOutputDevice());
341 // VCL hack for transparent child windows
342 // Problem is e.g. a radiobuttion form control in life mode. The used window
343 // is a transparence vcl childwindow. This flag only allows the parent window to
344 // paint into the child windows area, but there is no mechanism which takes
345 // care for a repaint of the child window. A transparent child window is NOT
346 // a window which always keeps it's content consistent over the parent, but it's
347 // more like just a paint flag for the parent.
348 // To get the update, the windows in question are updated manulally here.
349 if(bTargetIsWindow)
351 Window& rWindow = static_cast< Window& >(rmOutputDevice);
353 const Rectangle aRegionRectanglePixel(
354 maBufferRememberedRangePixel.getMinX(),
355 maBufferRememberedRangePixel.getMinY(),
356 maBufferRememberedRangePixel.getMaxX(),
357 maBufferRememberedRangePixel.getMaxY());
358 PaintTransparentChildren(rWindow, aRegionRectanglePixel);
361 // #i80730# restore visibility of VCL cursor
362 if(bCursorWasEnabled)
364 Window& rWindow = static_cast< Window& >(rmOutputDevice);
365 Cursor* pCursor = rWindow.GetCursor();
367 if(pCursor)
369 // check if cursor still exists. It may have been deleted from someone
370 pCursor->Show();
374 // forget remembered Region
375 maBufferRememberedRangePixel.reset();
378 return 0;
381 OverlayManagerBuffered::OverlayManagerBuffered(
382 OutputDevice& rOutputDevice,
383 bool bRefreshWithPreRendering)
384 : OverlayManager(rOutputDevice),
385 mbRefreshWithPreRendering(bRefreshWithPreRendering)
387 // Init timer
388 maBufferTimer.SetTimeout(1);
389 maBufferTimer.SetTimeoutHdl(LINK(this, OverlayManagerBuffered, ImpBufferTimerHandler));
392 rtl::Reference<OverlayManager> OverlayManagerBuffered::create(
393 OutputDevice& rOutputDevice,
394 bool bRefreshWithPreRendering)
396 return rtl::Reference<OverlayManager>(new OverlayManagerBuffered(rOutputDevice,
397 bRefreshWithPreRendering));
400 OverlayManagerBuffered::~OverlayManagerBuffered()
402 // Clear timer
403 maBufferTimer.Stop();
405 if(!maBufferRememberedRangePixel.isEmpty())
407 // Restore all rectangles for remembered region from buffer
408 ImpRestoreBackground();
412 void OverlayManagerBuffered::completeRedraw(const Region& rRegion, OutputDevice* pPreRenderDevice) const
414 if(!rRegion.IsEmpty())
416 // save new background
417 ((OverlayManagerBuffered*)this)->ImpSaveBackground(rRegion, pPreRenderDevice);
420 // call parent
421 OverlayManager::completeRedraw(rRegion, pPreRenderDevice);
424 void OverlayManagerBuffered::flush()
426 // call timer handler direct
427 ImpBufferTimerHandler(0);
430 // #i68597# part of content gets copied, react on it
431 void OverlayManagerBuffered::copyArea(const Point& rDestPt, const Point& rSrcPt, const Size& rSrcSize)
433 // scroll local buffered area
434 maBufferDevice.CopyArea(rDestPt, rSrcPt, rSrcSize);
437 void OverlayManagerBuffered::restoreBackground(const Region& rRegion) const
439 // restore
440 const Region aRegionPixel(getOutputDevice().LogicToPixel(rRegion));
441 ImpRestoreBackground(aRegionPixel);
443 // call parent
444 OverlayManager::restoreBackground(rRegion);
447 void OverlayManagerBuffered::invalidateRange(const basegfx::B2DRange& rRange)
449 if(!rRange.isEmpty())
451 // buffered output, do not invalidate but use the timer
452 // to trigger a timer event for refresh
453 maBufferTimer.Start();
455 // add the discrete range to the remembered region
456 // #i75163# use double precision and floor/ceil rounding to get overlapped pixel region, even
457 // when the given logic region has a width/height of 0.0. This does NOT work with LogicToPixel
458 // since it just transforms the top left and bottom right points equally without taking
459 // discrete pixel coverage into account. An empty B2DRange and thus empty logic Rectangle translated
460 // to an also empty discrete pixel rectangle - what is wrong.
461 basegfx::B2DRange aDiscreteRange(rRange);
462 aDiscreteRange.transform(getOutputDevice().GetViewTransformation());
464 if(maDrawinglayerOpt.IsAntiAliasing())
466 // assume AA needs one pixel more and invalidate one pixel more
467 const double fDiscreteOne(getDiscreteOne());
468 const basegfx::B2IPoint aTopLeft(
469 (sal_Int32)floor(aDiscreteRange.getMinX() - fDiscreteOne),
470 (sal_Int32)floor(aDiscreteRange.getMinY() - fDiscreteOne));
471 const basegfx::B2IPoint aBottomRight(
472 (sal_Int32)ceil(aDiscreteRange.getMaxX() + fDiscreteOne),
473 (sal_Int32)ceil(aDiscreteRange.getMaxY() + fDiscreteOne));
475 maBufferRememberedRangePixel.expand(aTopLeft);
476 maBufferRememberedRangePixel.expand(aBottomRight);
478 else
480 const basegfx::B2IPoint aTopLeft((sal_Int32)floor(aDiscreteRange.getMinX()), (sal_Int32)floor(aDiscreteRange.getMinY()));
481 const basegfx::B2IPoint aBottomRight((sal_Int32)ceil(aDiscreteRange.getMaxX()), (sal_Int32)ceil(aDiscreteRange.getMaxY()));
483 maBufferRememberedRangePixel.expand(aTopLeft);
484 maBufferRememberedRangePixel.expand(aBottomRight);
488 } // end of namespace overlay
489 } // end of namespace sdr
491 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */