1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
34 std::vector
<Window
*> m_aCandidates
;
35 std::set
<Window
*> m_aDeletedCandidates
;
36 DECL_LINK(WindowEventListener
, VclSimpleEvent
*);
38 void PaintTransparentChildren(Window
& rWindow
, Rectangle
const& rPixelRect
);
42 IMPL_LINK(CandidateMgr
, WindowEventListener
, VclSimpleEvent
*, pEvent
)
44 VclWindowEvent
* pWinEvent
= dynamic_cast< VclWindowEvent
* >( pEvent
);
47 Window
* pWindow
= pWinEvent
->GetWindow();
48 if (pWinEvent
->GetId() == VCLEVENT_OBJECT_DYING
)
50 m_aDeletedCandidates
.insert(pWindow
);
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())
65 pCandidate
->RemoveEventListener(LINK(this, CandidateMgr
, WindowEventListener
));
69 void PaintTransparentChildren(Window
& rWindow
, Rectangle
const& rPixelRect
)
71 if (!rWindow
.IsChildTransparentModeEnabled())
74 CandidateMgr aManager
;
75 aManager
.PaintTransparentChildren(rWindow
, rPixelRect
);
78 void CandidateMgr::PaintTransparentChildren(Window
& rWindow
, Rectangle
const& rPixelRect
)
80 Window
* pCandidate
= rWindow
.GetWindow( WINDOW_FIRSTCHILD
);
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
)
102 if (m_aDeletedCandidates
.find(pCandidate
) != m_aDeletedCandidates
.end())
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())
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());
139 maPreRenderDevice
.SetDrawMode(mrOutputDevice
.GetDrawMode());
140 maPreRenderDevice
.SetSettings(mrOutputDevice
.GetSettings());
143 void SdrPreRenderDevice::OutputPreRenderDevice(const Region
& rExpandedRegion
)
146 Region
aRegionPixel(mrOutputDevice
.LogicToPixel(rExpandedRegion
));
147 RegionHandle
aRegionHandle(aRegionPixel
.BeginEnumRects());
148 Rectangle aRegionRectanglePixel
;
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(
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
);
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())
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);
208 // unbuffered OverlayManager, just invalidates places where changes
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
220 Window
* pWindow
= dynamic_cast<Window
*>(&GetOutputDevice());
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();
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#
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
);
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());
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: */