LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/drawinglayer/source/processor2d - vclhelperbufferdevice.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 132 141 93.6 %
Date: 2013-07-09 Functions: 15 15 100.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 <vclhelperbufferdevice.hxx>
      21             : #include <basegfx/range/b2drange.hxx>
      22             : #include <vcl/bitmapex.hxx>
      23             : #include <basegfx/matrix/b2dhommatrix.hxx>
      24             : #include <tools/stream.hxx>
      25             : #include <vcl/timer.hxx>
      26             : #include <comphelper/broadcasthelper.hxx>
      27             : #include <vcl/lazydelete.hxx>
      28             : #include <vcl/dibtools.hxx>
      29             : 
      30             : //////////////////////////////////////////////////////////////////////////////
      31             : // buffered VDev usage
      32             : 
      33             : namespace
      34             : {
      35             :     typedef ::std::vector< VirtualDevice* > aBuffers;
      36             : 
      37             :     class VDevBuffer : public Timer, protected comphelper::OBaseMutex
      38             :     {
      39             :     private:
      40             :         // available buffers
      41             :         aBuffers            maFreeBuffers;
      42             : 
      43             :         // allocated/used buffers (remembered to allow deleteing them in destructor)
      44             :         aBuffers            maUsedBuffers;
      45             : 
      46             :     public:
      47             :         VDevBuffer();
      48             :         virtual ~VDevBuffer();
      49             : 
      50             :         VirtualDevice* alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono);
      51             :         void free(VirtualDevice& rDevice);
      52             : 
      53             :         // Timer virtuals
      54             :         virtual void Timeout();
      55             :     };
      56             : 
      57           7 :     VDevBuffer::VDevBuffer()
      58             :     :   Timer(),
      59             :         maFreeBuffers(),
      60           7 :         maUsedBuffers()
      61             :     {
      62           7 :         SetTimeout(10L * 1000L); // ten seconds
      63           7 :     }
      64             : 
      65          18 :     VDevBuffer::~VDevBuffer()
      66             :     {
      67           6 :         ::osl::MutexGuard aGuard(m_aMutex);
      68           6 :         Stop();
      69             : 
      70          38 :         while(!maFreeBuffers.empty())
      71             :         {
      72          26 :             delete *(maFreeBuffers.end() - 1);
      73          26 :             maFreeBuffers.pop_back();
      74             :         }
      75             : 
      76          12 :         while(!maUsedBuffers.empty())
      77             :         {
      78           0 :             delete *(maUsedBuffers.end() - 1);
      79           0 :             maUsedBuffers.pop_back();
      80           6 :         }
      81          12 :     }
      82             : 
      83        9895 :     VirtualDevice* VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono)
      84             :     {
      85        9895 :         ::osl::MutexGuard aGuard(m_aMutex);
      86        9895 :         VirtualDevice* pRetval = 0;
      87             : 
      88        9895 :         if(!maFreeBuffers.empty())
      89             :         {
      90        9878 :             bool bOkay(false);
      91        9878 :             aBuffers::iterator aFound(maFreeBuffers.end());
      92             : 
      93       53970 :             for(aBuffers::iterator a(maFreeBuffers.begin()); a != maFreeBuffers.end(); ++a)
      94             :             {
      95             :                 OSL_ENSURE(*a, "Empty pointer in VDevBuffer (!)");
      96             : 
      97       44092 :                 if((bMono && 1 == (*a)->GetBitCount()) || (!bMono && (*a)->GetBitCount() > 1))
      98             :                 {
      99             :                     // candidate is valid due to bit depth
     100       26004 :                     if(aFound != maFreeBuffers.end())
     101             :                     {
     102             :                         // already found
     103       16144 :                         if(bOkay)
     104             :                         {
     105             :                             // found is valid
     106       13328 :                             const bool bCandidateOkay((*a)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*a)->GetOutputHeightPixel() >= rSizePixel.getHeight());
     107             : 
     108       13328 :                             if(bCandidateOkay)
     109             :                             {
     110             :                                 // found and candidate are valid
     111       11609 :                                 const sal_uLong aSquare((*aFound)->GetOutputWidthPixel() * (*aFound)->GetOutputHeightPixel());
     112       11609 :                                 const sal_uLong aCandidateSquare((*a)->GetOutputWidthPixel() * (*a)->GetOutputHeightPixel());
     113             : 
     114       11609 :                                 if(aCandidateSquare < aSquare)
     115             :                                 {
     116             :                                     // candidate is valid and smaller, use it
     117        5544 :                                     aFound = a;
     118             :                                 }
     119             :                             }
     120             :                             else
     121             :                             {
     122             :                                 // found is valid, candidate is not. Keep found
     123             :                             }
     124             :                         }
     125             :                         else
     126             :                         {
     127             :                             // found is invalid, use candidate
     128        2816 :                             aFound = a;
     129        2816 :                             bOkay = (*aFound)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*aFound)->GetOutputHeightPixel() >= rSizePixel.getHeight();
     130             :                         }
     131             :                     }
     132             :                     else
     133             :                     {
     134             :                         // none yet, use candidate
     135        9860 :                         aFound = a;
     136        9860 :                         bOkay = (*aFound)->GetOutputWidthPixel() >= rSizePixel.getWidth() && (*aFound)->GetOutputHeightPixel() >= rSizePixel.getHeight();
     137             :                     }
     138             :                 }
     139             :             }
     140             : 
     141        9878 :             if(aFound != maFreeBuffers.end())
     142             :             {
     143        9860 :                 pRetval = *aFound;
     144        9860 :                 maFreeBuffers.erase(aFound);
     145             : 
     146        9860 :                 if(bOkay)
     147             :                 {
     148        8974 :                     if(bClear)
     149             :                     {
     150        4183 :                         pRetval->Erase(Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight()));
     151             :                     }
     152             :                 }
     153             :                 else
     154             :                 {
     155         886 :                     pRetval->SetOutputSizePixel(rSizePixel, bClear);
     156             :                 }
     157             :             }
     158             :         }
     159             : 
     160             :         // no success yet, create new buffer
     161        9895 :         if(!pRetval)
     162             :         {
     163          35 :             pRetval = (bMono) ? new VirtualDevice(rOutDev, 1) : new VirtualDevice(rOutDev);
     164          35 :             pRetval->SetOutputSizePixel(rSizePixel, bClear);
     165             :         }
     166             :         else
     167             :         {
     168             :             // reused, reset some values
     169        9860 :             pRetval->SetMapMode();
     170             :         }
     171             : 
     172             :         // remember allocated buffer
     173        9895 :         maUsedBuffers.push_back(pRetval);
     174             : 
     175        9895 :         return pRetval;
     176             :     }
     177             : 
     178        9895 :     void VDevBuffer::free(VirtualDevice& rDevice)
     179             :     {
     180        9895 :         ::osl::MutexGuard aGuard(m_aMutex);
     181        9895 :         const aBuffers::iterator aUsedFound(::std::find(maUsedBuffers.begin(), maUsedBuffers.end(), &rDevice));
     182             :         OSL_ENSURE(aUsedFound != maUsedBuffers.end(), "OOps, non-registered buffer freed (!)");
     183             : 
     184        9895 :         maUsedBuffers.erase(aUsedFound);
     185        9895 :         maFreeBuffers.push_back(&rDevice);
     186        9895 :         Start();
     187        9895 :     }
     188             : 
     189           4 :     void VDevBuffer::Timeout()
     190             :     {
     191           4 :         ::osl::MutexGuard aGuard(m_aMutex);
     192             : 
     193          17 :         while(!maFreeBuffers.empty())
     194             :         {
     195           9 :             delete *(maFreeBuffers.end() - 1);
     196           9 :             maFreeBuffers.pop_back();
     197           4 :         }
     198           4 :     }
     199             : }
     200             : 
     201             : //////////////////////////////////////////////////////////////////////////////
     202             : // support for rendering Bitmap and BitmapEx contents
     203             : 
     204             : namespace drawinglayer
     205             : {
     206             :     // static global VDev buffer for the VclProcessor2D's (VclMetafileProcessor2D and VclPixelProcessor2D)
     207       19790 :     VDevBuffer& getVDevBuffer()
     208             :     {
     209             :         // secure global instance with Vcl's safe desroyer of external (seen by
     210             :         // library base) stuff, the remembered VDevs need to be deleted before
     211             :         // Vcl's deinit
     212       19790 :         static vcl::DeleteOnDeinit< VDevBuffer > aVDevBuffer(new VDevBuffer());
     213       19790 :         return *aVDevBuffer.get();
     214             :     }
     215             : 
     216        5338 :     impBufferDevice::impBufferDevice(
     217             :         OutputDevice& rOutDev,
     218             :         const basegfx::B2DRange& rRange,
     219             :         bool bAddOffsetToMapping)
     220             :     :   mrOutDev(rOutDev),
     221             :         mpContent(0),
     222             :         mpMask(0),
     223        5338 :         mpAlpha(0)
     224             :     {
     225        5338 :         basegfx::B2DRange aRangePixel(rRange);
     226        5338 :         aRangePixel.transform(mrOutDev.GetViewTransformation());
     227             :         const Rectangle aRectPixel(
     228       10676 :             (sal_Int32)floor(aRangePixel.getMinX()), (sal_Int32)floor(aRangePixel.getMinY()),
     229       16014 :             (sal_Int32)ceil(aRangePixel.getMaxX()), (sal_Int32)ceil(aRangePixel.getMaxY()));
     230        5338 :         const Point aEmptyPoint;
     231        5338 :         maDestPixel = Rectangle(aEmptyPoint, mrOutDev.GetOutputSizePixel());
     232        5338 :         maDestPixel.Intersection(aRectPixel);
     233             : 
     234        5338 :         if(isVisible())
     235             :         {
     236        5250 :             mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), false, false);
     237             : 
     238             :             // #i93485# assert when copying from window to VDev is used
     239             :             OSL_ENSURE(mrOutDev.GetOutDevType() != OUTDEV_WINDOW,
     240             :                 "impBufferDevice render helper: Copying from Window to VDev, this should be avoided (!)");
     241             : 
     242        5250 :             const bool bWasEnabledSrc(mrOutDev.IsMapModeEnabled());
     243        5250 :             mrOutDev.EnableMapMode(false);
     244        5250 :             mpContent->DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(), maDestPixel.GetSize(), mrOutDev);
     245        5250 :             mrOutDev.EnableMapMode(bWasEnabledSrc);
     246             : 
     247        5250 :             MapMode aNewMapMode(mrOutDev.GetMapMode());
     248             : 
     249        5250 :             if(bAddOffsetToMapping)
     250             :             {
     251        5250 :                 const Point aLogicTopLeft(mrOutDev.PixelToLogic(maDestPixel.TopLeft()));
     252        5250 :                 aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y()));
     253             :             }
     254             : 
     255        5250 :             mpContent->SetMapMode(aNewMapMode);
     256             : 
     257             :             // copy AA flag for new target
     258        5250 :             mpContent->SetAntialiasing(mrOutDev.GetAntialiasing());
     259             :         }
     260        5338 :     }
     261             : 
     262        5338 :     impBufferDevice::~impBufferDevice()
     263             :     {
     264        5338 :         if(mpContent)
     265             :         {
     266        5250 :             getVDevBuffer().free(*mpContent);
     267             :         }
     268             : 
     269        5338 :         if(mpMask)
     270             :         {
     271        3703 :             getVDevBuffer().free(*mpMask);
     272             :         }
     273             : 
     274        5338 :         if(mpAlpha)
     275             :         {
     276         942 :             getVDevBuffer().free(*mpAlpha);
     277             :         }
     278        5338 :     }
     279             : 
     280        5250 :     void impBufferDevice::paint(double fTrans)
     281             :     {
     282        5250 :         if(isVisible())
     283             :         {
     284        5250 :             const Point aEmptyPoint;
     285        5250 :             const Size aSizePixel(maDestPixel.GetSize());
     286        5250 :             const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled());
     287             :             static bool bDoSaveForVisualControl(false);
     288             : 
     289        5250 :             mrOutDev.EnableMapMode(false);
     290        5250 :             mpContent->EnableMapMode(false);
     291        5250 :             Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel));
     292             : 
     293        5250 :             if(bDoSaveForVisualControl)
     294             :             {
     295           0 :                 SvFileStream aNew((const String&)String( "c:\\content.bmp" ), STREAM_WRITE|STREAM_TRUNC);
     296           0 :                 WriteDIB(aContent, aNew, false, true);
     297             :             }
     298             : 
     299        5250 :             if(mpAlpha)
     300             :             {
     301         942 :                 mpAlpha->EnableMapMode(false);
     302         942 :                 const AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel));
     303             : 
     304         942 :                 if(bDoSaveForVisualControl)
     305             :                 {
     306           0 :                     SvFileStream aNew((const String&)String( "c:\\transparence.bmp" ), STREAM_WRITE|STREAM_TRUNC);
     307           0 :                     WriteDIB(aAlphaMask.GetBitmap(), aNew, false, true);
     308             :                 }
     309             : 
     310         942 :                 mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
     311             :             }
     312        4308 :             else if(mpMask)
     313             :             {
     314        3703 :                 mpMask->EnableMapMode(false);
     315        3703 :                 const Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel));
     316             : 
     317        3703 :                 if(bDoSaveForVisualControl)
     318             :                 {
     319           0 :                     SvFileStream aNew((const String&)String( "c:\\mask.bmp" ), STREAM_WRITE|STREAM_TRUNC);
     320           0 :                     WriteDIB(aMask, aNew, false, true);
     321             :                 }
     322             : 
     323        3703 :                 mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask));
     324             :             }
     325         605 :             else if(0.0 != fTrans)
     326             :             {
     327         605 :                 sal_uInt8 nMaskValue((sal_uInt8)basegfx::fround(fTrans * 255.0));
     328         605 :                 const AlphaMask aAlphaMask(aSizePixel, &nMaskValue);
     329         605 :                 mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
     330             :             }
     331             :             else
     332             :             {
     333           0 :                 mrOutDev.DrawBitmap(maDestPixel.TopLeft(), aContent);
     334             :             }
     335             : 
     336        5250 :             mrOutDev.EnableMapMode(bWasEnabledDst);
     337             :         }
     338        5250 :     }
     339             : 
     340        5250 :     VirtualDevice& impBufferDevice::getContent()
     341             :     {
     342             :         OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
     343        5250 :         return *mpContent;
     344             :     }
     345             : 
     346        3703 :     VirtualDevice& impBufferDevice::getMask()
     347             :     {
     348             :         OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
     349        3703 :         if(!mpMask)
     350             :         {
     351        3703 :             mpMask = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, true);
     352        3703 :             mpMask->SetMapMode(mpContent->GetMapMode());
     353             : 
     354             :             // do NOT copy AA flag for mask!
     355             :         }
     356             : 
     357        3703 :         return *mpMask;
     358             :     }
     359             : 
     360         942 :     VirtualDevice& impBufferDevice::getTransparence()
     361             :     {
     362             :         OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
     363         942 :         if(!mpAlpha)
     364             :         {
     365         942 :             mpAlpha = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, false);
     366         942 :             mpAlpha->SetMapMode(mpContent->GetMapMode());
     367             : 
     368             :             // copy AA flag for new target; masking needs to be smooth
     369         942 :             mpAlpha->SetAntialiasing(mpContent->GetAntialiasing());
     370             :         }
     371             : 
     372         942 :         return *mpAlpha;
     373             :     }
     374         408 : } // end of namespace drawinglayer
     375             : 
     376             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10