LCOV - code coverage report
Current view: top level - svx/source/svdraw - sdrpaintwindow.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 123 135 91.1 %
Date: 2015-06-13 12:38:46 Functions: 19 21 90.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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/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>
      29             : 
      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        5044 : class CandidateMgr
      35             : {
      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();
      42             : };
      43             : 
      44           0 : IMPL_LINK(CandidateMgr, WindowEventListener, VclSimpleEvent*, pEvent)
      45             : {
      46           0 :     VclWindowEvent* pWinEvent = dynamic_cast< VclWindowEvent* >( pEvent );
      47           0 :     if (pWinEvent)
      48             :     {
      49           0 :         vcl::Window* pWindow = pWinEvent->GetWindow();
      50           0 :         if (pWinEvent->GetId() == VCLEVENT_OBJECT_DYING)
      51             :         {
      52           0 :             m_aDeletedCandidates.insert(pWindow);
      53             :         }
      54             :     }
      55             : 
      56           0 :     return 0;
      57             : }
      58             : 
      59       10088 : CandidateMgr::~CandidateMgr()
      60             : {
      61        5182 :     for (auto aI = m_aCandidates.begin(); aI != m_aCandidates.end(); ++aI)
      62             :     {
      63         138 :         VclPtr<vcl::Window> pCandidate = *aI;
      64         138 :         if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
      65           0 :             continue;
      66         138 :         pCandidate->RemoveEventListener(LINK(this, CandidateMgr, WindowEventListener));
      67         138 :     }
      68        5044 : }
      69             : 
      70        5044 : void PaintTransparentChildren(vcl::Window & rWindow, Rectangle const& rPixelRect)
      71             : {
      72        5044 :     if (!rWindow.IsChildTransparentModeEnabled())
      73        5044 :         return;
      74             : 
      75        5044 :     CandidateMgr aManager;
      76        5044 :     aManager.PaintTransparentChildren(rWindow, rPixelRect);
      77             : }
      78             : 
      79        5044 : void CandidateMgr::PaintTransparentChildren(vcl::Window & rWindow, Rectangle const& rPixelRect)
      80             : {
      81        5044 :     vcl::Window * pCandidate = rWindow.GetWindow( GetWindowType::FirstChild );
      82       12213 :     while (pCandidate)
      83             :     {
      84        2125 :         if (pCandidate->IsPaintTransparent())
      85             :         {
      86             :             const Rectangle aCandidatePosSizePixel(
      87         451 :                             pCandidate->GetPosPixel(),
      88         902 :                             pCandidate->GetSizePixel());
      89             : 
      90         451 :             if (aCandidatePosSizePixel.IsOver(rPixelRect))
      91             :             {
      92         138 :                 m_aCandidates.push_back(pCandidate);
      93         138 :                 pCandidate->AddEventListener(LINK(this, CandidateMgr, WindowEventListener));
      94             :             }
      95             :         }
      96        2125 :         pCandidate = pCandidate->GetWindow( GetWindowType::Next );
      97             :     }
      98             : 
      99        5182 :     for (auto aI = m_aCandidates.begin(); aI != m_aCandidates.end(); ++aI)
     100             :     {
     101         138 :         pCandidate = *aI;
     102         138 :         if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
     103           0 :             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         138 :         pCandidate->Invalidate(InvalidateFlags::NoTransparent|InvalidateFlags::Children);
     108             :         // important: actually paint the child here!
     109         138 :         if (m_aDeletedCandidates.find(pCandidate) != m_aDeletedCandidates.end())
     110           0 :             continue;
     111         138 :         pCandidate->Update();
     112             :     }
     113        5044 : }
     114             : 
     115        1079 : SdrPreRenderDevice::SdrPreRenderDevice(OutputDevice& rOriginal)
     116             : :   mrOutputDevice(rOriginal),
     117        1079 :     mpPreRenderDevice(VclPtr<VirtualDevice>::Create())
     118             : {
     119        1079 : }
     120             : 
     121        2120 : SdrPreRenderDevice::~SdrPreRenderDevice()
     122             : {
     123        1060 :     mpPreRenderDevice.disposeAndClear();
     124        1060 : }
     125             : 
     126       13751 : void SdrPreRenderDevice::PreparePreRenderDevice()
     127             : {
     128             :     // compare size of mpPreRenderDevice with size of visible area
     129       13751 :     if(mpPreRenderDevice->GetOutputSizePixel() != mrOutputDevice.GetOutputSizePixel())
     130             :     {
     131        1225 :         mpPreRenderDevice->SetOutputSizePixel(mrOutputDevice.GetOutputSizePixel());
     132             :     }
     133             : 
     134             :     // Also compare the MapModes for zoom/scroll changes
     135       13751 :     if(mpPreRenderDevice->GetMapMode() != mrOutputDevice.GetMapMode())
     136             :     {
     137        4181 :         mpPreRenderDevice->SetMapMode(mrOutputDevice.GetMapMode());
     138             :     }
     139             : 
     140             :     // #i29186#
     141       13751 :     mpPreRenderDevice->SetDrawMode(mrOutputDevice.GetDrawMode());
     142       13751 :     mpPreRenderDevice->SetSettings(mrOutputDevice.GetSettings());
     143       13751 : }
     144             : 
     145       13751 : void SdrPreRenderDevice::OutputPreRenderDevice(const vcl::Region& rExpandedRegion)
     146             : {
     147             :     // region to pixels
     148       13751 :     const vcl::Region aRegionPixel(mrOutputDevice.LogicToPixel(rExpandedRegion));
     149             :     //RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
     150             :     //Rectangle aRegionRectanglePixel;
     151             : 
     152             :     // MapModes off
     153       13751 :     bool bMapModeWasEnabledDest(mrOutputDevice.IsMapModeEnabled());
     154       13751 :     bool bMapModeWasEnabledSource(mpPreRenderDevice->IsMapModeEnabled());
     155       13751 :     mrOutputDevice.EnableMapMode(false);
     156       13751 :     mpPreRenderDevice->EnableMapMode(false);
     157             : 
     158       27502 :     RectangleVector aRectangles;
     159       13751 :     aRegionPixel.GetRegionRectangles(aRectangles);
     160             : 
     161       27904 :     for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
     162             :     {
     163             :         // for each rectangle, copy the area
     164       14153 :         const Point aTopLeft(aRectIter->TopLeft());
     165       14153 :         const Size aSize(aRectIter->GetSize());
     166             : 
     167             :         mrOutputDevice.DrawOutDev(
     168             :             aTopLeft, aSize,
     169             :             aTopLeft, aSize,
     170       14153 :             *mpPreRenderDevice.get());
     171             : 
     172             : #ifdef DBG_UTIL
     173             :         // #i74769#
     174             :         static bool bDoPaintForVisualControlRegion(false);
     175             : 
     176             :         if(bDoPaintForVisualControlRegion)
     177             :         {
     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));
     182             : 
     183             :             mrOutputDevice.SetLineColor(aColor);
     184             :             mrOutputDevice.SetFillColor();
     185             :             mrOutputDevice.DrawRect(*aRectIter);
     186             :         }
     187             : #endif
     188             :     }
     189             : 
     190       13751 :     mrOutputDevice.EnableMapMode(bMapModeWasEnabledDest);
     191       27502 :     mpPreRenderDevice->EnableMapMode(bMapModeWasEnabledSource);
     192       13751 : }
     193             : 
     194             : 
     195             : 
     196       14758 : void SdrPaintWindow::impCreateOverlayManager()
     197             : {
     198             :     // not yet one created?
     199       14758 :     if(!mxOverlayManager.is())
     200             :     {
     201             :         // is it a window?
     202        1882 :         if(OUTDEV_WINDOW == GetOutputDevice().GetOutDevType())
     203             :         {
     204             :             // decide which OverlayManager to use
     205        1312 :             if(GetPaintView().IsBufferedOverlayAllowed() && mbUseBuffer)
     206             :             {
     207             :                 // buffered OverlayManager, buffers its background and refreshes from there
     208             :                 // for pure overlay changes (no system redraw). The 3rd parameter specifies
     209             :                 // whether that refresh itself will use a 2nd vdev to avoid flickering.
     210             :                 // Also hand over the old OverlayManager if existent; this means to take over
     211             :                 // the registered OverlayObjects from it
     212        1303 :                 mxOverlayManager = sdr::overlay::OverlayManagerBuffered::create(GetOutputDevice(), GetPaintView().GetModel(), true);
     213             :             }
     214             :             else
     215             :             {
     216             :                 // unbuffered OverlayManager, just invalidates places where changes
     217             :                 // take place
     218             :                 // Also hand over the old OverlayManager if existent; this means to take over
     219             :                 // the registered OverlayObjects from it
     220           9 :                 mxOverlayManager = sdr::overlay::OverlayManager::create(GetOutputDevice(), GetPaintView().GetModel());
     221             :             }
     222             : 
     223             :             OSL_ENSURE(mxOverlayManager.is(), "SdrPaintWindow::SdrPaintWindow: Could not allocate an overlayManager (!)");
     224             : 
     225             :             // Request a repaint so that the buffered overlay manager fills
     226             :             // its buffer properly.  This is a workaround for missing buffer
     227             :             // updates.
     228        1312 :             vcl::Window* pWindow = dynamic_cast<vcl::Window*>(&GetOutputDevice());
     229        1312 :             if (pWindow != NULL)
     230        1312 :                 pWindow->Invalidate();
     231             : 
     232        1312 :             Color aColA(GetPaintView().getOptionsDrawinglayer().GetStripeColorA());
     233        1312 :             Color aColB(GetPaintView().getOptionsDrawinglayer().GetStripeColorB());
     234             : 
     235        1312 :             if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
     236             :             {
     237           0 :                 aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor();
     238           0 :                 aColB.Invert();
     239             :             }
     240             : 
     241        1312 :             mxOverlayManager->setStripeColorA(aColA);
     242        1312 :             mxOverlayManager->setStripeColorB(aColB);
     243        1312 :             mxOverlayManager->setStripeLengthPixel(GetPaintView().getOptionsDrawinglayer().GetStripeLength());
     244             :         }
     245             :     }
     246       14758 : }
     247             : 
     248       41631 : SdrPaintWindow::SdrPaintWindow(SdrPaintView& rNewPaintView, OutputDevice& rOut)
     249             : :   mrOutputDevice(rOut),
     250             :     mrPaintView(rNewPaintView),
     251             :     mpPreRenderDevice(0L),
     252             :     mbTemporaryTarget(false), // #i72889#
     253       41631 :     mbUseBuffer(true)
     254             : {
     255       41631 : }
     256             : 
     257       83216 : SdrPaintWindow::~SdrPaintWindow()
     258             : {
     259       41608 :     mxOverlayManager.clear();
     260             : 
     261       41608 :     DestroyPreRenderDevice();
     262       41608 : }
     263             : 
     264        6330 : rtl::Reference< sdr::overlay::OverlayManager > SdrPaintWindow::GetOverlayManager() const
     265             : {
     266        6330 :     if(!mxOverlayManager.is())
     267             :     {
     268             :         // Create buffered overlay manager by default.
     269         415 :         const_cast< SdrPaintWindow* >(this)->impCreateOverlayManager();
     270             :     }
     271             : 
     272        6330 :     return mxOverlayManager;
     273             : }
     274             : 
     275         458 : Rectangle SdrPaintWindow::GetVisibleArea() const
     276             : {
     277         458 :     Size aVisSizePixel(GetOutputDevice().GetOutputSizePixel());
     278         458 :     return Rectangle(GetOutputDevice().PixelToLogic(Rectangle(Point(0,0), aVisSizePixel)));
     279             : }
     280             : 
     281       13751 : bool SdrPaintWindow::OutputToRecordingMetaFile() const
     282             : {
     283       13751 :     GDIMetaFile* pMetaFile = mrOutputDevice.GetConnectMetaFile();
     284       13751 :     return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
     285             : }
     286             : 
     287       14343 : void SdrPaintWindow::PreparePreRenderDevice()
     288             : {
     289             :     const bool bPrepareBufferedOutput(
     290       14343 :         mrPaintView.IsBufferedOutputAllowed()
     291       14309 :         && !OutputToPrinter()
     292       14309 :         && !OutputToVirtualDevice()
     293       28094 :         && !OutputToRecordingMetaFile());
     294             : 
     295       14343 :     if(bPrepareBufferedOutput)
     296             :     {
     297       13751 :         if(!mpPreRenderDevice)
     298             :         {
     299        1079 :             mpPreRenderDevice = new SdrPreRenderDevice(mrOutputDevice);
     300             :         }
     301             :     }
     302             :     else
     303             :     {
     304         592 :         DestroyPreRenderDevice();
     305             :     }
     306             : 
     307       14343 :     if(mpPreRenderDevice)
     308             :     {
     309       13751 :         mpPreRenderDevice->PreparePreRenderDevice();
     310             :     }
     311       14343 : }
     312             : 
     313       42200 : void SdrPaintWindow::DestroyPreRenderDevice()
     314             : {
     315       42200 :     if(mpPreRenderDevice)
     316             :     {
     317        1060 :         delete mpPreRenderDevice;
     318        1060 :         mpPreRenderDevice = 0L;
     319             :     }
     320       42200 : }
     321             : 
     322       14343 : void SdrPaintWindow::OutputPreRenderDevice(const vcl::Region& rExpandedRegion)
     323             : {
     324       14343 :     if(mpPreRenderDevice)
     325             :     {
     326       13751 :         mpPreRenderDevice->OutputPreRenderDevice(rExpandedRegion);
     327             :     }
     328       14343 : }
     329             : 
     330             : // #i73602# add flag if buffer shall be used
     331       14343 : void SdrPaintWindow::DrawOverlay(const vcl::Region& rRegion)
     332             : {
     333             :     // ## force creation of OverlayManager since the first repaint needs to
     334             :     // save the background to get a controlled start into overlay mechanism
     335       14343 :     impCreateOverlayManager();
     336             : 
     337       14343 :     if(mxOverlayManager.is() && !OutputToPrinter())
     338             :     {
     339       13773 :         if(mpPreRenderDevice)
     340             :         {
     341       13751 :             mxOverlayManager->completeRedraw(rRegion, &mpPreRenderDevice->GetPreRenderDevice());
     342             :         }
     343             :         else
     344             :         {
     345          22 :             mxOverlayManager->completeRedraw(rRegion);
     346             :         }
     347             :     }
     348       14343 : }
     349             : 
     350             : 
     351       77578 : void SdrPaintWindow::SetRedrawRegion(const vcl::Region& rNew)
     352             : {
     353       77578 :     maRedrawRegion = rNew;
     354       77578 : }
     355             : 
     356             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11