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