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

Generated by: LCOV version 1.10