bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / svdraw / sdrpaintwindow.cxx
blobda94126cb55e9b7218c3fbb5c45aea13181ce578
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/sdrpaintwindow.hxx>
21 #include <svx/sdr/overlay/overlaymanagerbuffered.hxx>
22 #include <svx/svdpntv.hxx>
23 #include <vcl/gdimtf.hxx>
24 #include <vcl/svapp.hxx>
25 #include <set>
26 #include <vector>
28 //rhbz#1007697 do this in two loops, one to collect the candidates
29 //and another to update them because updating a candidate can
30 //trigger the candidate to be deleted, so asking for its
31 //sibling after that is going to fail hard
32 class CandidateMgr
34 std::vector<Window*> m_aCandidates;
35 std::set<Window*> m_aDeletedCandidates;
36 DECL_LINK(WindowEventListener, VclSimpleEvent*);
37 public:
38 void PaintTransparentChildren(Window & rWindow, Rectangle const& rPixelRect);
39 ~CandidateMgr();
42 IMPL_LINK(CandidateMgr, WindowEventListener, VclSimpleEvent*, pEvent)
44 VclWindowEvent* pWinEvent = dynamic_cast< VclWindowEvent* >( pEvent );
45 if (pWinEvent)
47 Window* pWindow = pWinEvent->GetWindow();
48 if (pWinEvent->GetId() == VCLEVENT_OBJECT_DYING)
50 m_aDeletedCandidates.insert(pWindow);
54 return 0;
57 CandidateMgr::~CandidateMgr()
59 for (std::vector<Window*>::iterator aI = m_aCandidates.begin();
60 aI != m_aCandidates.end(); ++aI)
62 Window* pCandidate = *aI;
63 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
64 continue;
65 pCandidate->RemoveEventListener(LINK(this, CandidateMgr, WindowEventListener));
69 void PaintTransparentChildren(Window & rWindow, Rectangle const& rPixelRect)
71 if (!rWindow.IsChildTransparentModeEnabled())
72 return;
74 CandidateMgr aManager;
75 aManager.PaintTransparentChildren(rWindow, rPixelRect);
78 void CandidateMgr::PaintTransparentChildren(Window & rWindow, Rectangle const& rPixelRect)
80 Window * pCandidate = rWindow.GetWindow( WINDOW_FIRSTCHILD );
81 while (pCandidate)
83 if (pCandidate->IsPaintTransparent())
85 const Rectangle aCandidatePosSizePixel(
86 pCandidate->GetPosPixel(),
87 pCandidate->GetSizePixel());
89 if (aCandidatePosSizePixel.IsOver(rPixelRect))
91 m_aCandidates.push_back(pCandidate);
92 pCandidate->AddEventListener(LINK(this, CandidateMgr, WindowEventListener));
95 pCandidate = pCandidate->GetWindow( WINDOW_NEXT );
98 for (std::vector<Window*>::iterator aI = m_aCandidates.begin();
99 aI != m_aCandidates.end(); ++aI)
101 pCandidate = *aI;
102 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
103 continue;
104 //rhbz#1007697 this can cause the window itself to be
105 //deleted. So we are listening to see if that happens
106 //and if so, then skip the update
107 pCandidate->Invalidate(INVALIDATE_NOTRANSPARENT|INVALIDATE_CHILDREN);
108 // important: actually paint the child here!
109 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
110 continue;
111 pCandidate->Update();
115 SdrPreRenderDevice::SdrPreRenderDevice(OutputDevice& rOriginal)
116 : mrOutputDevice(rOriginal)
120 SdrPreRenderDevice::~SdrPreRenderDevice()
124 void SdrPreRenderDevice::PreparePreRenderDevice()
126 // compare size of maPreRenderDevice with size of visible area
127 if(maPreRenderDevice.GetOutputSizePixel() != mrOutputDevice.GetOutputSizePixel())
129 maPreRenderDevice.SetOutputSizePixel(mrOutputDevice.GetOutputSizePixel());
132 // Also compare the MapModes for zoom/scroll changes
133 if(maPreRenderDevice.GetMapMode() != mrOutputDevice.GetMapMode())
135 maPreRenderDevice.SetMapMode(mrOutputDevice.GetMapMode());
138 // #i29186#
139 maPreRenderDevice.SetDrawMode(mrOutputDevice.GetDrawMode());
140 maPreRenderDevice.SetSettings(mrOutputDevice.GetSettings());
143 void SdrPreRenderDevice::OutputPreRenderDevice(const Region& rExpandedRegion)
145 // region to pixels
146 Region aRegionPixel(mrOutputDevice.LogicToPixel(rExpandedRegion));
147 RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
148 Rectangle aRegionRectanglePixel;
150 // MapModes off
151 sal_Bool bMapModeWasEnabledDest(mrOutputDevice.IsMapModeEnabled());
152 sal_Bool bMapModeWasEnabledSource(maPreRenderDevice.IsMapModeEnabled());
153 mrOutputDevice.EnableMapMode(sal_False);
154 maPreRenderDevice.EnableMapMode(sal_False);
156 while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
158 // for each rectangle, copy the area
159 const Point aTopLeft(aRegionRectanglePixel.TopLeft());
160 const Size aSize(aRegionRectanglePixel.GetSize());
162 mrOutputDevice.DrawOutDev(
163 aTopLeft, aSize,
164 aTopLeft, aSize,
165 maPreRenderDevice);
167 #ifdef DBG_UTIL
168 // #i74769#
169 static bool bDoPaintForVisualControlRegion(false);
170 if(bDoPaintForVisualControlRegion)
172 Color aColor((((((rand()&0x7f)|0x80)<<8L)|((rand()&0x7f)|0x80))<<8L)|((rand()&0x7f)|0x80));
173 mrOutputDevice.SetLineColor(aColor);
174 mrOutputDevice.SetFillColor();
175 mrOutputDevice.DrawRect(aRegionRectanglePixel);
177 #endif
180 aRegionPixel.EndEnumRects(aRegionHandle);
182 mrOutputDevice.EnableMapMode(bMapModeWasEnabledDest);
183 maPreRenderDevice.EnableMapMode(bMapModeWasEnabledSource);
186 ////////////////////////////////////////////////////////////////////////////////////////////////////
188 void SdrPaintWindow::impCreateOverlayManager()
190 // not yet one created?
191 if(!mxOverlayManager.is())
193 // is it a window?
194 if(OUTDEV_WINDOW == GetOutputDevice().GetOutDevType())
196 // decide which OverlayManager to use
197 if(GetPaintView().IsBufferedOverlayAllowed() && mbUseBuffer)
199 // buffered OverlayManager, buffers its background and refreshes from there
200 // for pure overlay changes (no system redraw). The 3rd parameter specifies
201 // whether that refresh itself will use a 2nd vdev to avoid flickering.
202 // Also hand over the old OverlayManager if existent; this means to take over
203 // the registered OverlayObjects from it
204 mxOverlayManager = ::sdr::overlay::OverlayManagerBuffered::create(GetOutputDevice(), true);
206 else
208 // unbuffered OverlayManager, just invalidates places where changes
209 // take place
210 // Also hand over the old OverlayManager if existent; this means to take over
211 // the registered OverlayObjects from it
212 mxOverlayManager = ::sdr::overlay::OverlayManager::create(GetOutputDevice());
215 OSL_ENSURE(mxOverlayManager.is(), "SdrPaintWindow::SdrPaintWindow: Could not allocate an overlayManager (!)");
217 // Request a repaint so that the buffered overlay manager fills
218 // its buffer properly. This is a workaround for missing buffer
219 // updates.
220 Window* pWindow = dynamic_cast<Window*>(&GetOutputDevice());
221 if (pWindow != NULL)
222 pWindow->Invalidate();
224 Color aColA(GetPaintView().getOptionsDrawinglayer().GetStripeColorA());
225 Color aColB(GetPaintView().getOptionsDrawinglayer().GetStripeColorB());
227 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
229 aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor();
230 aColB.Invert();
233 mxOverlayManager->setStripeColorA(aColA);
234 mxOverlayManager->setStripeColorB(aColB);
235 mxOverlayManager->setStripeLengthPixel(GetPaintView().getOptionsDrawinglayer().GetStripeLength());
240 SdrPaintWindow::SdrPaintWindow(SdrPaintView& rNewPaintView, OutputDevice& rOut)
241 : mrOutputDevice(rOut),
242 mrPaintView(rNewPaintView),
243 mpPreRenderDevice(0L),
244 mbTemporaryTarget(false), // #i72889#
245 mbUseBuffer(true)
249 SdrPaintWindow::~SdrPaintWindow()
251 mxOverlayManager.clear();
253 DestroyPreRenderDevice();
256 rtl::Reference< ::sdr::overlay::OverlayManager > SdrPaintWindow::GetOverlayManager() const
258 if(!mxOverlayManager.is())
260 // Create buffered overlay manager by default.
261 const_cast< SdrPaintWindow* >(this)->impCreateOverlayManager();
264 return mxOverlayManager;
267 Rectangle SdrPaintWindow::GetVisibleArea() const
269 Size aVisSizePixel(GetOutputDevice().GetOutputSizePixel());
270 return Rectangle(GetOutputDevice().PixelToLogic(Rectangle(Point(0,0), aVisSizePixel)));
273 bool SdrPaintWindow::OutputToRecordingMetaFile() const
275 GDIMetaFile* pMetaFile = mrOutputDevice.GetConnectMetaFile();
276 return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
279 void SdrPaintWindow::PreparePreRenderDevice()
281 const bool bPrepareBufferedOutput(
282 mrPaintView.IsBufferedOutputAllowed()
283 && !OutputToPrinter()
284 && !OutputToVirtualDevice()
285 && !OutputToRecordingMetaFile());
287 if(bPrepareBufferedOutput)
289 if(!mpPreRenderDevice)
291 mpPreRenderDevice = new SdrPreRenderDevice(mrOutputDevice);
294 else
296 DestroyPreRenderDevice();
299 if(mpPreRenderDevice)
301 mpPreRenderDevice->PreparePreRenderDevice();
305 void SdrPaintWindow::DestroyPreRenderDevice()
307 if(mpPreRenderDevice)
309 delete mpPreRenderDevice;
310 mpPreRenderDevice = 0L;
314 void SdrPaintWindow::OutputPreRenderDevice(const Region& rExpandedRegion)
316 if(mpPreRenderDevice)
318 mpPreRenderDevice->OutputPreRenderDevice(rExpandedRegion);
322 // #i73602# add flag if buffer shall be used
323 void SdrPaintWindow::DrawOverlay(const Region& rRegion)
325 // ## force creation of OverlayManager since the first repaint needs to
326 // save the background to get a controlled start into overlay mechanism
327 impCreateOverlayManager();
329 if(mxOverlayManager.is() && !OutputToPrinter())
331 if(mpPreRenderDevice)
333 mxOverlayManager->completeRedraw(rRegion, &mpPreRenderDevice->GetPreRenderDevice());
335 else
337 mxOverlayManager->completeRedraw(rRegion);
342 const Region& SdrPaintWindow::GetRedrawRegion() const
344 return maRedrawRegion;
347 void SdrPaintWindow::SetRedrawRegion(const Region& rNew)
349 maRedrawRegion = rNew;
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */