Adjust includes
[LibreOffice.git] / svx / source / svdraw / sdrpaintwindow.cxx
blob5373093eb5b4f50db864a21e3b7b902d6fba1eab
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/lok.hxx>
21 #include <comphelper/random.hxx>
22 #include <svx/sdrpaintwindow.hxx>
23 #include <sdr/overlay/overlaymanagerbuffered.hxx>
24 #include <svx/svdpntv.hxx>
25 #include <vcl/gdimtf.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.hxx>
28 #include <set>
29 #include <vector>
31 //rhbz#1007697 do this in two loops, one to collect the candidates
32 //and another to update them because updating a candidate can
33 //trigger the candidate to be deleted, so asking for its
34 //sibling after that is going to fail hard
35 class CandidateMgr
37 std::vector<VclPtr<vcl::Window> > m_aCandidates;
38 std::set<VclPtr<vcl::Window> > m_aDeletedCandidates;
39 DECL_LINK(WindowEventListener, VclWindowEvent&, void);
40 public:
41 void PaintTransparentChildren(vcl::Window const & rWindow, tools::Rectangle const& rPixelRect);
42 ~CandidateMgr();
45 IMPL_LINK(CandidateMgr, WindowEventListener, VclWindowEvent&, rEvent, void)
47 vcl::Window* pWindow = rEvent.GetWindow();
48 if (rEvent.GetId() == VclEventId::ObjectDying)
50 m_aDeletedCandidates.insert(pWindow);
54 CandidateMgr::~CandidateMgr()
56 for (auto aI = m_aCandidates.begin(); aI != m_aCandidates.end(); ++aI)
58 VclPtr<vcl::Window> pCandidate = *aI;
59 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
60 continue;
61 pCandidate->RemoveEventListener(LINK(this, CandidateMgr, WindowEventListener));
65 void PaintTransparentChildren(vcl::Window const & rWindow, tools::Rectangle const& rPixelRect)
67 if (!rWindow.IsChildTransparentModeEnabled())
68 return;
70 CandidateMgr aManager;
71 aManager.PaintTransparentChildren(rWindow, rPixelRect);
74 void CandidateMgr::PaintTransparentChildren(vcl::Window const & rWindow, tools::Rectangle const& rPixelRect)
76 vcl::Window * pCandidate = rWindow.GetWindow( GetWindowType::FirstChild );
77 while (pCandidate)
79 if (pCandidate->IsPaintTransparent())
81 const tools::Rectangle aCandidatePosSizePixel(
82 pCandidate->GetPosPixel(),
83 pCandidate->GetSizePixel());
85 if (aCandidatePosSizePixel.IsOver(rPixelRect))
87 m_aCandidates.emplace_back(pCandidate);
88 pCandidate->AddEventListener(LINK(this, CandidateMgr, WindowEventListener));
91 pCandidate = pCandidate->GetWindow( GetWindowType::Next );
94 for (auto aI = m_aCandidates.begin(); aI != m_aCandidates.end(); ++aI)
96 pCandidate = aI->get();
97 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
98 continue;
99 //rhbz#1007697 this can cause the window itself to be
100 //deleted. So we are listening to see if that happens
101 //and if so, then skip the update
102 pCandidate->Invalidate(InvalidateFlags::NoTransparent|InvalidateFlags::Children);
103 // important: actually paint the child here!
104 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
105 continue;
106 pCandidate->Update();
110 SdrPreRenderDevice::SdrPreRenderDevice(OutputDevice& rOriginal)
111 : mpOutputDevice(&rOriginal),
112 mpPreRenderDevice(VclPtr<VirtualDevice>::Create())
116 SdrPreRenderDevice::~SdrPreRenderDevice()
118 mpPreRenderDevice.disposeAndClear();
121 void SdrPreRenderDevice::PreparePreRenderDevice()
123 // compare size of mpPreRenderDevice with size of visible area
124 if(mpPreRenderDevice->GetOutputSizePixel() != mpOutputDevice->GetOutputSizePixel())
126 mpPreRenderDevice->SetOutputSizePixel(mpOutputDevice->GetOutputSizePixel());
129 // Also compare the MapModes for zoom/scroll changes
130 if(mpPreRenderDevice->GetMapMode() != mpOutputDevice->GetMapMode())
132 mpPreRenderDevice->SetMapMode(mpOutputDevice->GetMapMode());
135 // #i29186#
136 mpPreRenderDevice->SetDrawMode(mpOutputDevice->GetDrawMode());
137 mpPreRenderDevice->SetSettings(mpOutputDevice->GetSettings());
140 void SdrPreRenderDevice::OutputPreRenderDevice(const vcl::Region& rExpandedRegion)
142 // region to pixels
143 const vcl::Region aRegionPixel(mpOutputDevice->LogicToPixel(rExpandedRegion));
144 //RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
145 //Rectangle aRegionRectanglePixel;
147 // MapModes off
148 bool bMapModeWasEnabledDest(mpOutputDevice->IsMapModeEnabled());
149 bool bMapModeWasEnabledSource(mpPreRenderDevice->IsMapModeEnabled());
150 mpOutputDevice->EnableMapMode(false);
151 mpPreRenderDevice->EnableMapMode(false);
153 RectangleVector aRectangles;
154 aRegionPixel.GetRegionRectangles(aRectangles);
156 for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
158 // for each rectangle, copy the area
159 const Point aTopLeft(aRectIter->TopLeft());
160 const Size aSize(aRectIter->GetSize());
162 mpOutputDevice->DrawOutDev(
163 aTopLeft, aSize,
164 aTopLeft, aSize,
165 *mpPreRenderDevice.get());
167 #ifdef DBG_UTIL
168 // #i74769#
169 static bool bDoPaintForVisualControlRegion(false);
171 if(bDoPaintForVisualControlRegion)
173 int nR = comphelper::rng::uniform_int_distribution(0, 0x7F-1);
174 int nG = comphelper::rng::uniform_int_distribution(0, 0x7F-1);
175 int nB = comphelper::rng::uniform_int_distribution(0, 0x7F-1);
176 const Color aColor(((((nR|0x80)<<8)|(nG|0x80))<<8)|(nB|0x80));
178 mpOutputDevice->SetLineColor(aColor);
179 mpOutputDevice->SetFillColor();
180 mpOutputDevice->DrawRect(*aRectIter);
182 #endif
185 mpOutputDevice->EnableMapMode(bMapModeWasEnabledDest);
186 mpPreRenderDevice->EnableMapMode(bMapModeWasEnabledSource);
190 void SdrPaintWindow::impCreateOverlayManager()
192 // not yet one created?
193 if(!mxOverlayManager.is())
195 // is it a window?
196 if(OUTDEV_WINDOW == GetOutputDevice().GetOutDevType())
198 vcl::Window& rWindow = dynamic_cast<vcl::Window&>(GetOutputDevice());
199 // decide which OverlayManager to use
200 if(GetPaintView().IsBufferedOverlayAllowed() && !rWindow.SupportsDoubleBuffering())
202 // buffered OverlayManager, buffers its background and refreshes from there
203 // for pure overlay changes (no system redraw). The 3rd parameter specifies
204 // whether that refresh itself will use a 2nd vdev to avoid flickering.
205 // Also hand over the old OverlayManager if existent; this means to take over
206 // the registered OverlayObjects from it
207 mxOverlayManager = sdr::overlay::OverlayManagerBuffered::create(GetOutputDevice());
209 else
211 // unbuffered OverlayManager, just invalidates places where changes
212 // take place
213 // Also hand over the old OverlayManager if existent; this means to take over
214 // the registered OverlayObjects from it
215 mxOverlayManager = sdr::overlay::OverlayManager::create(GetOutputDevice());
218 OSL_ENSURE(mxOverlayManager.is(), "SdrPaintWindow::SdrPaintWindow: Could not allocate an overlayManager (!)");
220 // Request a repaint so that the buffered overlay manager fills
221 // its buffer properly. This is a workaround for missing buffer
222 // updates.
223 if (!comphelper::LibreOfficeKit::isActive())
225 rWindow.Invalidate();
228 Color aColA(GetPaintView().getOptionsDrawinglayer().GetStripeColorA());
229 Color aColB(GetPaintView().getOptionsDrawinglayer().GetStripeColorB());
231 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
233 aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor();
234 aColB.Invert();
237 mxOverlayManager->setStripeColorA(aColA);
238 mxOverlayManager->setStripeColorB(aColB);
239 mxOverlayManager->setStripeLengthPixel(GetPaintView().getOptionsDrawinglayer().GetStripeLength());
244 SdrPaintWindow::SdrPaintWindow(SdrPaintView& rNewPaintView, OutputDevice& rOut, vcl::Window* pWindow)
245 : mpOutputDevice(&rOut),
246 mpWindow(pWindow),
247 mrPaintView(rNewPaintView),
248 mpPreRenderDevice(nullptr),
249 mbTemporaryTarget(false) // #i72889#
253 SdrPaintWindow::~SdrPaintWindow()
255 mxOverlayManager.clear();
257 DestroyPreRenderDevice();
260 rtl::Reference< sdr::overlay::OverlayManager > const & SdrPaintWindow::GetOverlayManager() const
262 if(!mxOverlayManager.is())
264 // Create buffered overlay manager by default.
265 const_cast< SdrPaintWindow* >(this)->impCreateOverlayManager();
268 return mxOverlayManager;
271 tools::Rectangle SdrPaintWindow::GetVisibleArea() const
273 Size aVisSizePixel(GetOutputDevice().GetOutputSizePixel());
274 return tools::Rectangle(GetOutputDevice().PixelToLogic(tools::Rectangle(Point(0,0), aVisSizePixel)));
277 bool SdrPaintWindow::OutputToRecordingMetaFile() const
279 GDIMetaFile* pMetaFile = mpOutputDevice->GetConnectMetaFile();
280 return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
283 void SdrPaintWindow::PreparePreRenderDevice()
285 const bool bPrepareBufferedOutput(
286 mrPaintView.IsBufferedOutputAllowed()
287 && !OutputToPrinter()
288 && !OutputToVirtualDevice()
289 && !OutputToRecordingMetaFile());
291 if(bPrepareBufferedOutput)
293 if(!mpPreRenderDevice)
295 mpPreRenderDevice = new SdrPreRenderDevice(*mpOutputDevice.get());
298 else
300 DestroyPreRenderDevice();
303 if(mpPreRenderDevice)
305 mpPreRenderDevice->PreparePreRenderDevice();
309 void SdrPaintWindow::DestroyPreRenderDevice()
311 if(mpPreRenderDevice)
313 delete mpPreRenderDevice;
314 mpPreRenderDevice = nullptr;
318 void SdrPaintWindow::OutputPreRenderDevice(const vcl::Region& rExpandedRegion)
320 if(mpPreRenderDevice)
322 mpPreRenderDevice->OutputPreRenderDevice(rExpandedRegion);
326 // #i73602# add flag if buffer shall be used
327 void SdrPaintWindow::DrawOverlay(const vcl::Region& rRegion)
329 // ## force creation of OverlayManager since the first repaint needs to
330 // save the background to get a controlled start into overlay mechanism
331 impCreateOverlayManager();
333 if(mxOverlayManager.is() && !OutputToPrinter())
335 if(mpPreRenderDevice)
337 mxOverlayManager->completeRedraw(rRegion, &mpPreRenderDevice->GetPreRenderDevice());
339 else
341 mxOverlayManager->completeRedraw(rRegion);
347 void SdrPaintWindow::SetRedrawRegion(const vcl::Region& rNew)
349 maRedrawRegion = rNew;
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */