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

Generated by: LCOV version 1.11