LibreOffice Module svx (master) 1
sdrpaintwindow.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <comphelper/lok.hxx>
21#include <osl/diagnose.h>
24#include <svx/svdpntv.hxx>
25#include <vcl/gdimtf.hxx>
26#include <vcl/svapp.hxx>
27#include <vcl/settings.hxx>
28#include <vcl/window.hxx>
30#include <set>
31#include <vector>
32
33namespace {
34
35//rhbz#1007697 do this in two loops, one to collect the candidates
36//and another to update them because updating a candidate can
37//trigger the candidate to be deleted, so asking for its
38//sibling after that is going to fail hard
39class CandidateMgr
40{
41 std::vector<VclPtr<vcl::Window> > m_aCandidates;
42 std::set<VclPtr<vcl::Window> > m_aDeletedCandidates;
43 DECL_LINK(WindowEventListener, VclWindowEvent&, void);
44public:
45 void PaintTransparentChildren(vcl::Window const & rWindow, tools::Rectangle const& rPixelRect);
46 ~CandidateMgr();
47};
48
49}
50
51IMPL_LINK(CandidateMgr, WindowEventListener, VclWindowEvent&, rEvent, void)
52{
53 vcl::Window* pWindow = rEvent.GetWindow();
54 if (rEvent.GetId() == VclEventId::ObjectDying)
55 {
56 m_aDeletedCandidates.insert(pWindow);
57 }
58}
59
60CandidateMgr::~CandidateMgr()
61{
62 for (VclPtr<vcl::Window>& pCandidate : m_aCandidates)
63 {
64 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
65 continue;
66 pCandidate->RemoveEventListener(LINK(this, CandidateMgr, WindowEventListener));
67 }
68}
69
70void PaintTransparentChildren(vcl::Window const & rWindow, tools::Rectangle const& rPixelRect)
71{
72 if (!rWindow.IsChildTransparentModeEnabled())
73 return;
74
75 CandidateMgr aManager;
76 aManager.PaintTransparentChildren(rWindow, rPixelRect);
77}
78
79void CandidateMgr::PaintTransparentChildren(vcl::Window const & rWindow, tools::Rectangle const& rPixelRect)
80{
81 vcl::Window * pCandidate = rWindow.GetWindow( GetWindowType::FirstChild );
82 while (pCandidate)
83 {
84 if (pCandidate->IsPaintTransparent())
85 {
86 const tools::Rectangle aCandidatePosSizePixel(
87 pCandidate->GetPosPixel(),
88 pCandidate->GetSizePixel());
89
90 if (aCandidatePosSizePixel.Overlaps(rPixelRect))
91 {
92 m_aCandidates.emplace_back(pCandidate);
93 pCandidate->AddEventListener(LINK(this, CandidateMgr, WindowEventListener));
94 }
95 }
96 pCandidate = pCandidate->GetWindow( GetWindowType::Next );
97 }
98
99 for (const auto& rpCandidate : m_aCandidates)
100 {
101 pCandidate = rpCandidate.get();
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(InvalidateFlags::NoTransparent|InvalidateFlags::Children);
108 // important: actually paint the child here!
109 if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
110 continue;
111 pCandidate->PaintImmediately();
112 }
113}
114
116: mpOutputDevice(&rOriginal),
117 mpPreRenderDevice(VclPtr<VirtualDevice>::Create())
118{
119}
120
122{
124}
125
127{
128 // compare size of mpPreRenderDevice with size of visible area
129 if(mpPreRenderDevice->GetOutputSizePixel() != mpOutputDevice->GetOutputSizePixel())
130 {
131 mpPreRenderDevice->SetOutputSizePixel(mpOutputDevice->GetOutputSizePixel());
132 }
133
134 // Also compare the MapModes for zoom/scroll changes
135 if(mpPreRenderDevice->GetMapMode() != mpOutputDevice->GetMapMode())
136 {
137 mpPreRenderDevice->SetMapMode(mpOutputDevice->GetMapMode());
138 }
139
140 // #i29186#
141 mpPreRenderDevice->SetDrawMode(mpOutputDevice->GetDrawMode());
142 mpPreRenderDevice->SetSettings(mpOutputDevice->GetSettings());
143}
144
146{
147 // region to pixels
148 const vcl::Region aRegionPixel(mpOutputDevice->LogicToPixel(rExpandedRegion));
149 //RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
150 //Rectangle aRegionRectanglePixel;
151
152 // MapModes off
153 bool bMapModeWasEnabledDest(mpOutputDevice->IsMapModeEnabled());
154 bool bMapModeWasEnabledSource(mpPreRenderDevice->IsMapModeEnabled());
155 mpOutputDevice->EnableMapMode(false);
156 mpPreRenderDevice->EnableMapMode(false);
157
158 RectangleVector aRectangles;
159 aRegionPixel.GetRegionRectangles(aRectangles);
160
161 for(const auto& rRect : aRectangles)
162 {
163 // for each rectangle, copy the area
164 const Point aTopLeft(rRect.TopLeft());
165 const Size aSize(rRect.GetSize());
166
167 mpOutputDevice->DrawOutDev(
168 aTopLeft, aSize,
169 aTopLeft, aSize,
171 }
172
173 mpOutputDevice->EnableMapMode(bMapModeWasEnabledDest);
174 mpPreRenderDevice->EnableMapMode(bMapModeWasEnabledSource);
175}
176
178{
181
182 if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
183 {
185 aColB.Invert();
186 }
187
188 xOverlayManager->setStripeColorA(aColA);
189 xOverlayManager->setStripeColorB(aColB);
190 xOverlayManager->setStripeLengthPixel(SvtOptionsDrawinglayer::GetStripeLength());
191}
192
194{
196 // is it a window?
197 if (OUTDEV_WINDOW == rOutputDevice.GetOutDevType())
198 {
199 vcl::Window* pWindow = rOutputDevice.GetOwnerWindow();
200 // decide which OverlayManager to use
202 {
203 // buffered OverlayManager, buffers its background and refreshes from there
204 // for pure overlay changes (no system redraw). The 3rd parameter specifies
205 // whether that refresh itself will use a 2nd vdev to avoid flickering.
206 // Also hand over the old OverlayManager if existent; this means to take over
207 // the registered OverlayObjects from it
208 xOverlayManager = sdr::overlay::OverlayManagerBuffered::create(rOutputDevice);
209 }
210 else
211 {
212 // unbuffered OverlayManager, just invalidates places where changes
213 // take place
214 // Also hand over the old OverlayManager if existent; this means to take over
215 // the registered OverlayObjects from it
216 xOverlayManager = sdr::overlay::OverlayManager::create(rOutputDevice);
217 }
218
219 OSL_ENSURE(xOverlayManager.is(), "SdrPaintWindow::SdrPaintWindow: Could not allocate an overlayManager (!)");
220
221 // Request a repaint so that the buffered overlay manager fills
222 // its buffer properly. This is a workaround for missing buffer
223 // updates.
225 {
226 pWindow->Invalidate();
227 }
228
229 InitOverlayManager(xOverlayManager);
230 }
231 return xOverlayManager;
232}
233
235{
236 // not yet one created?
237 if(!mxOverlayManager.is())
239}
240
242: mpOutputDevice(&rOut),
243 mpWindow(pWindow),
244 mrPaintView(rNewPaintView),
245 mbTemporaryTarget(false), // #i72889#
246 mbOutputToWindow(OUTDEV_WINDOW == mpOutputDevice->GetOutDevType()),
247 mpPatched(nullptr)
248{
249}
250
252{
253 mxOverlayManager.clear();
254
255 mpPreRenderDevice.reset();
256}
257
259{
260 if(!mxOverlayManager.is())
261 {
262 // Create buffered overlay manager by default.
263 const_cast< SdrPaintWindow* >(this)->impCreateOverlayManager();
264 }
265
266 return mxOverlayManager;
267}
268
270{
271 Size aVisSizePixel(GetOutputDevice().GetOutputSizePixel());
272 return GetOutputDevice().PixelToLogic(tools::Rectangle(Point(0,0), aVisSizePixel));
273}
274
276{
277 GDIMetaFile* pMetaFile = mpOutputDevice->GetConnectMetaFile();
278 return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
279}
280
282{
283 const bool bPrepareBufferedOutput(
285 && !OutputToPrinter()
286 && !mpOutputDevice->IsVirtual()
288
289 if(bPrepareBufferedOutput)
290 {
292 {
294 }
295 mpPreRenderDevice->PreparePreRenderDevice();
296 }
297 else
298 {
299 mpPreRenderDevice.reset();
300 }
301}
302
304{
306 {
307 mpPreRenderDevice->OutputPreRenderDevice(rExpandedRegion);
308 }
309}
310
311// #i73602# add flag if buffer shall be used
313{
314 // ## force creation of OverlayManager since the first repaint needs to
315 // save the background to get a controlled start into overlay mechanism
317
318 if(mxOverlayManager.is() && !OutputToPrinter())
319 {
321 {
322 mxOverlayManager->completeRedraw(rRegion, &mpPreRenderDevice->GetPreRenderDevice());
323 }
324 else
325 {
326 mxOverlayManager->completeRedraw(rRegion);
327 }
328 }
329}
330
331
333{
334 maRedrawRegion = rNew;
335}
336
337/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
void Invert()
bool IsPause() const
bool IsRecord() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
OutDevType GetOutDevType() const
virtual vcl::Window * GetOwnerWindow() const
bool IsBufferedOverlayAllowed() const
Definition: svdpntv.cxx:1172
bool IsBufferedOutputAllowed() const
Definition: svdpntv.cxx:1159
virtual rtl::Reference< sdr::overlay::OverlayManager > CreateOverlayManager(OutputDevice &rDevice) const
static void InitOverlayManager(rtl::Reference< sdr::overlay::OverlayManager > xOverlayManager)
VclPtr< OutputDevice > mpOutputDevice
rtl::Reference< sdr::overlay::OverlayManager > mxOverlayManager
void DrawOverlay(const vcl::Region &rRegion)
rtl::Reference< sdr::overlay::OverlayManager > const & GetOverlayManager() const
OutputDevice & GetOutputDevice() const
void SetRedrawRegion(const vcl::Region &rNew)
void OutputPreRenderDevice(const vcl::Region &rExpandedRegion)
std::unique_ptr< SdrPreRenderDevice > mpPreRenderDevice
void PreparePreRenderDevice()
tools::Rectangle GetVisibleArea() const
bool OutputToRecordingMetaFile() const
vcl::Region maRedrawRegion
SdrPaintWindow(SdrPaintView &rNewPaintView, OutputDevice &rOut, vcl::Window *pWindow=nullptr)
bool OutputToPrinter() const
void impCreateOverlayManager()
SdrPaintView & mrPaintView
VclPtr< OutputDevice > mpOutputDevice
void OutputPreRenderDevice(const vcl::Region &rExpandedRegion)
SdrPreRenderDevice(OutputDevice &rOriginal)
VclPtr< VirtualDevice > mpPreRenderDevice
const Color & GetHighlightColor() const
void disposeAndClear()
static rtl::Reference< OverlayManager > create(OutputDevice &rOutputDevice)
static rtl::Reference< OverlayManager > create(OutputDevice &rOutputDevice)
void GetRegionRectangles(RectangleVector &rTarget) const
void PaintImmediately()
bool IsPaintTransparent() const
bool SupportsDoubleBuffering() const
vcl::Window * GetWindow(GetWindowType nType) const
bool IsChildTransparentModeEnabled() const
virtual Point GetPosPixel() const
void AddEventListener(const Link< VclWindowEvent &, void > &rEventListener)
virtual Size GetSizePixel() const
void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
sal_uInt16 GetStripeLength()
void Create(SvxOrientationItem &rItem, SvStream &rStrm, sal_uInt16)
Definition: legacyitem.cxx:34
OUTDEV_WINDOW
std::vector< tools::Rectangle > RectangleVector
void PaintTransparentChildren(vcl::Window const &rWindow, tools::Rectangle const &rPixelRect)
paint the transparent children of rWin that overlap rPixelRect (for example, transparent form control...
IMPL_LINK(CandidateMgr, WindowEventListener, VclWindowEvent &, rEvent, void)
VclPtr< vcl::Window > mpWindow