1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <svx/sdrpaintwindow.hxx>
31 #include <svx/sdr/overlay/overlaymanagerbuffered.hxx>
32 #include <svx/svdpntv.hxx>
33 #include <vcl/gdimtf.hxx>
34 #include <vcl/svapp.hxx>
35 
36 ////////////////////////////////////////////////////////////////////////////////////////////////////
37 
38 SdrPreRenderDevice::SdrPreRenderDevice(OutputDevice& rOriginal)
39 :	mrOutputDevice(rOriginal)
40 {
41 }
42 
43 SdrPreRenderDevice::~SdrPreRenderDevice()
44 {
45 }
46 
47 void SdrPreRenderDevice::PreparePreRenderDevice()
48 {
49 	// compare size of maPreRenderDevice with size of visible area
50 	if(maPreRenderDevice.GetOutputSizePixel() != mrOutputDevice.GetOutputSizePixel())
51 	{
52 		maPreRenderDevice.SetOutputSizePixel(mrOutputDevice.GetOutputSizePixel());
53 	}
54 
55 	// Also compare the MapModes for zoom/scroll changes
56 	if(maPreRenderDevice.GetMapMode() != mrOutputDevice.GetMapMode())
57 	{
58 		maPreRenderDevice.SetMapMode(mrOutputDevice.GetMapMode());
59 	}
60 
61 	// #i29186#
62 	maPreRenderDevice.SetDrawMode(mrOutputDevice.GetDrawMode());
63 	maPreRenderDevice.SetSettings(mrOutputDevice.GetSettings());
64 }
65 
66 void SdrPreRenderDevice::OutputPreRenderDevice(const Region& rExpandedRegion)
67 {
68 	// region to pixels
69 	Region aRegionPixel(mrOutputDevice.LogicToPixel(rExpandedRegion));
70 	RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
71 	Rectangle aRegionRectanglePixel;
72 
73 	// MapModes off
74 	sal_Bool bMapModeWasEnabledDest(mrOutputDevice.IsMapModeEnabled());
75 	sal_Bool bMapModeWasEnabledSource(maPreRenderDevice.IsMapModeEnabled());
76 	mrOutputDevice.EnableMapMode(sal_False);
77 	maPreRenderDevice.EnableMapMode(sal_False);
78 
79 	while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
80 	{
81 		// for each rectangle, copy the area
82 		const Point aTopLeft(aRegionRectanglePixel.TopLeft());
83 		const Size aSize(aRegionRectanglePixel.GetSize());
84 
85 		mrOutputDevice.DrawOutDev(
86 			aTopLeft, aSize,
87 			aTopLeft, aSize,
88 			maPreRenderDevice);
89 
90 #ifdef DBG_UTIL
91 		// #i74769#
92 		static bool bDoPaintForVisualControlRegion(false);
93 		if(bDoPaintForVisualControlRegion)
94 		{
95 			Color aColor((((((rand()&0x7f)|0x80)<<8L)|((rand()&0x7f)|0x80))<<8L)|((rand()&0x7f)|0x80));
96 			mrOutputDevice.SetLineColor(aColor);
97 			mrOutputDevice.SetFillColor();
98 			mrOutputDevice.DrawRect(aRegionRectanglePixel);
99 		}
100 #endif
101 	}
102 
103 	aRegionPixel.EndEnumRects(aRegionHandle);
104 
105 	mrOutputDevice.EnableMapMode(bMapModeWasEnabledDest);
106 	maPreRenderDevice.EnableMapMode(bMapModeWasEnabledSource);
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////////////////////////
110 
111 void SdrPaintWindow::impCreateOverlayManager(const bool bUseBuffer)
112 {
113     // When the buffer usage has changed then we have to create a new
114     // overlay manager.  Save the current one so that later we can move its
115     // overlay objects to the new one.
116     sdr::overlay::OverlayManager* pOldOverlayManager = NULL;
117 
118 	if(mbUseBuffer != bUseBuffer)
119     {
120         mbUseBuffer = bUseBuffer;
121         pOldOverlayManager = mpOverlayManager;
122         mpOverlayManager = NULL;
123     }
124 
125 	// not yet one created?
126 	if(!mpOverlayManager)
127 	{
128 		// is it a window?
129 		if(OUTDEV_WINDOW == GetOutputDevice().GetOutDevType())
130 		{
131 			// decide which OverlayManager to use
132 			if(GetPaintView().IsBufferedOverlayAllowed() && mbUseBuffer)
133 			{
134 				// buffered OverlayManager, buffers it's background and refreshes from there
135 				// for pure overlay changes (no system redraw). The 3rd parameter specifies
136 				// if that refresh itself will use a 2nd vdev to avoid flickering.
137 				// Also hand over the evtl. existing old OverlayManager; this means to take over
138 				// the registered OverlayObjects from it
139 				mpOverlayManager = new ::sdr::overlay::OverlayManagerBuffered(GetOutputDevice(), pOldOverlayManager, true);
140 			}
141 			else
142 			{
143 				// unbuffered OverlayManager, just invalidates places where changes
144 				// take place
145 				// Also hand over the evtl. existing old OverlayManager; this means to take over
146 				// the registered OverlayObjects from it
147 				mpOverlayManager = new ::sdr::overlay::OverlayManager(GetOutputDevice(), pOldOverlayManager);
148 			}
149 
150 			OSL_ENSURE(mpOverlayManager, "SdrPaintWindow::SdrPaintWindow: Could not allocate an overlayManager (!)");
151 
152             // Request a repaint so that the buffered overlay manager fills
153             // its buffer properly.  This is a workaround for missing buffer
154             // updates.
155             Window* pWindow = dynamic_cast<Window*>(&GetOutputDevice());
156             if (pWindow != NULL)
157                 pWindow->Invalidate();
158 
159 			Color aColA(GetPaintView().getOptionsDrawinglayer().GetStripeColorA());
160 			Color aColB(GetPaintView().getOptionsDrawinglayer().GetStripeColorB());
161 
162 			if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
163 			{
164 				aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor();
165 				aColB.Invert();
166 			}
167 
168 			mpOverlayManager->setStripeColorA(aColA);
169 			mpOverlayManager->setStripeColorB(aColB);
170 			mpOverlayManager->setStripeLengthPixel(GetPaintView().getOptionsDrawinglayer().GetStripeLength());
171 		}
172 	}
173 
174 	// OverlayObjects are transfered for the evtl. newly created OverlayManager by handing over
175 	// at construction time
176 	if(pOldOverlayManager)
177     {
178         // The old overlay manager is not used anymore and can be (has to be) deleted.
179         delete pOldOverlayManager;
180     }
181 }
182 
183 SdrPaintWindow::SdrPaintWindow(SdrPaintView& rNewPaintView, OutputDevice& rOut)
184 :	mrOutputDevice(rOut),
185 	mrPaintView(rNewPaintView),
186 	mpOverlayManager(0L),
187 	mpPreRenderDevice(0L),
188 	mbTemporaryTarget(false), // #i72889#
189     mbUseBuffer(true)
190 {
191 }
192 
193 SdrPaintWindow::~SdrPaintWindow()
194 {
195 	if(mpOverlayManager)
196 	{
197 		delete mpOverlayManager;
198 		mpOverlayManager = 0L;
199 	}
200 
201 	DestroyPreRenderDevice();
202 }
203 
204 ::sdr::overlay::OverlayManager* SdrPaintWindow::GetOverlayManager() const
205 {
206 	if(!mpOverlayManager)
207 	{
208         // Create buffered overlay manager by default.
209 		const_cast< SdrPaintWindow* >(this)->impCreateOverlayManager(true);
210 	}
211 
212 	return mpOverlayManager;
213 }
214 
215 Rectangle SdrPaintWindow::GetVisibleArea() const
216 {
217 	Size aVisSizePixel(GetOutputDevice().GetOutputSizePixel());
218 	return Rectangle(GetOutputDevice().PixelToLogic(Rectangle(Point(0,0), aVisSizePixel)));
219 }
220 
221 sal_Bool SdrPaintWindow::OutputToRecordingMetaFile() const
222 {
223 	GDIMetaFile* pMetaFile = mrOutputDevice.GetConnectMetaFile();
224 	return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
225 }
226 
227 void SdrPaintWindow::PreparePreRenderDevice()
228 {
229 	const sal_Bool bPrepareBufferedOutput(
230 		mrPaintView.IsBufferedOutputAllowed()
231 		&& !OutputToPrinter()
232 		&& !OutputToVirtualDevice()
233 		&& !OutputToRecordingMetaFile());
234 
235 	if(bPrepareBufferedOutput)
236 	{
237 		if(!mpPreRenderDevice)
238 		{
239 			mpPreRenderDevice = new SdrPreRenderDevice(mrOutputDevice);
240 		}
241 	}
242 	else
243 	{
244 		DestroyPreRenderDevice();
245 	}
246 
247 	if(mpPreRenderDevice)
248 	{
249 		mpPreRenderDevice->PreparePreRenderDevice();
250 	}
251 }
252 
253 void SdrPaintWindow::DestroyPreRenderDevice()
254 {
255 	if(mpPreRenderDevice)
256 	{
257 		delete mpPreRenderDevice;
258 		mpPreRenderDevice = 0L;
259 	}
260 }
261 
262 void SdrPaintWindow::OutputPreRenderDevice(const Region& rExpandedRegion)
263 {
264 	if(mpPreRenderDevice)
265 	{
266 		mpPreRenderDevice->OutputPreRenderDevice(rExpandedRegion);
267 	}
268 }
269 
270 // #i73602# add flag if buffer shall be used
271 void SdrPaintWindow::DrawOverlay(const Region& rRegion, bool bUseBuffer)
272 {
273 	// ## force creation of OverlayManager since the first repaint needs to
274 	// save the background to get a controlled start into overlay mechanism
275 	impCreateOverlayManager(bUseBuffer);
276 
277 	if(mpOverlayManager && !OutputToPrinter())
278 	{
279 		if(mpPreRenderDevice && bUseBuffer)
280 		{
281 			mpOverlayManager->completeRedraw(rRegion, &mpPreRenderDevice->GetPreRenderDevice());
282 		}
283 		else
284 		{
285 			mpOverlayManager->completeRedraw(rRegion);
286 		}
287 	}
288 }
289 
290 void SdrPaintWindow::HideOverlay(const Region& rRegion)
291 {
292 	if(mpOverlayManager && !OutputToPrinter())
293 	{
294 		if(!mpPreRenderDevice)
295 		{
296 			mpOverlayManager->restoreBackground(rRegion);
297 		}
298 	}
299 }
300 
301 const Region& SdrPaintWindow::GetRedrawRegion() const
302 {
303 	return maRedrawRegion;
304 }
305 
306 void SdrPaintWindow::SetRedrawRegion(const Region& rNew)
307 {
308 	maRedrawRegion = rNew;
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////////////////////////
312 // eof
313