LCOV - code coverage report
Current view: top level - vcl/source/outdev - polygon.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 130 221 58.8 %
Date: 2014-11-03 Functions: 9 10 90.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             : #include <sal/types.h>
      20             : 
      21             : #include <basegfx/matrix/b2dhommatrix.hxx>
      22             : #include <basegfx/polygon/b2dpolygontools.hxx>
      23             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      24             : #include <boost/scoped_array.hpp>
      25             : #include <tools/poly.hxx>
      26             : #include <vcl/outdev.hxx>
      27             : #include <vcl/virdev.hxx>
      28             : 
      29             : #include "salgdi.hxx"
      30             : 
      31             : 
      32             : #define OUTDEV_POLYPOLY_STACKBUF        32
      33             : 
      34      175458 : void OutputDevice::DrawPolyPolygon( const tools::PolyPolygon& rPolyPoly )
      35             : {
      36             : 
      37      175458 :     if( mpMetaFile )
      38           2 :         mpMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
      39             : 
      40      175458 :     sal_uInt16 nPoly = rPolyPoly.Count();
      41             : 
      42      175458 :     if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || !nPoly || ImplIsRecordLayout() )
      43           2 :         return;
      44             : 
      45             :     // we need a graphics
      46      175456 :     if ( !mpGraphics && !AcquireGraphics() )
      47           0 :             return;
      48             : 
      49      175456 :     if ( mbInitClipRegion )
      50         166 :         InitClipRegion();
      51             : 
      52      175456 :     if ( mbOutputClipped )
      53           0 :         return;
      54             : 
      55      175456 :     if ( mbInitLineColor )
      56       15730 :         InitLineColor();
      57             : 
      58      175456 :     if ( mbInitFillColor )
      59       18942 :         InitFillColor();
      60             : 
      61             :     // use b2dpolygon drawing if possible
      62      350930 :     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) &&
      63          18 :        mpGraphics->supportsOperation(OutDevSupport_B2DDraw) &&
      64      175456 :        ROP_OVERPAINT == GetRasterOp() &&
      65           0 :        (IsLineColor() || IsFillColor()))
      66             :     {
      67           0 :         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
      68           0 :         basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
      69           0 :         bool bSuccess(true);
      70             : 
      71             :         // transform the polygon and ensure closed
      72           0 :         aB2DPolyPolygon.transform(aTransform);
      73           0 :         aB2DPolyPolygon.setClosed(true);
      74             : 
      75           0 :         if(IsFillColor())
      76             :         {
      77           0 :             bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
      78             :         }
      79             : 
      80           0 :         if(bSuccess && IsLineColor())
      81             :         {
      82           0 :             const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
      83             : 
      84           0 :             if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
      85             :             {
      86           0 :                 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
      87             :             }
      88             : 
      89           0 :             for(sal_uInt32 a(0); bSuccess && a < aB2DPolyPolygon.count(); a++)
      90             :             {
      91             :                 bSuccess = mpGraphics->DrawPolyLine( aB2DPolyPolygon.getB2DPolygon(a),
      92             :                                                      0.0,
      93             :                                                      aB2DLineWidth,
      94             :                                                      basegfx::B2DLINEJOIN_NONE,
      95             :                                                      css::drawing::LineCap_BUTT,
      96           0 :                                                      this);
      97           0 :             }
      98             :         }
      99             : 
     100           0 :         if(bSuccess)
     101             :         {
     102           0 :             return;
     103           0 :         }
     104             :     }
     105             : 
     106      175456 :     if ( nPoly == 1 )
     107             :     {
     108             :         // #100127# Map to DrawPolygon
     109      173379 :         Polygon aPoly = rPolyPoly.GetObject( 0 );
     110      173379 :         if( aPoly.GetSize() >= 2 )
     111             :         {
     112      173379 :             GDIMetaFile* pOldMF = mpMetaFile;
     113      173379 :             mpMetaFile = NULL;
     114             : 
     115      173379 :             DrawPolygon( aPoly );
     116             : 
     117      173379 :             mpMetaFile = pOldMF;
     118      173379 :         }
     119             :     }
     120             :     else
     121             :     {
     122             :         // #100127# moved real tools::PolyPolygon draw to separate method,
     123             :         // have to call recursively, avoiding duplicate
     124             :         // ImplLogicToDevicePixel calls
     125        2077 :         ImplDrawPolyPolygon( nPoly, ImplLogicToDevicePixel( rPolyPoly ) );
     126             :     }
     127      175456 :     if( mpAlphaVDev )
     128        5288 :         mpAlphaVDev->DrawPolyPolygon( rPolyPoly );
     129             : }
     130             : 
     131        1800 : void OutputDevice::DrawPolygon( const basegfx::B2DPolygon& rB2DPolygon)
     132             : {
     133             :     // AW: Do NOT paint empty polygons
     134        1800 :     if(rB2DPolygon.count())
     135             :     {
     136        1800 :         basegfx::B2DPolyPolygon aPP( rB2DPolygon );
     137        1800 :         DrawPolyPolygon( aPP );
     138             :     }
     139        1800 : }
     140             : 
     141      181492 : void OutputDevice::DrawPolygon( const Polygon& rPoly )
     142             : {
     143             : 
     144      181492 :     if( mpMetaFile )
     145          12 :         mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
     146             : 
     147      181492 :     sal_uInt16 nPoints = rPoly.GetSize();
     148             : 
     149      181492 :     if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || (nPoints < 2) || ImplIsRecordLayout() )
     150           0 :         return;
     151             : 
     152             :     // we need a graphics
     153      181492 :     if ( !mpGraphics && !AcquireGraphics() )
     154           0 :         return;
     155             : 
     156      181492 :     if ( mbInitClipRegion )
     157         147 :         InitClipRegion();
     158             : 
     159      181492 :     if ( mbOutputClipped )
     160           0 :         return;
     161             : 
     162      181492 :     if ( mbInitLineColor )
     163        1221 :         InitLineColor();
     164             : 
     165      181492 :     if ( mbInitFillColor )
     166        2105 :         InitFillColor();
     167             : 
     168             :     // use b2dpolygon drawing if possible
     169      363002 :     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) &&
     170          18 :        mpGraphics->supportsOperation(OutDevSupport_B2DDraw) &&
     171      181492 :        ROP_OVERPAINT == GetRasterOp() &&
     172           0 :        (IsLineColor() || IsFillColor()))
     173             :     {
     174           0 :         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
     175           0 :         basegfx::B2DPolygon aB2DPolygon(rPoly.getB2DPolygon());
     176           0 :         bool bSuccess(true);
     177             : 
     178             :         // transform the polygon and ensure closed
     179           0 :         aB2DPolygon.transform(aTransform);
     180           0 :         aB2DPolygon.setClosed(true);
     181             : 
     182           0 :         if(IsFillColor())
     183             :         {
     184           0 :             bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(aB2DPolygon), 0.0, this);
     185             :         }
     186             : 
     187           0 :         if(bSuccess && IsLineColor())
     188             :         {
     189           0 :             const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
     190             : 
     191           0 :             if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
     192             :             {
     193           0 :                 aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
     194             :             }
     195             : 
     196             :             bSuccess = mpGraphics->DrawPolyLine( aB2DPolygon,
     197             :                                                  0.0,
     198             :                                                  aB2DLineWidth,
     199             :                                                  basegfx::B2DLINEJOIN_NONE,
     200             :                                                  css::drawing::LineCap_BUTT,
     201           0 :                                                  this);
     202             :         }
     203             : 
     204           0 :         if(bSuccess)
     205             :         {
     206           0 :             return;
     207           0 :         }
     208             :     }
     209             : 
     210      181492 :     Polygon aPoly = ImplLogicToDevicePixel( rPoly );
     211      181492 :     const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
     212             : 
     213             :     // #100127# Forward beziers to sal, if any
     214      181492 :     if( aPoly.HasFlags() )
     215             :     {
     216        5940 :         const sal_uInt8* pFlgAry = aPoly.GetConstFlagAry();
     217        5940 :         if( !mpGraphics->DrawPolygonBezier( nPoints, pPtAry, pFlgAry, this ) )
     218             :         {
     219        5940 :             aPoly = Polygon::SubdivideBezier(aPoly);
     220        5940 :             pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
     221        5940 :             mpGraphics->DrawPolygon( aPoly.GetSize(), pPtAry, this );
     222             :         }
     223             :     }
     224             :     else
     225             :     {
     226      175552 :         mpGraphics->DrawPolygon( nPoints, pPtAry, this );
     227             :     }
     228      181492 :     if( mpAlphaVDev )
     229        5288 :         mpAlphaVDev->DrawPolygon( rPoly );
     230             : }
     231             : 
     232             : // Caution: This method is nearly the same as
     233             : // OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency),
     234             : // so when changes are made here do not forget to make change sthere, too
     235             : 
     236       52278 : void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
     237             : {
     238             : 
     239       52278 :     if( mpMetaFile )
     240        3336 :         mpMetaFile->AddAction( new MetaPolyPolygonAction( tools::PolyPolygon( rB2DPolyPoly ) ) );
     241             : 
     242             :     // call helper
     243       52278 :     ImplDrawPolyPolygonWithB2DPolyPolygon(rB2DPolyPoly);
     244       52278 : }
     245             : 
     246       52278 : void OutputDevice::ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyPolygon& rB2DPolyPoly)
     247             : {
     248             :     // Do not paint empty PolyPolygons
     249       52278 :     if(!rB2DPolyPoly.count() || !IsDeviceOutputNecessary())
     250        6672 :         return;
     251             : 
     252             :     // we need a graphics
     253       48942 :     if( !mpGraphics && !AcquireGraphics() )
     254           0 :         return;
     255             : 
     256       48942 :     if( mbInitClipRegion )
     257          16 :         InitClipRegion();
     258             : 
     259       48942 :     if( mbOutputClipped )
     260           0 :         return;
     261             : 
     262       48942 :     if( mbInitLineColor )
     263         375 :         InitLineColor();
     264             : 
     265       48942 :     if( mbInitFillColor )
     266       44837 :         InitFillColor();
     267             : 
     268       97884 :     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) &&
     269           0 :        mpGraphics->supportsOperation(OutDevSupport_B2DDraw) &&
     270       48942 :        ROP_OVERPAINT == GetRasterOp() &&
     271           0 :        (IsLineColor() || IsFillColor()))
     272             :     {
     273           0 :         const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
     274           0 :         basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
     275           0 :         bool bSuccess(true);
     276             : 
     277             :         // transform the polygon and ensure closed
     278           0 :         aB2DPolyPolygon.transform(aTransform);
     279           0 :         aB2DPolyPolygon.setClosed(true);
     280             : 
     281           0 :         if(IsFillColor())
     282             :         {
     283           0 :             bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
     284             :         }
     285             : 
     286           0 :         if(bSuccess && IsLineColor())
     287             :         {
     288           0 :             const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
     289             : 
     290           0 :             if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
     291             :             {
     292           0 :                 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
     293             :             }
     294             : 
     295           0 :             for(sal_uInt32 a(0);bSuccess && a < aB2DPolyPolygon.count(); a++)
     296             :             {
     297             :                 bSuccess = mpGraphics->DrawPolyLine( aB2DPolyPolygon.getB2DPolygon(a),
     298             :                                                      0.0,
     299             :                                                      aB2DLineWidth,
     300             :                                                      basegfx::B2DLINEJOIN_NONE,
     301             :                                                      css::drawing::LineCap_BUTT,
     302           0 :                                                      this);
     303           0 :             }
     304             :         }
     305             : 
     306           0 :         if(bSuccess)
     307             :         {
     308           0 :             return;
     309           0 :         }
     310             :     }
     311             : 
     312             :     // fallback to old polygon drawing if needed
     313       48942 :     const tools::PolyPolygon aToolsPolyPolygon( rB2DPolyPoly );
     314       97884 :     const tools::PolyPolygon aPixelPolyPolygon = ImplLogicToDevicePixel( aToolsPolyPolygon );
     315       97884 :     ImplDrawPolyPolygon( aPixelPolyPolygon.Count(), aPixelPolyPolygon );
     316             : }
     317             : 
     318             : // #100127# Extracted from OutputDevice::DrawPolyPolygon()
     319       52408 : void OutputDevice::ImplDrawPolyPolygon( sal_uInt16 nPoly, const tools::PolyPolygon& rPolyPoly )
     320             : {
     321             :     // AW: This crashes on empty PolyPolygons, avoid that
     322       52408 :     if(!nPoly)
     323       52408 :         return;
     324             : 
     325             :     sal_uInt32 aStackAry1[OUTDEV_POLYPOLY_STACKBUF];
     326             :     PCONSTSALPOINT aStackAry2[OUTDEV_POLYPOLY_STACKBUF];
     327             :     sal_uInt8* aStackAry3[OUTDEV_POLYPOLY_STACKBUF];
     328             :     sal_uInt32* pPointAry;
     329             :     PCONSTSALPOINT*     pPointAryAry;
     330             :     const sal_uInt8** pFlagAryAry;
     331       52408 :     sal_uInt16 i = 0;
     332       52408 :     sal_uInt16 j = 0;
     333       52408 :     sal_uInt16 last = 0;
     334       52408 :     bool bHaveBezier = false;
     335       52408 :     if ( nPoly > OUTDEV_POLYPOLY_STACKBUF )
     336             :     {
     337         150 :         pPointAry       = new sal_uInt32[nPoly];
     338         150 :         pPointAryAry    = new PCONSTSALPOINT[nPoly];
     339         150 :         pFlagAryAry     = new const sal_uInt8*[nPoly];
     340             :     }
     341             :     else
     342             :     {
     343       52258 :         pPointAry       = aStackAry1;
     344       52258 :         pPointAryAry    = aStackAry2;
     345       52258 :         pFlagAryAry     = (const sal_uInt8**)aStackAry3;
     346             :     }
     347             : 
     348       72898 :     do
     349             :     {
     350       72898 :         const Polygon& rPoly = rPolyPoly.GetObject( i );
     351       72898 :         sal_uInt16 nSize = rPoly.GetSize();
     352       72898 :         if ( nSize )
     353             :         {
     354       72898 :             pPointAry[j] = nSize;
     355       72898 :             pPointAryAry[j] = (PCONSTSALPOINT)rPoly.GetConstPointAry();
     356       72898 :             pFlagAryAry[j] = rPoly.GetConstFlagAry();
     357       72898 :             last = i;
     358             : 
     359       72898 :             if( pFlagAryAry[j] )
     360        8563 :                 bHaveBezier = true;
     361             : 
     362       72898 :             ++j;
     363             :         }
     364       72898 :         ++i;
     365             :     }
     366             :     while ( i < nPoly );
     367             : 
     368       52408 :     if ( j == 1 )
     369             :     {
     370             :         // #100127# Forward beziers to sal, if any
     371       48640 :         if( bHaveBezier )
     372             :         {
     373        5131 :             if( !mpGraphics->DrawPolygonBezier( *pPointAry, *pPointAryAry, *pFlagAryAry, this ) )
     374             :             {
     375        5131 :                 Polygon aPoly = Polygon::SubdivideBezier( rPolyPoly.GetObject( last ) );
     376        5131 :                 mpGraphics->DrawPolygon( aPoly.GetSize(), (const SalPoint*)aPoly.GetConstPointAry(), this );
     377             :             }
     378             :         }
     379             :         else
     380             :         {
     381       43509 :             mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry, this );
     382             :         }
     383             :     }
     384             :     else
     385             :     {
     386             :         // #100127# Forward beziers to sal, if any
     387        3768 :         if( bHaveBezier )
     388             :         {
     389        1389 :             if( !mpGraphics->DrawPolyPolygonBezier( j, pPointAry, pPointAryAry, pFlagAryAry, this ) )
     390             :             {
     391        1389 :                 tools::PolyPolygon aPolyPoly = tools::PolyPolygon::SubdivideBezier( rPolyPoly );
     392        1389 :                 ImplDrawPolyPolygon( aPolyPoly.Count(), aPolyPoly );
     393             :             }
     394             :         }
     395             :         else
     396             :         {
     397        2379 :             mpGraphics->DrawPolyPolygon( j, pPointAry, pPointAryAry, this );
     398             :         }
     399             :     }
     400             : 
     401       52408 :     if ( pPointAry != aStackAry1 )
     402             :     {
     403         150 :         delete[] pPointAry;
     404         150 :         delete[] pPointAryAry;
     405         150 :         delete[] pFlagAryAry;
     406             :     }
     407             : }
     408             : 
     409     2894576 : void OutputDevice::ImplDrawPolygon( const Polygon& rPoly, const tools::PolyPolygon* pClipPolyPoly )
     410             : {
     411     2894576 :     if( pClipPolyPoly )
     412             :     {
     413           0 :         ImplDrawPolyPolygon( rPoly, pClipPolyPoly );
     414             :     }
     415             :     else
     416             :     {
     417     2894576 :         sal_uInt16 nPoints = rPoly.GetSize();
     418             : 
     419     2894576 :         if ( nPoints < 2 )
     420     2894576 :             return;
     421             : 
     422     2894576 :         const SalPoint* pPtAry = (const SalPoint*)rPoly.GetConstPointAry();
     423     2894576 :         mpGraphics->DrawPolygon( nPoints, pPtAry, this );
     424             :     }
     425             : }
     426             : 
     427           0 : void OutputDevice::ImplDrawPolyPolygon( const tools::PolyPolygon& rPolyPoly, const tools::PolyPolygon* pClipPolyPoly )
     428             : {
     429             :     tools::PolyPolygon* pPolyPoly;
     430             : 
     431           0 :     if( pClipPolyPoly )
     432             :     {
     433           0 :         pPolyPoly = new tools::PolyPolygon;
     434           0 :         rPolyPoly.GetIntersection( *pClipPolyPoly, *pPolyPoly );
     435             :     }
     436             :     else
     437             :     {
     438           0 :         pPolyPoly = (tools::PolyPolygon*) &rPolyPoly;
     439             :     }
     440           0 :     if( pPolyPoly->Count() == 1 )
     441             :     {
     442           0 :         const Polygon rPoly = pPolyPoly->GetObject( 0 );
     443           0 :         sal_uInt16 nSize = rPoly.GetSize();
     444             : 
     445           0 :         if( nSize >= 2 )
     446             :         {
     447           0 :             const SalPoint* pPtAry = (const SalPoint*)rPoly.GetConstPointAry();
     448           0 :             mpGraphics->DrawPolygon( nSize, pPtAry, this );
     449           0 :         }
     450             :     }
     451           0 :     else if( pPolyPoly->Count() )
     452             :     {
     453           0 :         sal_uInt16 nCount = pPolyPoly->Count();
     454           0 :         boost::scoped_array<sal_uInt32> pPointAry(new sal_uInt32[nCount]);
     455           0 :         boost::scoped_array<PCONSTSALPOINT> pPointAryAry(new PCONSTSALPOINT[nCount]);
     456           0 :         sal_uInt16 i = 0;
     457           0 :         do
     458             :         {
     459           0 :             const Polygon& rPoly = pPolyPoly->GetObject( i );
     460           0 :             sal_uInt16 nSize = rPoly.GetSize();
     461           0 :             if ( nSize )
     462             :             {
     463           0 :                 pPointAry[i] = nSize;
     464           0 :                 pPointAryAry[i] = (PCONSTSALPOINT)rPoly.GetConstPointAry();
     465           0 :                 i++;
     466             :             }
     467             :             else
     468           0 :                 nCount--;
     469             :         }
     470             :         while( i < nCount );
     471             : 
     472           0 :         if( nCount == 1 )
     473           0 :             mpGraphics->DrawPolygon( pPointAry[0], pPointAryAry[0], this );
     474             :         else
     475           0 :             mpGraphics->DrawPolyPolygon( nCount, pPointAry.get(), pPointAryAry.get(), this );
     476             :     }
     477             : 
     478           0 :     if( pClipPolyPoly )
     479           0 :         delete pPolyPoly;
     480        1233 : }
     481             : 
     482             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10