LCOV - code coverage report
Current view: top level - sd/source/ui/slidesorter/view - SlsLayeredDevice.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 105 186 56.5 %
Date: 2014-11-03 Functions: 33 44 75.0 %
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 "SlsLayeredDevice.hxx"
      21             : 
      22             : #include <vcl/window.hxx>
      23             : #include <vcl/virdev.hxx>
      24             : 
      25             : #include <boost/bind.hpp>
      26             : #include <boost/function.hpp>
      27             : 
      28             : #include <tools/gen.hxx>
      29             : 
      30             : namespace sd { namespace slidesorter { namespace view {
      31             : 
      32             : namespace {
      33             : static const sal_Int32 gnMaximumLayerCount = 8;
      34             : 
      35             : class LayerInvalidator : public ILayerInvalidator
      36             : {
      37             : public:
      38         252 :     LayerInvalidator (
      39             :         const ::boost::shared_ptr<LayeredDevice>& rpLayeredDevice,
      40             :         const SharedSdWindow& rpTargetWindow,
      41             :         const int nLayer)
      42             :         : mpLayeredDevice(rpLayeredDevice),
      43             :           mpTargetWindow(rpTargetWindow),
      44         252 :           mnLayer(nLayer)
      45             :     {
      46         252 :     }
      47             : 
      48         504 :     virtual ~LayerInvalidator ( )
      49         252 :     {
      50         504 :     }
      51             : 
      52           0 :     virtual void Invalidate (const Rectangle& rInvalidationBox) SAL_OVERRIDE
      53             :     {
      54           0 :         mpLayeredDevice->Invalidate(rInvalidationBox, mnLayer);
      55           0 :         mpTargetWindow->Invalidate(rInvalidationBox);
      56           0 :     }
      57             : 
      58             : private:
      59             :     const ::boost::shared_ptr<LayeredDevice> mpLayeredDevice;
      60             :     SharedSdWindow mpTargetWindow;
      61             :     const int mnLayer;
      62             : };
      63             : 
      64         431 : void DeviceCopy (
      65             :     OutputDevice& rTargetDevice,
      66             :     OutputDevice& rSourceDevice,
      67             :     const Rectangle& rBox)
      68             : {
      69             :     rTargetDevice.DrawOutDev(
      70             :         rBox.TopLeft(),
      71             :         rBox.GetSize(),
      72             :         rBox.TopLeft(),
      73             :         rBox.GetSize(),
      74         431 :         rSourceDevice);
      75         431 : }
      76             : 
      77         431 : void ForAllRectangles (const vcl::Region& rRegion, ::boost::function<void(const Rectangle&)> aFunction)
      78             : {
      79             :     OSL_ASSERT(aFunction);
      80         431 :     RectangleVector aRectangles;
      81         431 :     rRegion.GetRegionRectangles(aRectangles);
      82             : 
      83         431 :     if(0 == aRectangles.size())
      84             :     {
      85           0 :         aFunction(Rectangle());
      86             :     }
      87             :     else
      88             :     {
      89         862 :         for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
      90             :         {
      91         431 :             aFunction(*aRectIter);
      92             :         }
      93             : 
      94             :         //Region aMutableRegionCopy (rRegion);
      95             :         //RegionHandle aHandle(aMutableRegionCopy.BeginEnumRects());
      96             :         //Rectangle aBox;
      97             :         //while (aMutableRegionCopy.GetEnumRects(aHandle, aBox))
      98             :         //    aFunction(aBox);
      99             :         //aMutableRegionCopy.EndEnumRects(aHandle);
     100         431 :     }
     101         431 : }
     102             : 
     103             : class Layer : private ::boost::noncopyable
     104             : {
     105             : public:
     106             :     Layer (void);
     107             :     ~Layer (void);
     108             : 
     109             :     void Initialize (const SharedSdWindow& rpTargetWindow);
     110             :     void InvalidateRectangle (const Rectangle& rInvalidationBox);
     111             :     void InvalidateRegion (const vcl::Region& rInvalidationRegion);
     112             :     void Validate (const MapMode& rMapMode);
     113             :     void Repaint (
     114             :         OutputDevice& rTargetDevice,
     115             :         const Rectangle& rRepaintRectangle);
     116             :     void Resize (const Size& rSize);
     117             :     void AddPainter (const SharedILayerPainter& rpPainter);
     118             :     void RemovePainter (const SharedILayerPainter& rpPainter);
     119             :     bool HasPainter (void) const;
     120             :     void Dispose (void);
     121             : 
     122             : private:
     123             :     ::boost::shared_ptr<VirtualDevice> mpLayerDevice;
     124             :     ::std::vector<SharedILayerPainter> maPainters;
     125             :     vcl::Region maInvalidationRegion;
     126             : 
     127             :     void ValidateRectangle (const Rectangle& rBox);
     128             : };
     129             : typedef ::boost::shared_ptr<Layer> SharedLayer;
     130             : 
     131             : } // end of anonymous namespace
     132             : 
     133         126 : class LayeredDevice::LayerContainer
     134             : {
     135             : public:
     136         126 :     LayerContainer() : mvLayers() {}
     137             : 
     138         431 :     bool empty() const { return mvLayers.empty(); }
     139             : 
     140        5237 :     size_t size() const { return mvLayers.size(); }
     141             : 
     142           0 :     const SharedLayer& back() const { return mvLayers.back(); }
     143             : 
     144        1234 :     const ::std::vector<SharedLayer>::const_iterator begin() const { return mvLayers.begin(); }
     145        1234 :     const ::std::vector<SharedLayer>::const_iterator end() const { return mvLayers.end(); }
     146             : 
     147         126 :     void clear() { mvLayers.clear(); }
     148             : 
     149           0 :     void pop_back() { mvLayers.pop_back(); }
     150             : 
     151         126 :     void resize(size_t n) { mvLayers.resize(n); }
     152             : 
     153        3204 :     SharedLayer& operator[](size_t i) { return mvLayers[i]; }
     154             : 
     155             : private:
     156             :     ::std::vector<SharedLayer> mvLayers;
     157             : };
     158             : 
     159             : //===== LayeredDevice =========================================================
     160             : 
     161         126 : LayeredDevice::LayeredDevice (const SharedSdWindow& rpTargetWindow)
     162             :     : mpTargetWindow(rpTargetWindow),
     163             :       mpLayers(new LayerContainer()),
     164         252 :       mpBackBuffer(new VirtualDevice(*mpTargetWindow)),
     165         378 :       maSavedMapMode(rpTargetWindow->GetMapMode())
     166             : {
     167         126 :     mpBackBuffer->SetOutputSizePixel(mpTargetWindow->GetSizePixel());
     168         126 : }
     169             : 
     170         126 : LayeredDevice::~LayeredDevice (void)
     171             : {
     172         126 : }
     173             : 
     174           0 : void LayeredDevice::Invalidate (
     175             :     const Rectangle& rInvalidationArea,
     176             :     const sal_Int32 nLayer)
     177             : {
     178           0 :     if (nLayer<0 || size_t(nLayer)>=mpLayers->size())
     179             :     {
     180             :         OSL_ASSERT(nLayer>=0 && size_t(nLayer)<mpLayers->size());
     181           0 :         return;
     182             :     }
     183             : 
     184           0 :     (*mpLayers)[nLayer]->InvalidateRectangle(rInvalidationArea);
     185             : }
     186             : 
     187        1350 : void LayeredDevice::InvalidateAllLayers (const Rectangle& rInvalidationArea)
     188             : {
     189        4050 :     for (sal_uInt32 nLayer=0; nLayer<mpLayers->size(); ++nLayer)
     190        2700 :         (*mpLayers)[nLayer]->InvalidateRectangle(rInvalidationArea);
     191        1350 : }
     192             : 
     193           0 : void LayeredDevice::InvalidateAllLayers (const vcl::Region& rInvalidationRegion)
     194             : {
     195           0 :     for (sal_uInt32 nLayer=0; nLayer<mpLayers->size(); ++nLayer)
     196           0 :         (*mpLayers)[nLayer]->InvalidateRegion(rInvalidationRegion);
     197           0 : }
     198             : 
     199         252 : void LayeredDevice::RegisterPainter (
     200             :     const SharedILayerPainter& rpPainter,
     201             :     const sal_Int32 nLayer)
     202             : {
     203             :     OSL_ASSERT(mpLayers);
     204         252 :     if ( ! rpPainter)
     205             :     {
     206             :         OSL_ASSERT(rpPainter);
     207           0 :         return;
     208             :     }
     209         252 :     if (nLayer<0 || nLayer>=gnMaximumLayerCount)
     210             :     {
     211             :         OSL_ASSERT(nLayer>=0 && nLayer<gnMaximumLayerCount);
     212           0 :         return;
     213             :     }
     214             : 
     215             :     // Provide the layers.
     216         252 :     if (sal_uInt32(nLayer) >= mpLayers->size())
     217             :     {
     218         126 :         const sal_Int32 nOldLayerCount (mpLayers->size());
     219         126 :         mpLayers->resize(nLayer+1);
     220             : 
     221         378 :         for (size_t nIndex=nOldLayerCount; nIndex<mpLayers->size(); ++nIndex)
     222         252 :             (*mpLayers)[nIndex].reset(new Layer());
     223             :     }
     224             : 
     225         252 :     (*mpLayers)[nLayer]->AddPainter(rpPainter);
     226         252 :     if (nLayer == 0)
     227           0 :         (*mpLayers)[nLayer]->Initialize(mpTargetWindow);
     228             : 
     229         252 :     rpPainter->SetLayerInvalidator(
     230         252 :         SharedILayerInvalidator(new LayerInvalidator(shared_from_this(),mpTargetWindow,nLayer)));
     231             : }
     232             : 
     233           0 : void LayeredDevice::RemovePainter (
     234             :     const SharedILayerPainter& rpPainter,
     235             :     const sal_Int32 nLayer)
     236             : {
     237           0 :     if ( ! rpPainter)
     238             :     {
     239             :         OSL_ASSERT(rpPainter);
     240           0 :         return;
     241             :     }
     242           0 :     if (nLayer<0 || size_t(nLayer)>=mpLayers->size())
     243             :     {
     244             :         OSL_ASSERT(nLayer>=0 && size_t(nLayer)<mpLayers->size());
     245           0 :         return;
     246             :     }
     247             : 
     248           0 :     rpPainter->SetLayerInvalidator(SharedILayerInvalidator());
     249             : 
     250           0 :     (*mpLayers)[nLayer]->RemovePainter(rpPainter);
     251             : 
     252             :     // Remove top most layers that do not contain any painters.
     253           0 :     while ( ! mpLayers->empty() && ! mpLayers->back()->HasPainter())
     254           0 :         mpLayers->pop_back();
     255             : }
     256             : 
     257         431 : void LayeredDevice::Repaint (const vcl::Region& rRepaintRegion)
     258             : {
     259             :     // Validate the contents of all layers (that have their own devices.)
     260             :     ::std::for_each(
     261             :         mpLayers->begin(),
     262             :         mpLayers->end(),
     263         431 :         ::boost::bind(&Layer::Validate, _1, mpTargetWindow->GetMapMode()));
     264             : 
     265         431 :     ForAllRectangles(rRepaintRegion, ::boost::bind(&LayeredDevice::RepaintRectangle, this, _1));
     266         431 : }
     267             : 
     268         431 : void LayeredDevice::RepaintRectangle (const Rectangle& rRepaintRectangle)
     269             : {
     270         431 :     if (mpLayers->empty())
     271         431 :         return;
     272         431 :     else if (mpLayers->size() == 1)
     273             :     {
     274             :         // Just copy the main layer into the target device.
     275           0 :         (*mpLayers)[0]->Repaint(*mpTargetWindow, rRepaintRectangle);
     276             :     }
     277             :     else
     278             :     {
     279             :         // Paint all layers first into the back buffer (to avoid flickering
     280             :         // due to synchronous paints) and then copy that into the target
     281             :         // device.
     282         431 :         mpBackBuffer->SetMapMode(mpTargetWindow->GetMapMode());
     283             :         ::std::for_each(
     284             :             mpLayers->begin(),
     285             :             mpLayers->end(),
     286         431 :             ::boost::bind(&Layer::Repaint, _1, ::boost::ref(*mpBackBuffer), rRepaintRectangle));
     287             : 
     288         431 :         DeviceCopy(*mpTargetWindow, *mpBackBuffer, rRepaintRectangle);
     289             :     }
     290             : }
     291             : 
     292         246 : void LayeredDevice::Resize (void)
     293             : {
     294         246 :     const Size aSize (mpTargetWindow->GetSizePixel());
     295         246 :     mpBackBuffer->SetOutputSizePixel(aSize);
     296         246 :     ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Resize, _1, aSize));
     297         246 : }
     298             : 
     299         126 : void LayeredDevice::Dispose (void)
     300             : {
     301         126 :     ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Dispose, _1));
     302         126 :     mpLayers->clear();
     303         126 : }
     304             : 
     305         431 : bool LayeredDevice::HandleMapModeChange (void)
     306             : {
     307         431 :     const MapMode& rMapMode (mpTargetWindow->GetMapMode());
     308         431 :     if (maSavedMapMode == rMapMode)
     309         322 :         return false;
     310             : 
     311             :     const Rectangle aLogicWindowBox (
     312         109 :         mpTargetWindow->PixelToLogic(Rectangle(Point(0,0), mpTargetWindow->GetSizePixel())));
     313         218 :     if (maSavedMapMode.GetScaleX() != rMapMode.GetScaleX()
     314         109 :         || maSavedMapMode.GetScaleY() != rMapMode.GetScaleY()
     315         218 :         || maSavedMapMode.GetMapUnit() != rMapMode.GetMapUnit())
     316             :     {
     317             :         // When the scale has changed then we have to paint everything.
     318         109 :         InvalidateAllLayers(aLogicWindowBox);
     319             :     }
     320           0 :     else if (maSavedMapMode.GetOrigin() != rMapMode.GetOrigin())
     321             :     {
     322             :         // Window has been scrolled.  Adapt contents of backbuffers and
     323             :         // layer devices.
     324           0 :         const Point aDelta (rMapMode.GetOrigin() - maSavedMapMode.GetOrigin());
     325           0 :         mpBackBuffer->CopyArea(
     326             :             aLogicWindowBox.TopLeft(),
     327           0 :             mpTargetWindow->PixelToLogic(Point(0,0), maSavedMapMode),
     328           0 :             aLogicWindowBox.GetSize());
     329             : 
     330             :         // Invalidate the area(s) that have been exposed.
     331           0 :         const Rectangle aWindowBox (Point(0,0), mpTargetWindow->GetSizePixel());
     332           0 :         if (aDelta.Y() < 0)
     333           0 :             InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
     334             :                 aWindowBox.Left(),
     335           0 :                 aWindowBox.Bottom()+aDelta.Y(),
     336             :                 aWindowBox.Right(),
     337           0 :                 aWindowBox.Bottom())));
     338           0 :         else if (aDelta.Y() > 0)
     339           0 :             InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
     340             :                 aWindowBox.Left(),
     341             :                 aWindowBox.Top(),
     342             :                 aWindowBox.Right(),
     343           0 :                 aWindowBox.Top()+aDelta.Y())));
     344           0 :         if (aDelta.X() < 0)
     345           0 :             InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
     346           0 :                 aWindowBox.Right()+aDelta.X(),
     347             :                 aWindowBox.Top(),
     348             :                 aWindowBox.Right(),
     349           0 :                 aWindowBox.Bottom())));
     350           0 :         else if (aDelta.X() > 0)
     351           0 :             InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
     352             :                 aWindowBox.Left(),
     353             :                 aWindowBox.Top(),
     354           0 :                 aWindowBox.Left()+aDelta.X(),
     355           0 :                 aWindowBox.Bottom())));
     356             :     }
     357             :     else
     358             :     {
     359             :         // Can this happen?  Lets trigger a warning when it does.
     360             :         OSL_ASSERT(false);
     361             :     }
     362             : 
     363         109 :     maSavedMapMode = rMapMode;
     364             : 
     365         109 :     return true;
     366             : }
     367             : 
     368             : //===== Layer =================================================================
     369             : 
     370         252 : Layer::Layer (void)
     371             :     : mpLayerDevice(),
     372             :       maPainters(),
     373         252 :       maInvalidationRegion()
     374             : {
     375         252 : }
     376             : 
     377         252 : Layer::~Layer (void)
     378             : {
     379         252 : }
     380             : 
     381           0 : void Layer::Initialize (const SharedSdWindow& rpTargetWindow)
     382             : {
     383             : #if 0
     384             :     (void)rpTargetWindow;
     385             : #else
     386           0 :     if ( ! mpLayerDevice)
     387             :     {
     388           0 :         mpLayerDevice.reset(new VirtualDevice(*rpTargetWindow));
     389           0 :         mpLayerDevice->SetOutputSizePixel(rpTargetWindow->GetSizePixel());
     390             :     }
     391             : #endif
     392           0 : }
     393             : 
     394        2700 : void Layer::InvalidateRectangle (const Rectangle& rInvalidationBox)
     395             : {
     396        2700 :     maInvalidationRegion.Union(rInvalidationBox);
     397        2700 : }
     398             : 
     399           0 : void Layer::InvalidateRegion (const vcl::Region& rInvalidationRegion)
     400             : {
     401           0 :     maInvalidationRegion.Union(rInvalidationRegion);
     402           0 : }
     403             : 
     404         862 : void Layer::Validate (const MapMode& rMapMode)
     405             : {
     406         862 :     if (mpLayerDevice && ! maInvalidationRegion.IsEmpty())
     407             :     {
     408           0 :         vcl::Region aRegion (maInvalidationRegion);
     409           0 :         maInvalidationRegion.SetEmpty();
     410             : 
     411           0 :         mpLayerDevice->SetMapMode(rMapMode);
     412             :         ForAllRectangles(
     413             :             aRegion,
     414           0 :             ::boost::bind(&Layer::ValidateRectangle, this, _1));
     415             :     }
     416         862 : }
     417             : 
     418           0 : void Layer::ValidateRectangle (const Rectangle& rBox)
     419             : {
     420           0 :     if ( ! mpLayerDevice)
     421           0 :         return;
     422           0 :     const vcl::Region aSavedClipRegion (mpLayerDevice->GetClipRegion());
     423           0 :     mpLayerDevice->IntersectClipRegion(rBox);
     424             : 
     425           0 :     for (::std::vector<SharedILayerPainter>::const_iterator
     426           0 :              iPainter(maPainters.begin()),
     427           0 :              iEnd(maPainters.end());
     428             :          iPainter!=iEnd;
     429             :          ++iPainter)
     430             :     {
     431           0 :         (*iPainter)->Paint(*mpLayerDevice, rBox);
     432             :     }
     433             : 
     434           0 :     mpLayerDevice->SetClipRegion(aSavedClipRegion);
     435             : }
     436             : 
     437         862 : void Layer::Repaint (
     438             :     OutputDevice& rTargetDevice,
     439             :     const Rectangle& rRepaintRectangle)
     440             : {
     441         862 :     if (mpLayerDevice)
     442             :     {
     443           0 :         DeviceCopy(rTargetDevice, *mpLayerDevice, rRepaintRectangle);
     444             :     }
     445             :     else
     446             :     {
     447             :         ::std::for_each(
     448             :             maPainters.begin(),
     449             :             maPainters.end(),
     450             :             ::boost::bind(&ILayerPainter::Paint,
     451             :                 _1,
     452             :                 ::boost::ref(rTargetDevice),
     453         862 :                 rRepaintRectangle));
     454             :     }
     455         862 : }
     456             : 
     457         492 : void Layer::Resize (const Size& rSize)
     458             : {
     459         492 :     if (mpLayerDevice)
     460             :     {
     461           0 :         mpLayerDevice->SetOutputSizePixel(rSize);
     462           0 :         maInvalidationRegion = Rectangle(Point(0,0), rSize);
     463             :     }
     464         492 : }
     465             : 
     466         252 : void Layer::AddPainter (const SharedILayerPainter& rpPainter)
     467             : {
     468             :     OSL_ASSERT(::std::find(maPainters.begin(), maPainters.end(), rpPainter) == maPainters.end());
     469             : 
     470         252 :     maPainters.push_back(rpPainter);
     471         252 : }
     472             : 
     473           0 : void Layer::RemovePainter (const SharedILayerPainter& rpPainter)
     474             : {
     475             :     const ::std::vector<SharedILayerPainter>::iterator iPainter (
     476           0 :         ::std::find(maPainters.begin(), maPainters.end(), rpPainter));
     477           0 :     if (iPainter != maPainters.end())
     478             :     {
     479           0 :         maPainters.erase(iPainter);
     480             :     }
     481             :     else
     482             :     {
     483             :         DBG_ASSERT(false,"LayeredDevice::RemovePainter called for painter that is not registered");
     484             :     }
     485           0 : }
     486             : 
     487           0 : bool Layer::HasPainter (void) const
     488             : {
     489           0 :     return !maPainters.empty();
     490             : }
     491             : 
     492         252 : void Layer::Dispose (void)
     493             : {
     494         252 :     maPainters.clear();
     495         252 : }
     496             : 
     497         114 : } } } // end of namespace ::sd::slidesorter::view
     498             : 
     499             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10