LCOV - code coverage report
Current view: top level - svx/source/xoutdev - _xpoly.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 256 594 43.1 %
Date: 2015-06-13 12:38:46 Functions: 36 63 57.1 %
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 <osl/endian.h>
      21             : #include <tools/stream.hxx>
      22             : #include <tools/debug.hxx>
      23             : #include <tools/poly.hxx>
      24             : #include <tools/helpers.hxx>
      25             : #include <tools/gen.hxx>
      26             : 
      27             : #include <svx/xpoly.hxx>
      28             : #include "xpolyimp.hxx"
      29             : #include <basegfx/polygon/b2dpolygon.hxx>
      30             : #include <basegfx/point/b2dpoint.hxx>
      31             : #include <basegfx/vector/b2dvector.hxx>
      32             : #include <basegfx/polygon/b2dpolygontools.hxx>
      33             : #include <basegfx/range/b2drange.hxx>
      34             : #include <basegfx/numeric/ftools.hxx>
      35             : 
      36             : 
      37        1315 : ImpXPolygon::ImpXPolygon(sal_uInt16 nInitSize, sal_uInt16 _nResize)
      38             :     : pPointAry(NULL)
      39             :     , pFlagAry(NULL)
      40             :     , pOldPointAry(NULL)
      41             :     , bDeleteOldPoints(false)
      42             :     , nSize(0)
      43             :     , nResize(_nResize)
      44             :     , nPoints(0)
      45        1315 :     , nRefCount(1)
      46             : {
      47        1315 :     Resize(nInitSize);
      48        1315 : }
      49             : 
      50          11 : ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
      51             :     : pPointAry(NULL)
      52             :     , pFlagAry(NULL)
      53             :     , pOldPointAry(NULL)
      54             :     , bDeleteOldPoints(false)
      55             :     , nSize(0)
      56             :     , nResize(rImpXPoly.nResize)
      57             :     , nPoints(0)
      58          11 :     , nRefCount(1)
      59             : {
      60          11 :     ( (ImpXPolygon&) rImpXPoly ).CheckPointDelete();
      61             : 
      62          11 :     Resize( rImpXPoly.nSize );
      63             : 
      64             :     // copy
      65          11 :     nPoints = rImpXPoly.nPoints;
      66          11 :     memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
      67          11 :     memcpy( pFlagAry, rImpXPoly.pFlagAry, nSize );
      68          11 : }
      69             : 
      70        1326 : ImpXPolygon::~ImpXPolygon()
      71             : {
      72        1326 :     delete[] reinterpret_cast<char*>(pPointAry);
      73        1326 :     delete[] pFlagAry;
      74        1326 :     if ( bDeleteOldPoints )
      75           0 :         delete[] reinterpret_cast<char*>(pOldPointAry);
      76        1326 : }
      77             : 
      78           0 : bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
      79             : {
      80           0 :     return nPoints==rImpXPoly.nPoints &&
      81           0 :            (nPoints==0 ||
      82           0 :             (memcmp(pPointAry,rImpXPoly.pPointAry,nPoints*sizeof(Point))==0 &&
      83           0 :              memcmp(pFlagAry,rImpXPoly.pFlagAry,nPoints)==0));
      84             : }
      85             : 
      86             : /** Change polygon size
      87             :  *
      88             :  * @param nNewSize      the new size of the polygon
      89             :  * @param bDeletePoints if FALSE, do not delete the point array directly but
      90             :  *                      wait for the next call before doing so. This prevents
      91             :  *                      errors with XPoly[n] = XPoly[0] where a resize might
      92             :  *                      destroy the right side point array too early.
      93             :  */
      94        1326 : void ImpXPolygon::Resize( sal_uInt16 nNewSize, bool bDeletePoints )
      95             : {
      96        1326 :     if( nNewSize == nSize )
      97        1326 :         return;
      98             : 
      99        1326 :     sal_uInt8*   pOldFlagAry  = pFlagAry;
     100        1326 :     sal_uInt16  nOldSize     = nSize;
     101             : 
     102        1326 :     CheckPointDelete();
     103        1326 :     pOldPointAry = pPointAry;
     104             : 
     105             :     // Round the new size to a multiple of nResize, if
     106             :     // the object was not newly created (nSize != 0)
     107        1326 :     if ( nSize != 0 && nNewSize > nSize )
     108             :     {
     109             :         DBG_ASSERT(nResize, "Trying to resize but nResize = 0 !");
     110           0 :         nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
     111             :     }
     112             :     // create point array
     113        1326 :     nSize     = nNewSize;
     114        1326 :     pPointAry = reinterpret_cast<Point*>(new char[ nSize*sizeof( Point ) ]);
     115        1326 :     memset( pPointAry, 0, nSize*sizeof( Point ) );
     116             : 
     117             :     // create flag array
     118        1326 :     pFlagAry = new sal_uInt8[ nSize ];
     119        1326 :     memset( pFlagAry, 0, nSize );
     120             : 
     121             :     // copy if needed
     122        1326 :     if( nOldSize )
     123             :     {
     124           0 :         if( nOldSize < nSize )
     125             :         {
     126           0 :             memcpy( pPointAry, pOldPointAry, nOldSize*sizeof( Point ) );
     127           0 :             memcpy( pFlagAry,  pOldFlagAry, nOldSize );
     128             :         }
     129             :         else
     130             :         {
     131           0 :             memcpy( pPointAry, pOldPointAry, nSize*sizeof( Point ) );
     132           0 :             memcpy( pFlagAry, pOldFlagAry, nSize );
     133             : 
     134             :             // adjust number of valid points
     135           0 :             if( nPoints > nSize )
     136           0 :                 nPoints = nSize;
     137             :         }
     138           0 :         if ( bDeletePoints )    delete[] reinterpret_cast<char*>(pOldPointAry);
     139           0 :         else                    bDeleteOldPoints = true;
     140           0 :         delete[] pOldFlagAry;
     141             :     }
     142             : }
     143             : 
     144         170 : void ImpXPolygon::InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount )
     145             : {
     146         170 :     CheckPointDelete();
     147             : 
     148         170 :     if ( nPos > nPoints )
     149           0 :         nPos = nPoints;
     150             : 
     151             :     // if the polygon is too small than enlarge it
     152         170 :     if( (nPoints + nCount) > nSize )
     153           0 :         Resize( nPoints + nCount );
     154             : 
     155             :     // If the insert is not at the last position, move everything after backwards
     156         170 :     if( nPos < nPoints )
     157             :     {
     158           0 :         sal_uInt16 nMove = nPoints - nPos;
     159           0 :         memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
     160           0 :                  nMove * sizeof(Point) );
     161           0 :         memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
     162             :     }
     163         170 :     memset( &pPointAry[nPos], 0, nCount * sizeof( Point ) );
     164         170 :     memset( &pFlagAry [nPos], 0, nCount );
     165             : 
     166         170 :     nPoints = nPoints + nCount;
     167         170 : }
     168             : 
     169          66 : void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
     170             : {
     171          66 :     CheckPointDelete();
     172             : 
     173          66 :     if( (nPos + nCount) <= nPoints )
     174             :     {
     175          66 :         sal_uInt16 nMove = nPoints - nPos - nCount;
     176             : 
     177          66 :         if( nMove )
     178             :         {
     179          20 :             memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
     180          30 :                      nMove * sizeof(Point) );
     181          10 :             memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
     182             :         }
     183          66 :         memset( &pPointAry[nPoints - nCount], 0, nCount * sizeof( Point ) );
     184          66 :         memset( &pFlagAry [nPoints - nCount], 0, nCount );
     185          66 :         nPoints = nPoints - nCount;
     186             :     }
     187          66 : }
     188             : 
     189         998 : XPolygon::XPolygon( sal_uInt16 nSize, sal_uInt16 nResize )
     190             : {
     191         998 :     pImpXPolygon = new ImpXPolygon( nSize, nResize );
     192         998 : }
     193             : 
     194        1101 : XPolygon::XPolygon( const XPolygon& rXPoly )
     195             : {
     196        1101 :     pImpXPolygon = rXPoly.pImpXPolygon;
     197        1101 :     pImpXPolygon->nRefCount++;
     198        1101 : }
     199             : 
     200             : /// create a XPolygon out of a standard polygon
     201           1 : XPolygon::XPolygon( const Polygon& rPoly )
     202             : {
     203             : 
     204           1 :     sal_uInt16 nSize = rPoly.GetSize();
     205           1 :     pImpXPolygon = new ImpXPolygon( nSize );
     206           1 :     pImpXPolygon->nPoints = nSize;
     207             : 
     208           3 :     for( sal_uInt16 i = 0; i < nSize;  i++ )
     209             :     {
     210           2 :         pImpXPolygon->pPointAry[i] = rPoly[i];
     211           2 :         pImpXPolygon->pFlagAry[i] = (sal_uInt8) rPoly.GetFlags( i );
     212             :     }
     213           1 : }
     214             : 
     215             : /// create a rectangle (also with rounded corners) as a Bézier polygon
     216          15 : XPolygon::XPolygon(const Rectangle& rRect, long nRx, long nRy)
     217             : {
     218          15 :     pImpXPolygon = new ImpXPolygon(17);
     219          15 :     long nWh = (rRect.GetWidth()  - 1) / 2;
     220          15 :     long nHh = (rRect.GetHeight() - 1) / 2;
     221             : 
     222          15 :     if ( nRx > nWh )    nRx = nWh;
     223          15 :     if ( nRy > nHh )    nRy = nHh;
     224             : 
     225             :     // negate Rx => circle clockwise
     226          15 :     nRx = -nRx;
     227             : 
     228             :     // factor for control points of the Bézier curve: 8/3 * (sin(45g) - 0.5)
     229          15 :     long    nXHdl = (long)(0.552284749 * nRx);
     230          15 :     long    nYHdl = (long)(0.552284749 * nRy);
     231          15 :     sal_uInt16  nPos = 0;
     232             : 
     233          15 :     if ( nRx && nRy )
     234             :     {
     235           2 :         Point aCenter;
     236             : 
     237          10 :         for (sal_uInt16 nQuad = 0; nQuad < 4; nQuad++)
     238             :         {
     239           8 :             switch ( nQuad )
     240             :             {
     241           2 :                 case 0: aCenter = rRect.TopLeft();
     242           2 :                         aCenter.X() -= nRx;
     243           2 :                         aCenter.Y() += nRy;
     244           2 :                         break;
     245           2 :                 case 1: aCenter = rRect.TopRight();
     246           2 :                         aCenter.X() += nRx;
     247           2 :                         aCenter.Y() += nRy;
     248           2 :                         break;
     249           2 :                 case 2: aCenter = rRect.BottomRight();
     250           2 :                         aCenter.X() += nRx;
     251           2 :                         aCenter.Y() -= nRy;
     252           2 :                         break;
     253           2 :                 case 3: aCenter = rRect.BottomLeft();
     254           2 :                         aCenter.X() -= nRx;
     255           2 :                         aCenter.Y() -= nRy;
     256           2 :                         break;
     257             :             }
     258           8 :             GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
     259           8 :             pImpXPolygon->pFlagAry[nPos  ] = (sal_uInt8) XPOLY_SMOOTH;
     260           8 :             pImpXPolygon->pFlagAry[nPos+3] = (sal_uInt8) XPOLY_SMOOTH;
     261           8 :             nPos += 4;
     262           2 :         }
     263             :     }
     264             :     else
     265             :     {
     266          13 :         pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
     267          13 :         pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
     268          13 :         pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
     269          13 :         pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
     270             :     }
     271          15 :     pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
     272          15 :     pImpXPolygon->nPoints = nPos + 1;
     273          15 : }
     274             : 
     275             : /// create a ellipse (curve) as Bézier polygon
     276           0 : XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
     277             :                    sal_uInt16 nStartAngle, sal_uInt16 nEndAngle, bool bClose)
     278             : {
     279           0 :     pImpXPolygon = new ImpXPolygon(17);
     280             : 
     281           0 :     nStartAngle %= 3600;
     282           0 :     if ( nEndAngle > 3600 ) nEndAngle %= 3600;
     283           0 :     bool bFull = (nStartAngle == 0 && nEndAngle == 3600);
     284             : 
     285             :     // factor for control points of the Bézier curve: 8/3 * (sin(45g) - 0.5)
     286           0 :     long    nXHdl = (long)(0.552284749 * nRx);
     287           0 :     long    nYHdl = (long)(0.552284749 * nRy);
     288           0 :     sal_uInt16  nPos = 0;
     289           0 :     bool    bLoopEnd = false;
     290             : 
     291           0 :     do
     292             :     {
     293             :         sal_uInt16 nA1, nA2;
     294           0 :         sal_uInt16 nQuad = nStartAngle / 900;
     295           0 :         if ( nQuad == 4 ) nQuad = 0;
     296           0 :         bLoopEnd = CheckAngles(nStartAngle, nEndAngle, nA1, nA2);
     297           0 :         GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
     298           0 :         nPos += 3;
     299           0 :         if ( !bLoopEnd )
     300           0 :             pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
     301             : 
     302           0 :     } while ( !bLoopEnd );
     303             : 
     304             :     // if not a full circle than connect edges with center point if necessary
     305           0 :     if ( !bFull && bClose )
     306           0 :         pImpXPolygon->pPointAry[++nPos] = rCenter;
     307             : 
     308           0 :     if ( bFull )
     309             :     {
     310           0 :         pImpXPolygon->pFlagAry[0   ] = (sal_uInt8) XPOLY_SMOOTH;
     311           0 :         pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
     312             :     }
     313           0 :     pImpXPolygon->nPoints = nPos + 1;
     314           0 : }
     315             : 
     316        2416 : XPolygon::~XPolygon()
     317             : {
     318        2416 :     if( pImpXPolygon->nRefCount > 1 )
     319        1216 :         pImpXPolygon->nRefCount--;
     320             :     else
     321        1200 :         delete pImpXPolygon;
     322        2416 : }
     323             : 
     324             : /// check reference counter and decouple if > 1
     325        2916 : void XPolygon::CheckReference()
     326             : {
     327        2916 :     if( pImpXPolygon->nRefCount > 1 )
     328             :     {
     329          11 :         pImpXPolygon->nRefCount--;
     330          11 :         pImpXPolygon = new ImpXPolygon( *pImpXPolygon );
     331             :     }
     332        2916 : }
     333             : 
     334           0 : void XPolygon::SetPointCount( sal_uInt16 nPoints )
     335             : {
     336           0 :     pImpXPolygon->CheckPointDelete();
     337           0 :     CheckReference();
     338             : 
     339           0 :     if( pImpXPolygon->nSize < nPoints )
     340           0 :         pImpXPolygon->Resize( nPoints );
     341             : 
     342           0 :     if ( nPoints < pImpXPolygon->nPoints )
     343             :     {
     344           0 :         sal_uInt16 nSize = pImpXPolygon->nPoints - nPoints;
     345           0 :         memset( &pImpXPolygon->pPointAry[nPoints], 0, nSize * sizeof( Point ) );
     346           0 :         memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
     347             :     }
     348           0 :     pImpXPolygon->nPoints = nPoints;
     349           0 : }
     350             : 
     351           1 : sal_uInt16 XPolygon::GetSize() const
     352             : {
     353           1 :     pImpXPolygon->CheckPointDelete();
     354           1 :     return pImpXPolygon->nSize;
     355             : }
     356             : 
     357         862 : sal_uInt16 XPolygon::GetPointCount() const
     358             : {
     359         862 :     pImpXPolygon->CheckPointDelete();
     360         862 :     return pImpXPolygon->nPoints;
     361             : }
     362             : 
     363         170 : void XPolygon::Insert( sal_uInt16 nPos, const Point& rPt, XPolyFlags eFlags )
     364             : {
     365         170 :     CheckReference();
     366         170 :     if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
     367         170 :     pImpXPolygon->InsertSpace( nPos, 1 );
     368         170 :     pImpXPolygon->pPointAry[nPos] = rPt;
     369         170 :     pImpXPolygon->pFlagAry[nPos]  = (sal_uInt8)eFlags;
     370         170 : }
     371             : 
     372           0 : void XPolygon::Insert( sal_uInt16 nPos, const XPolygon& rXPoly )
     373             : {
     374           0 :     CheckReference();
     375           0 :     if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
     376             : 
     377           0 :     sal_uInt16 nPoints = rXPoly.GetPointCount();
     378             : 
     379           0 :     pImpXPolygon->InsertSpace( nPos, nPoints );
     380             : 
     381           0 :     memcpy( &(pImpXPolygon->pPointAry[nPos]),
     382             :             rXPoly.pImpXPolygon->pPointAry,
     383           0 :             nPoints*sizeof( Point ) );
     384           0 :     memcpy( &(pImpXPolygon->pFlagAry[nPos]),
     385             :             rXPoly.pImpXPolygon->pFlagAry,
     386           0 :             nPoints );
     387           0 : }
     388             : 
     389          66 : void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
     390             : {
     391          66 :     CheckReference();
     392          66 :     pImpXPolygon->Remove( nPos, nCount );
     393          66 : }
     394             : 
     395           0 : void XPolygon::Move( long nHorzMove, long nVertMove )
     396             : {
     397           0 :     if ( !nHorzMove && !nVertMove )
     398           0 :         return;
     399             : 
     400           0 :     CheckReference();
     401             : 
     402             :     // move points
     403           0 :     sal_uInt16 nCount = pImpXPolygon->nPoints;
     404           0 :     for ( sal_uInt16 i = 0; i < nCount; i++ )
     405             :     {
     406           0 :         Point* pPt = &(pImpXPolygon->pPointAry[i]);
     407           0 :         pPt->X() += nHorzMove;
     408           0 :         pPt->Y() += nVertMove;
     409             :     }
     410             : }
     411             : 
     412         194 : Rectangle XPolygon::GetBoundRect() const
     413             : {
     414         194 :     pImpXPolygon->CheckPointDelete();
     415         194 :     Rectangle aRetval;
     416             : 
     417         194 :     if(pImpXPolygon->nPoints)
     418             :     {
     419             :         // #i37709#
     420             :         // For historical reasons the control points are not part of the
     421             :         // BoundRect. This makes it necessary to subdivide the polygon to
     422             :         // get a relatively correct BoundRect. Numerically, this is not
     423             :         // correct and never was.
     424             : 
     425         193 :         const basegfx::B2DRange aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
     426             :         aRetval = Rectangle(
     427             :             FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
     428         193 :             FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
     429             :     }
     430             : 
     431         194 :     return aRetval;
     432             : }
     433             : 
     434         863 : const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
     435             : {
     436             :     DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
     437             : 
     438         863 :     pImpXPolygon->CheckPointDelete();
     439         863 :     return pImpXPolygon->pPointAry[nPos];
     440             : }
     441             : 
     442        2580 : Point& XPolygon::operator[]( sal_uInt16 nPos )
     443             : {
     444        2580 :     pImpXPolygon->CheckPointDelete();
     445        2580 :     CheckReference();
     446             : 
     447        2580 :     if( nPos >= pImpXPolygon->nSize )
     448             :     {
     449             :         DBG_ASSERT(pImpXPolygon->nResize, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
     450           0 :         pImpXPolygon->Resize(nPos + 1, false);
     451             :     }
     452        2580 :     if( nPos >= pImpXPolygon->nPoints )
     453        1797 :         pImpXPolygon->nPoints = nPos + 1;
     454             : 
     455        2580 :     return pImpXPolygon->pPointAry[nPos];
     456             : }
     457             : 
     458         126 : XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
     459             : {
     460         126 :     if (this == &rXPoly)
     461           0 :         return *this;
     462             : 
     463         126 :     pImpXPolygon->CheckPointDelete();
     464             : 
     465         126 :     rXPoly.pImpXPolygon->nRefCount++;
     466             : 
     467         126 :     if( pImpXPolygon->nRefCount > 1 )
     468           0 :         pImpXPolygon->nRefCount--;
     469             :     else
     470         126 :         delete pImpXPolygon;
     471             : 
     472         126 :     pImpXPolygon = rXPoly.pImpXPolygon;
     473         126 :     return *this;
     474             : }
     475             : 
     476           0 : bool XPolygon::operator==( const XPolygon& rXPoly ) const
     477             : {
     478           0 :     pImpXPolygon->CheckPointDelete();
     479           0 :     if (rXPoly.pImpXPolygon==pImpXPolygon) return true;
     480           0 :     return *rXPoly.pImpXPolygon == *pImpXPolygon;
     481             : }
     482             : 
     483           0 : bool XPolygon::operator!=( const XPolygon& rXPoly ) const
     484             : {
     485           0 :     pImpXPolygon->CheckPointDelete();
     486           0 :     if (rXPoly.pImpXPolygon==pImpXPolygon) return false;
     487           0 :     return *rXPoly.pImpXPolygon != *pImpXPolygon;
     488             : }
     489             : 
     490             : /// get the flags for the point at the given position
     491        1467 : XPolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
     492             : {
     493        1467 :     pImpXPolygon->CheckPointDelete();
     494        1467 :     return (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
     495             : }
     496             : 
     497             : /// set the flags for the point at the given position
     498         100 : void XPolygon::SetFlags( sal_uInt16 nPos, XPolyFlags eFlags )
     499             : {
     500         100 :     pImpXPolygon->CheckPointDelete();
     501         100 :     CheckReference();
     502         100 :     pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) eFlags;
     503         100 : }
     504             : 
     505             : /// short path to read the CONTROL flag directly (TODO: better explain what the sense behind this flag is!)
     506           0 : bool XPolygon::IsControl(sal_uInt16 nPos) const
     507             : {
     508           0 :     return ( (XPolyFlags) pImpXPolygon->pFlagAry[nPos] == XPOLY_CONTROL );
     509             : }
     510             : 
     511             : /// short path to read the SMOOTH and SYMMTR flag directly (TODO: better explain what the sense behind these flags is!)
     512           0 : bool XPolygon::IsSmooth(sal_uInt16 nPos) const
     513             : {
     514           0 :     XPolyFlags eFlag = (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
     515           0 :     return ( eFlag == XPOLY_SMOOTH || eFlag == XPOLY_SYMMTR );
     516             : }
     517             : 
     518             : /** calculate the euclidean distance between two points
     519             :  *
     520             :  * @param nP1 The first point
     521             :  * @param nP2 The second point
     522             :  */
     523           0 : double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
     524             : {
     525           0 :     const Point& rP1 = pImpXPolygon->pPointAry[nP1];
     526           0 :     const Point& rP2 = pImpXPolygon->pPointAry[nP2];
     527           0 :     double fDx = rP2.X() - rP1.X();
     528           0 :     double fDy = rP2.Y() - rP1.Y();
     529           0 :     return sqrt(fDx * fDx + fDy * fDy);
     530             : }
     531             : 
     532           0 : void XPolygon::SubdivideBezier(sal_uInt16 nPos, bool bCalcFirst, double fT)
     533             : {
     534           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     535           0 :     double  fT2 = fT * fT;
     536           0 :     double  fT3 = fT * fT2;
     537           0 :     double  fU = 1.0 - fT;
     538           0 :     double  fU2 = fU * fU;
     539           0 :     double  fU3 = fU * fU2;
     540           0 :     sal_uInt16  nIdx = nPos;
     541             :     short   nPosInc, nIdxInc;
     542             : 
     543           0 :     if ( bCalcFirst )
     544             :     {
     545           0 :         nPos += 3;
     546           0 :         nPosInc = -1;
     547           0 :         nIdxInc = 0;
     548             :     }
     549             :     else
     550             :     {
     551           0 :         nPosInc = 1;
     552           0 :         nIdxInc = 1;
     553             :     }
     554           0 :     pPoints[nPos].X() = (long) (fU3 *       pPoints[nIdx  ].X() +
     555           0 :                                 fT  * fU2 * pPoints[nIdx+1].X() * 3 +
     556           0 :                                 fT2 * fU  * pPoints[nIdx+2].X() * 3 +
     557           0 :                                 fT3 *       pPoints[nIdx+3].X());
     558           0 :     pPoints[nPos].Y() = (long) (fU3 *       pPoints[nIdx  ].Y() +
     559           0 :                                 fT  * fU2 * pPoints[nIdx+1].Y() * 3 +
     560           0 :                                 fT2 * fU  * pPoints[nIdx+2].Y() * 3 +
     561           0 :                                 fT3 *       pPoints[nIdx+3].Y());
     562           0 :     nPos = nPos + nPosInc;
     563           0 :     nIdx = nIdx + nIdxInc;
     564           0 :     pPoints[nPos].X() = (long) (fU2 *       pPoints[nIdx  ].X() +
     565           0 :                                 fT  * fU *  pPoints[nIdx+1].X() * 2 +
     566           0 :                                 fT2 *       pPoints[nIdx+2].X());
     567           0 :     pPoints[nPos].Y() = (long) (fU2 *       pPoints[nIdx  ].Y() +
     568           0 :                                 fT  * fU *  pPoints[nIdx+1].Y() * 2 +
     569           0 :                                 fT2 *       pPoints[nIdx+2].Y());
     570           0 :     nPos = nPos + nPosInc;
     571           0 :     nIdx = nIdx + nIdxInc;
     572           0 :     pPoints[nPos].X() = (long) (fU * pPoints[nIdx  ].X() +
     573           0 :                                 fT * pPoints[nIdx+1].X());
     574           0 :     pPoints[nPos].Y() = (long) (fU * pPoints[nIdx  ].Y() +
     575           0 :                                 fT * pPoints[nIdx+1].Y());
     576           0 : }
     577             : 
     578             : /// Generate a Bézier arc
     579           8 : void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
     580             :                          long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
     581             :                          sal_uInt16 nQuad, sal_uInt16 nFirst)
     582             : {
     583           8 :     Point* pPoints = pImpXPolygon->pPointAry;
     584           8 :     pPoints[nFirst  ] = rCenter;
     585           8 :     pPoints[nFirst+3] = rCenter;
     586             : 
     587           8 :     if ( nQuad == 1 || nQuad == 2 )
     588             :     {
     589           4 :         nRx   = -nRx; nXHdl = -nXHdl;
     590             :     }
     591           8 :     if ( nQuad == 0 || nQuad == 1 )
     592             :     {
     593           4 :         nRy   = -nRy; nYHdl = -nYHdl;
     594             :     }
     595             : 
     596           8 :     if ( nQuad == 0 || nQuad == 2 )
     597             :     {
     598           4 :         pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
     599             :     }
     600             :     else
     601             :     {
     602           4 :         pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
     603             :     }
     604           8 :     pPoints[nFirst+1] = pPoints[nFirst];
     605           8 :     pPoints[nFirst+2] = pPoints[nFirst+3];
     606             : 
     607           8 :     if ( nQuad == 0 || nQuad == 2 )
     608             :     {
     609           4 :         pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
     610             :     }
     611             :     else
     612             :     {
     613           4 :         pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
     614             :     }
     615           8 :     if ( nStart > 0 )
     616           0 :         SubdivideBezier(nFirst, false, (double)nStart / 900);
     617           8 :     if ( nEnd < 900 )
     618           0 :         SubdivideBezier(nFirst, true, (double)(nEnd-nStart) / (900-nStart));
     619           8 :     SetFlags(nFirst+1, XPOLY_CONTROL);
     620           8 :     SetFlags(nFirst+2, XPOLY_CONTROL);
     621           8 : }
     622             : 
     623           0 : bool XPolygon::CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2)
     624             : {
     625           0 :     if ( nStart == 3600 ) nStart = 0;
     626           0 :     if ( nEnd == 0 ) nEnd = 3600;
     627           0 :     sal_uInt16 nStPrev = nStart;
     628           0 :     sal_uInt16 nMax = (nStart / 900 + 1) * 900;
     629           0 :     sal_uInt16 nMin = nMax - 900;
     630             : 
     631           0 :     if ( nEnd >= nMax || nEnd <= nStart )   nA2 = 900;
     632           0 :     else                                    nA2 = nEnd - nMin;
     633           0 :     nA1 = nStart - nMin;
     634           0 :     nStart = nMax;
     635             : 
     636             :     // returns true when the last segment was calculated
     637           0 :     return (nStPrev < nEnd && nStart >= nEnd);
     638             : }
     639             : 
     640             : /** Calculate a smooth transition to connect two Bézier curves
     641             :  *
     642             :  * This is done by projecting the corresponding point onto a line between
     643             :  * two other points.
     644             :  *
     645             :  * @param nCenter The point at the end or beginning of the curve.
     646             :  *                If nCenter is at the end of the polygon the point is moved
     647             :  *                to the opposite side.
     648             :  * @param nDrag The moved point that specifies the relocation.
     649             :  * @param nPnt The point to modify.
     650             :  */
     651           0 : void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 nPnt)
     652             : {
     653           0 :     CheckReference();
     654             : 
     655             :     // If nPoint is no control point, i.e. cannot be moved, than
     656             :     // move nDrag instead on the line between nCenter and nPnt
     657           0 :     if ( !IsControl(nPnt) )
     658             :     {
     659           0 :         sal_uInt16 nTmp = nDrag;
     660           0 :         nDrag = nPnt;
     661           0 :         nPnt = nTmp;
     662             :     }
     663           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     664           0 :     Point   aDiff   = pPoints[nDrag] - pPoints[nCenter];
     665           0 :     double  fDiv    = CalcDistance(nCenter, nDrag);
     666             : 
     667           0 :     if ( fDiv )
     668             :     {
     669           0 :         double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
     670             :         // keep the length if SMOOTH
     671           0 :         if ( GetFlags(nCenter) == XPOLY_SMOOTH || !IsControl(nDrag) )
     672             :         {
     673           0 :             aDiff.X() = (long) (fRatio * aDiff.X());
     674           0 :             aDiff.Y() = (long) (fRatio * aDiff.Y());
     675             :         }
     676           0 :         pPoints[nPnt] = pPoints[nCenter] - aDiff;
     677             :     }
     678           0 : }
     679             : 
     680             : /** Calculate tangent between two Bézier curves
     681             :  *
     682             :  * @param nCenter start or end point of the curves
     683             :  * @param nPrev previous reference point
     684             :  * @param nNext next reference point
     685             :  */
     686           0 : void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNext)
     687             : {
     688           0 :     CheckReference();
     689             : 
     690           0 :     double fAbsLen = CalcDistance(nNext, nPrev);
     691             : 
     692           0 :     if ( fAbsLen )
     693             :     {
     694           0 :         const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
     695           0 :         Point&  rNext = pImpXPolygon->pPointAry[nNext];
     696           0 :         Point&  rPrev = pImpXPolygon->pPointAry[nPrev];
     697           0 :         Point   aDiff = rNext - rPrev;
     698           0 :         double  fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
     699           0 :         double  fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
     700             : 
     701             :         // same length for both sides if SYMMTR
     702           0 :         if ( GetFlags(nCenter) == XPOLY_SYMMTR )
     703             :         {
     704           0 :             fPrevLen = (fNextLen + fPrevLen) / 2;
     705           0 :             fNextLen = fPrevLen;
     706             :         }
     707           0 :         rNext.X() = rCenter.X() + (long) (fNextLen * aDiff.X());
     708           0 :         rNext.Y() = rCenter.Y() + (long) (fNextLen * aDiff.Y());
     709           0 :         rPrev.X() = rCenter.X() - (long) (fPrevLen * aDiff.X());
     710           0 :         rPrev.Y() = rCenter.Y() - (long) (fPrevLen * aDiff.Y());
     711             :     }
     712           0 : }
     713             : 
     714             : /// convert four polygon points into a Bézier curve
     715           0 : void XPolygon::PointsToBezier(sal_uInt16 nFirst)
     716             : {
     717             :     double  nFullLength, nPart1Length, nPart2Length;
     718             :     double  fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
     719             :     double  fTx1, fTx2, fTy1, fTy2;
     720             :     double  fT1, fU1, fT2, fU2, fV;
     721           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     722             : 
     723           0 :     if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
     724           0 :          IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
     725           0 :         return;
     726             : 
     727           0 :     CheckReference();
     728             : 
     729           0 :     fTx1 = pPoints[nFirst+1].X();
     730           0 :     fTy1 = pPoints[nFirst+1].Y();
     731           0 :     fTx2 = pPoints[nFirst+2].X();
     732           0 :     fTy2 = pPoints[nFirst+2].Y();
     733           0 :     fX0  = pPoints[nFirst  ].X();
     734           0 :     fY0  = pPoints[nFirst  ].Y();
     735           0 :     fX3  = pPoints[nFirst+3].X();
     736           0 :     fY3  = pPoints[nFirst+3].Y();
     737             : 
     738           0 :     nPart1Length = CalcDistance(nFirst, nFirst+1);
     739           0 :     nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
     740           0 :     nFullLength  = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
     741           0 :     if ( nFullLength < 20 )
     742           0 :         return;
     743             : 
     744           0 :     if ( nPart2Length == nFullLength )
     745           0 :         nPart2Length -= 1;
     746           0 :     if ( nPart1Length == nFullLength )
     747           0 :         nPart1Length = nPart2Length - 1;
     748           0 :     if ( nPart1Length <= 0 )
     749           0 :         nPart1Length = 1;
     750           0 :     if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
     751           0 :         nPart2Length = nPart1Length + 1;
     752             : 
     753           0 :     fT1 = nPart1Length / nFullLength;
     754           0 :     fU1 = 1.0 - fT1;
     755           0 :     fT2 = nPart2Length / nFullLength;
     756           0 :     fU2 = 1.0 - fT2;
     757           0 :     fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
     758             : 
     759           0 :     fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
     760           0 :     fX1 /= fV;
     761           0 :     fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
     762           0 :     fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
     763             : 
     764           0 :     fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
     765           0 :     fY1 /= fV;
     766           0 :     fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
     767           0 :     fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
     768             : 
     769           0 :     fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
     770           0 :     fX2 -= fX1 * fU2 / fT2;
     771           0 :     fX2 -= fX3 * fT2 / (fU2 * 3);
     772             : 
     773           0 :     fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
     774           0 :     fY2 -= fY1 * fU2 / fT2;
     775           0 :     fY2 -= fY3 * fT2 / (fU2 * 3);
     776             : 
     777           0 :     pPoints[nFirst+1] = Point((long) fX1, (long) fY1);
     778           0 :     pPoints[nFirst+2] = Point((long) fX2, (long) fY2);
     779           0 :     SetFlags(nFirst+1, XPOLY_CONTROL);
     780           0 :     SetFlags(nFirst+2, XPOLY_CONTROL);
     781             : }
     782             : 
     783             : /// scale in X- and/or Y-direction
     784           0 : void XPolygon::Scale(double fSx, double fSy)
     785             : {
     786           0 :     pImpXPolygon->CheckPointDelete();
     787           0 :     CheckReference();
     788             : 
     789           0 :     sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
     790             : 
     791           0 :     for (sal_uInt16 i = 0; i < nPntCnt; i++)
     792             :     {
     793           0 :         Point& rPnt = pImpXPolygon->pPointAry[i];
     794           0 :         rPnt.X() = (long)(fSx * rPnt.X());
     795           0 :         rPnt.Y() = (long)(fSy * rPnt.Y());
     796             :     }
     797           0 : }
     798             : 
     799             : /**
     800             :  * Distort a polygon by scaling its coordinates relative to a reference
     801             :  * rectangle into an arbitrary rectangle.
     802             :  *
     803             :  * Mapping between polygon corners and reference rectangle:
     804             :  *     0: top left     0----1
     805             :  *     1: top right    |    |
     806             :  *     2: bottom right 3----2
     807             :  *     3: bottom left
     808             :  */
     809           0 : void XPolygon::Distort(const Rectangle& rRefRect,
     810             :                        const XPolygon& rDistortedRect)
     811             : {
     812           0 :     pImpXPolygon->CheckPointDelete();
     813           0 :     CheckReference();
     814             : 
     815             :     long    Xr, Wr;
     816             :     long    Yr, Hr;
     817             : 
     818           0 :     Xr = rRefRect.Left();
     819           0 :     Yr = rRefRect.Top();
     820           0 :     Wr = rRefRect.GetWidth();
     821           0 :     Hr = rRefRect.GetHeight();
     822             : 
     823           0 :     if ( Wr && Hr )
     824             :     {
     825             :         long    X1, X2, X3, X4;
     826             :         long    Y1, Y2, Y3, Y4;
     827             :         DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
     828             :                    "Distort: rectangle to small");
     829             : 
     830           0 :         X1 = rDistortedRect[0].X();
     831           0 :         Y1 = rDistortedRect[0].Y();
     832           0 :         X2 = rDistortedRect[1].X();
     833           0 :         Y2 = rDistortedRect[1].Y();
     834           0 :         X3 = rDistortedRect[3].X();
     835           0 :         Y3 = rDistortedRect[3].Y();
     836           0 :         X4 = rDistortedRect[2].X();
     837           0 :         Y4 = rDistortedRect[2].Y();
     838             : 
     839           0 :         sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
     840             : 
     841           0 :         for (sal_uInt16 i = 0; i < nPntCnt; i++)
     842             :         {
     843             :             double  fTx, fTy, fUx, fUy;
     844           0 :             Point& rPnt = pImpXPolygon->pPointAry[i];
     845             : 
     846           0 :             fTx = (double)(rPnt.X() - Xr) / Wr;
     847           0 :             fTy = (double)(rPnt.Y() - Yr) / Hr;
     848           0 :             fUx = 1.0 - fTx;
     849           0 :             fUy = 1.0 - fTy;
     850             : 
     851           0 :             rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) +
     852           0 :                                 fTy * (fUx * X3 + fTx * X4) );
     853           0 :             rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) +
     854           0 :                                 fTx * (fUy * Y2 + fTy * Y4) );
     855             :         }
     856             :     }
     857           0 : }
     858             : 
     859         266 : basegfx::B2DPolygon XPolygon::getB2DPolygon() const
     860             : {
     861             :     // #i74631# use tools Polygon class for conversion to not have the code doubled
     862             :     // here. This needs one more conversion but avoids different convertors in
     863             :     // the long run
     864             :     DBG_ASSERT(pImpXPolygon != 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
     865         266 :     const Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry);
     866             : 
     867         266 :     return aSource.getB2DPolygon();
     868             : }
     869             : 
     870         301 : XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
     871             : {
     872             :     // #i74631# use tools Polygon class for conversion to not have the code doubled
     873             :     // here. This needs one more conversion but avoids different convertors in
     874             :     // the long run
     875             : 
     876         301 :     const Polygon aSource(rPolygon);
     877         301 :     sal_uInt16 nSize = aSource.GetSize();
     878         301 :     pImpXPolygon = new ImpXPolygon( nSize );
     879         301 :     pImpXPolygon->nPoints = nSize;
     880             : 
     881        3157 :     for( sal_uInt16 i = 0; i < nSize;  i++ )
     882             :     {
     883        2856 :         pImpXPolygon->pPointAry[i] = aSource[i];
     884        2856 :         pImpXPolygon->pFlagAry[i] = (sal_uInt8) aSource.GetFlags( i );
     885         301 :     }
     886         301 : }
     887             : 
     888             : // XPolyPolygon
     889             : 
     890           0 : ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon& rImpXPolyPoly ) :
     891           0 :                      aXPolyList( rImpXPolyPoly.aXPolyList )
     892             : {
     893           0 :     nRefCount = 1;
     894             : 
     895             :     // duplicate elements
     896           0 :     for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
     897           0 :         aXPolyList[ i ] = new XPolygon( *aXPolyList[ i ] );
     898           0 : }
     899             : 
     900         378 : ImpXPolyPolygon::~ImpXPolyPolygon()
     901             : {
     902         425 :     for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
     903         236 :         delete aXPolyList[ i ];
     904         189 :     aXPolyList.clear();
     905         189 : }
     906             : 
     907           0 : bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon& rImpXPolyPoly) const
     908             : {
     909           0 :     size_t nCount = aXPolyList.size();
     910           0 :     const XPolygonList& rCmpList = rImpXPolyPoly.aXPolyList;
     911           0 :     if ( nCount != rCmpList.size() ) return false;
     912           0 :     bool bEq=true;
     913           0 :     for ( size_t i = nCount; i > 0 && bEq; )
     914             :     {
     915           0 :         i--;
     916           0 :         bEq = ( *aXPolyList[ i ] == *rCmpList[ i ] );
     917             :     }
     918           0 :     return bEq;
     919             : }
     920             : 
     921          18 : XPolyPolygon::XPolyPolygon( sal_uInt16 /*nInitSize*/, sal_uInt16 /*nResize*/ )
     922             : {
     923          18 :     pImpXPolyPolygon = new ImpXPolyPolygon();
     924          18 : }
     925             : 
     926           0 : XPolyPolygon::XPolyPolygon( const XPolyPolygon& rXPolyPoly )
     927             : {
     928           0 :     pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
     929           0 :     pImpXPolyPolygon->nRefCount++;
     930           0 : }
     931             : 
     932         189 : XPolyPolygon::~XPolyPolygon()
     933             : {
     934         189 :     if( pImpXPolyPolygon->nRefCount > 1 )
     935          15 :         pImpXPolyPolygon->nRefCount--;
     936             :     else
     937         174 :         delete pImpXPolyPolygon;
     938         189 : }
     939             : 
     940             : /// check reference counter and decouple if > 1
     941         236 : void XPolyPolygon::CheckReference()
     942             : {
     943         236 :     if( pImpXPolyPolygon->nRefCount > 1 )
     944             :     {
     945           0 :         pImpXPolyPolygon->nRefCount--;
     946           0 :         pImpXPolyPolygon = new ImpXPolyPolygon( *pImpXPolyPolygon );
     947             :     }
     948         236 : }
     949             : 
     950         236 : void XPolyPolygon::Insert( const XPolygon& rXPoly, sal_uInt16 nPos )
     951             : {
     952         236 :     CheckReference();
     953         236 :     XPolygon* pXPoly = new XPolygon( rXPoly );
     954         236 :     if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
     955             :     {
     956           0 :         XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
     957           0 :         ::std::advance( it, nPos );
     958           0 :         pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
     959             :     }
     960             :     else
     961         236 :         pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
     962         236 : }
     963             : 
     964             : /// insert all XPolygons of a XPolyPolygon
     965           0 : void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly, sal_uInt16 nPos )
     966             : {
     967           0 :     CheckReference();
     968             : 
     969           0 :     for ( size_t i = 0; i < rXPolyPoly.Count(); i++)
     970             :     {
     971           0 :         XPolygon* pXPoly = new XPolygon( rXPolyPoly[i] );
     972             : 
     973           0 :         if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
     974             :         {
     975           0 :             XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
     976           0 :             ::std::advance( it, nPos );
     977           0 :             pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
     978           0 :             nPos++;
     979             :         }
     980             :         else
     981           0 :             pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
     982             :     }
     983           0 : }
     984             : 
     985           0 : XPolygon XPolyPolygon::Remove( sal_uInt16 nPos )
     986             : {
     987           0 :     CheckReference();
     988           0 :     XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
     989           0 :     ::std::advance( it, nPos );
     990           0 :     XPolygon* pTmpXPoly = *it;
     991           0 :     pImpXPolyPolygon->aXPolyList.erase( it );
     992           0 :     XPolygon  aXPoly( *pTmpXPoly );
     993           0 :     delete pTmpXPoly;
     994           0 :     return aXPoly;
     995             : }
     996             : 
     997         173 : const XPolygon& XPolyPolygon::GetObject( sal_uInt16 nPos ) const
     998             : {
     999         173 :     return *(pImpXPolyPolygon->aXPolyList[ nPos ]);
    1000             : }
    1001             : 
    1002           0 : void XPolyPolygon::Clear()
    1003             : {
    1004           0 :     if ( pImpXPolyPolygon->nRefCount > 1 )
    1005             :     {
    1006           0 :         pImpXPolyPolygon->nRefCount--;
    1007           0 :         pImpXPolyPolygon = new ImpXPolyPolygon();
    1008             :     }
    1009             :     else
    1010             :     {
    1011           0 :         for( size_t i = 0, n = pImpXPolyPolygon->aXPolyList.size(); i < n; ++i )
    1012           0 :             delete pImpXPolyPolygon->aXPolyList[ i ];
    1013           0 :         pImpXPolyPolygon->aXPolyList.clear();
    1014             :     }
    1015           0 : }
    1016             : 
    1017         162 : sal_uInt16 XPolyPolygon::Count() const
    1018             : {
    1019         162 :     return (sal_uInt16)(pImpXPolyPolygon->aXPolyList.size());
    1020             : }
    1021             : 
    1022          15 : Rectangle XPolyPolygon::GetBoundRect() const
    1023             : {
    1024          15 :     size_t nXPoly = pImpXPolyPolygon->aXPolyList.size();
    1025          15 :     Rectangle aRect;
    1026             : 
    1027          78 :     for ( size_t n = 0; n < nXPoly; n++ )
    1028             :     {
    1029          63 :         const XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList[ n ];
    1030          63 :         aRect.Union( pXPoly->GetBoundRect() );
    1031             :     }
    1032             : 
    1033          15 :     return aRect;
    1034             : }
    1035             : 
    1036           0 : XPolygon& XPolyPolygon::operator[]( sal_uInt16 nPos )
    1037             : {
    1038           0 :     CheckReference();
    1039           0 :     return *( pImpXPolyPolygon->aXPolyList[ nPos ] );
    1040             : }
    1041             : 
    1042          15 : XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& rXPolyPoly )
    1043             : {
    1044          15 :     rXPolyPoly.pImpXPolyPolygon->nRefCount++;
    1045             : 
    1046          15 :     if( pImpXPolyPolygon->nRefCount > 1 )
    1047           0 :         pImpXPolyPolygon->nRefCount--;
    1048             :     else
    1049          15 :         delete pImpXPolyPolygon;
    1050             : 
    1051          15 :     pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
    1052          15 :     return *this;
    1053             : }
    1054             : 
    1055           0 : bool XPolyPolygon::operator==( const XPolyPolygon& rXPolyPoly ) const
    1056             : {
    1057           0 :     if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return true;
    1058           0 :     return *pImpXPolyPolygon == *rXPolyPoly.pImpXPolyPolygon;
    1059             : }
    1060             : 
    1061           0 : bool XPolyPolygon::operator!=( const XPolyPolygon& rXPolyPoly ) const
    1062             : {
    1063           0 :     if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return false;
    1064           0 :     return *pImpXPolyPolygon != *rXPolyPoly.pImpXPolyPolygon;
    1065             : }
    1066             : 
    1067             : /**
    1068             :  * Distort a polygon by scaling its coordinates relative to a reference
    1069             :  * rectangle into an arbitrary rectangle.
    1070             :  *
    1071             :  * Mapping between polygon corners and reference rectangle:
    1072             :  *     0: top left     0----1
    1073             :  *     1: top right    |    |
    1074             :  *     2: bottom right 3----2
    1075             :  *     3: bottom left
    1076             :  */
    1077           0 : void XPolyPolygon::Distort(const Rectangle& rRefRect,
    1078             :                            const XPolygon& rDistortedRect)
    1079             : {
    1080           0 :     CheckReference();
    1081             : 
    1082           0 :     for (size_t i = 0; i < Count(); i++)
    1083           0 :         pImpXPolyPolygon->aXPolyList[ i ]->Distort(rRefRect, rDistortedRect);
    1084           0 : }
    1085             : 
    1086           3 : basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
    1087             : {
    1088           3 :     basegfx::B2DPolyPolygon aRetval;
    1089             : 
    1090           6 :     for(sal_uInt16 a(0L); a < Count(); a++)
    1091             :     {
    1092           3 :         const XPolygon& rPoly = (*this)[a];
    1093           3 :         aRetval.append(rPoly.getB2DPolygon());
    1094             :     }
    1095             : 
    1096           3 :     return aRetval;
    1097             : }
    1098             : 
    1099         171 : XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
    1100             : {
    1101         171 :     pImpXPolyPolygon = new ImpXPolyPolygon();
    1102             : 
    1103         404 :     for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
    1104             :     {
    1105         233 :         basegfx::B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
    1106         466 :         XPolygon aNewPoly(aCandidate);
    1107         233 :         Insert(aNewPoly);
    1108         233 :     }
    1109         171 : }
    1110             : 
    1111             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11