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