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