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

Generated by: LCOV version 1.10