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