bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / sdrpaintwindow.cxx
blob8a2da86d6ce5c40bd0808e18dcd32fb0265dc4f4
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 <comphelper/random.hxx>
21 #include <svx/sdrpaintwindow.hxx>
22 #include <sdr/overlay/overlaymanagerbuffered.hxx>
23 #include <svx/svdpntv.hxx>
24 #include <vcl/gdimtf.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/settings.hxx>
27 #include <set>
28 #include <vector>
30 //rhbz#1007697 do this in two loops, one to collect the candidates
31 //and another to update them because updating a candidate can
32 //trigger the candidate to be deleted, so asking for its
33 //sibling after that is going to fail hard
34 class CandidateMgr
36 std::vector<VclPtr<vcl::Window> > m_aCandidates;
37 std::set<VclPtr<vcl::Window> > m_aDeletedCandidates;
38 DECL_LINK(WindowEventListener, VclSimpleEvent*);
39 public:
40 void PaintTransparentChildren(vcl::Window & rWindow, Rectangle const& rPixelRect);
41 ~CandidateMgr();
44 IMPL_LINK(CandidateMgr, WindowEventListener, VclSimpleEvent*, pEvent)
46 VclWindowEvent* pWinEvent = dynamic_cast< VclWindowEvent* >( pEvent );
47 if (pWinEvent)
49 vcl::Window* pWindow = pWinEvent->GetWindow();
50 if (pWinEvent->GetId() == VCLEVENT_OBJECT_DYING)
52 m_aDeletedCandidates.insert(pWindow);
56 return 0;
59 CandidateMgr::~CandidateMgr()
61 for (auto aI = m_aCandidates.begin(); aI != m_aCandidates.end(); ++aI)
63 VclPtr<vcl::Window> pCandidate = *aI;
64 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
65 continue;
66 pCandidate->RemoveEventListener(LINK(this, CandidateMgr, WindowEventListener));
70 void PaintTransparentChildren(vcl::Window & rWindow, Rectangle const& rPixelRect)
72 if (!rWindow.IsChildTransparentModeEnabled())
73 return;
75 CandidateMgr aManager;
76 aManager.PaintTransparentChildren(rWindow, rPixelRect);
79 void CandidateMgr::PaintTransparentChildren(vcl::Window & rWindow, Rectangle const& rPixelRect)
81 vcl::Window * pCandidate = rWindow.GetWindow( GetWindowType::FirstChild );
82 while (pCandidate)
84 if (pCandidate->IsPaintTransparent())
86 const Rectangle aCandidatePosSizePixel(
87 pCandidate->GetPosPixel(),
88 pCandidate->GetSizePixel());
90 if (aCandidatePosSizePixel.IsOver(rPixelRect))
92 m_aCandidates.push_back(pCandidate);
93 pCandidate->AddEventListener(LINK(this, CandidateMgr, WindowEventListener));
96 pCandidate = pCandidate->GetWindow( GetWindowType::Next );
99 for (auto aI = m_aCandidates.begin(); 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),
117 mpPreRenderDevice(VclPtr<VirtualDevice>::Create())
121 SdrPreRenderDevice::~SdrPreRenderDevice()
123 mpPreRenderDevice.disposeAndClear();
126 void SdrPreRenderDevice::PreparePreRenderDevice()
128 // compare size of mpPreRenderDevice with size of visible area
129 if(mpPreRenderDevice->GetOutputSizePixel() != mrOutputDevice.GetOutputSizePixel())
131 mpPreRenderDevice->SetOutputSizePixel(mrOutputDevice.GetOutputSizePixel());
134 // Also compare the MapModes for zoom/scroll changes
135 if(mpPreRenderDevice->GetMapMode() != mrOutputDevice.GetMapMode())
137 mpPreRenderDevice->SetMapMode(mrOutputDevice.GetMapMode());
140 // #i29186#
141 mpPreRenderDevice->SetDrawMode(mrOutputDevice.GetDrawMode());
142 mpPreRenderDevice->SetSettings(mrOutputDevice.GetSettings());
145 void SdrPreRenderDevice::OutputPreRenderDevice(const vcl::Region& rExpandedRegion)
147 // region to pixels
148 const vcl::Region aRegionPixel(mrOutputDevice.LogicToPixel(rExpandedRegion));
149 //RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
150 //Rectangle aRegionRectanglePixel;
152 // MapModes off
153 bool bMapModeWasEnabledDest(mrOutputDevice.IsMapModeEnabled());
154 bool bMapModeWasEnabledSource(mpPreRenderDevice->IsMapModeEnabled());
155 mrOutputDevice.EnableMapMode(false);
156 mpPreRenderDevice->EnableMapMode(false);
158 RectangleVector aRectangles;
159 aRegionPixel.GetRegionRectangles(aRectangles);
161 for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
163 // for each rectangle, copy the area
164 const Point aTopLeft(aRectIter->TopLeft());
165 const Size aSize(aRectIter->GetSize());
167 mrOutputDevice.DrawOutDev(
168 aTopLeft, aSize,
169 aTopLeft, aSize,
170 *mpPreRenderDevice.get());
172 #ifdef DBG_UTIL
173 // #i74769#
174 static bool bDoPaintForVisualControlRegion(false);
176 if(bDoPaintForVisualControlRegion)
178 int nR = comphelper::rng::uniform_int_distribution(0, 0x7F-1);
179 int nG = comphelper::rng::uniform_int_distribution(0, 0x7F-1);
180 int nB = comphelper::rng::uniform_int_distribution(0, 0x7F-1);
181 const Color aColor(((((nR|0x80)<<8L)|(nG|0x80))<<8L)|(nB|0x80));
183 mrOutputDevice.SetLineColor(aColor);
184 mrOutputDevice.SetFillColor();
185 mrOutputDevice.DrawRect(*aRectIter);
187 #endif
190 mrOutputDevice.EnableMapMode(bMapModeWasEnabledDest);
191 mpPreRenderDevice->EnableMapMode(bMapModeWasEnabledSource);
196 void SdrPaintWindow::impCreateOverlayManager()
198 // not yet one created?
199 if(!mxOverlayManager.is())
201 // is it a window?
202 if(OUTDEV_WINDOW == GetOutputDevice().GetOutDevType())
204 vcl::Window* pWindow = dynamic_cast<vcl::Window*>(&GetOutputDevice());
205 // decide which OverlayManager to use
206 if(GetPaintView().IsBufferedOverlayAllowed() && mbUseBuffer && !pWindow->SupportsDoubleBuffering())
208 // buffered OverlayManager, buffers its background and refreshes from there
209 // for pure overlay changes (no system redraw). The 3rd parameter specifies
210 // whether that refresh itself will use a 2nd vdev to avoid flickering.
211 // Also hand over the old OverlayManager if existent; this means to take over
212 // the registered OverlayObjects from it
213 mxOverlayManager = sdr::overlay::OverlayManagerBuffered::create(GetOutputDevice(), GetPaintView().GetModel(), true);
215 else
217 // unbuffered OverlayManager, just invalidates places where changes
218 // take place
219 // Also hand over the old OverlayManager if existent; this means to take over
220 // the registered OverlayObjects from it
221 mxOverlayManager = sdr::overlay::OverlayManager::create(GetOutputDevice(), GetPaintView().GetModel());
224 OSL_ENSURE(mxOverlayManager.is(), "SdrPaintWindow::SdrPaintWindow: Could not allocate an overlayManager (!)");
226 // Request a repaint so that the buffered overlay manager fills
227 // its buffer properly. This is a workaround for missing buffer
228 // updates.
229 if (pWindow != NULL)
230 pWindow->Invalidate();
232 Color aColA(GetPaintView().getOptionsDrawinglayer().GetStripeColorA());
233 Color aColB(GetPaintView().getOptionsDrawinglayer().GetStripeColorB());
235 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
237 aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor();
238 aColB.Invert();
241 mxOverlayManager->setStripeColorA(aColA);
242 mxOverlayManager->setStripeColorB(aColB);
243 mxOverlayManager->setStripeLengthPixel(GetPaintView().getOptionsDrawinglayer().GetStripeLength());
248 SdrPaintWindow::SdrPaintWindow(SdrPaintView& rNewPaintView, OutputDevice& rOut, vcl::Window* pWindow)
249 : mrOutputDevice(rOut),
250 mpWindow(pWindow),
251 mrPaintView(rNewPaintView),
252 mpPreRenderDevice(0L),
253 mbTemporaryTarget(false), // #i72889#
254 mbUseBuffer(true)
258 SdrPaintWindow::~SdrPaintWindow()
260 mxOverlayManager.clear();
262 DestroyPreRenderDevice();
265 rtl::Reference< sdr::overlay::OverlayManager > SdrPaintWindow::GetOverlayManager() const
267 if(!mxOverlayManager.is())
269 // Create buffered overlay manager by default.
270 const_cast< SdrPaintWindow* >(this)->impCreateOverlayManager();
273 return mxOverlayManager;
276 Rectangle SdrPaintWindow::GetVisibleArea() const
278 Size aVisSizePixel(GetOutputDevice().GetOutputSizePixel());
279 return Rectangle(GetOutputDevice().PixelToLogic(Rectangle(Point(0,0), aVisSizePixel)));
282 bool SdrPaintWindow::OutputToRecordingMetaFile() const
284 GDIMetaFile* pMetaFile = mrOutputDevice.GetConnectMetaFile();
285 return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
288 void SdrPaintWindow::PreparePreRenderDevice()
290 const bool bPrepareBufferedOutput(
291 mrPaintView.IsBufferedOutputAllowed()
292 && !OutputToPrinter()
293 && !OutputToVirtualDevice()
294 && !OutputToRecordingMetaFile());
296 if(bPrepareBufferedOutput)
298 if(!mpPreRenderDevice)
300 mpPreRenderDevice = new SdrPreRenderDevice(mrOutputDevice);
303 else
305 DestroyPreRenderDevice();
308 if(mpPreRenderDevice)
310 mpPreRenderDevice->PreparePreRenderDevice();
314 void SdrPaintWindow::DestroyPreRenderDevice()
316 if(mpPreRenderDevice)
318 delete mpPreRenderDevice;
319 mpPreRenderDevice = 0L;
323 void SdrPaintWindow::OutputPreRenderDevice(const vcl::Region& rExpandedRegion)
325 if(mpPreRenderDevice)
327 mpPreRenderDevice->OutputPreRenderDevice(rExpandedRegion);
331 // #i73602# add flag if buffer shall be used
332 void SdrPaintWindow::DrawOverlay(const vcl::Region& rRegion)
334 // ## force creation of OverlayManager since the first repaint needs to
335 // save the background to get a controlled start into overlay mechanism
336 impCreateOverlayManager();
338 if(mxOverlayManager.is() && !OutputToPrinter())
340 if(mpPreRenderDevice)
342 mxOverlayManager->completeRedraw(rRegion, &mpPreRenderDevice->GetPreRenderDevice());
344 else
346 mxOverlayManager->completeRedraw(rRegion);
352 void SdrPaintWindow::SetRedrawRegion(const vcl::Region& rNew)
354 maRedrawRegion = rNew;
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */