LCOV - code coverage report
Current view: top level - svx/source/xoutdev - _xpoly.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 249 591 42.1 %
Date: 2014-04-11 Functions: 35 63 55.6 %
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        1109 : ImpXPolygon::ImpXPolygon(sal_uInt16 nInitSize, sal_uInt16 _nResize)
      38             :     : pPointAry(NULL)
      39             :     , pFlagAry(NULL)
      40             :     , pOldPointAry(NULL)
      41             :     , bDeleteOldPoints(sal_False)
      42             :     , nSize(0)
      43             :     , nResize(_nResize)
      44             :     , nPoints(0)
      45        1109 :     , nRefCount(1)
      46             : {
      47        1109 :     Resize(nInitSize);
      48        1109 : }
      49             : 
      50           2 : ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
      51             :     : pPointAry(NULL)
      52             :     , pFlagAry(NULL)
      53             :     , pOldPointAry(NULL)
      54             :     , bDeleteOldPoints(sal_False)
      55             :     , nSize(0)
      56             :     , nResize(rImpXPoly.nResize)
      57             :     , nPoints(0)
      58           2 :     , nRefCount(1)
      59             : {
      60           2 :     ( (ImpXPolygon&) rImpXPoly ).CheckPointDelete();
      61             : 
      62           2 :     Resize( rImpXPoly.nSize );
      63             : 
      64             :     // copy
      65           2 :     nPoints = rImpXPoly.nPoints;
      66           2 :     memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
      67           2 :     memcpy( pFlagAry, rImpXPoly.pFlagAry, nSize );
      68           2 : }
      69             : 
      70        1111 : ImpXPolygon::~ImpXPolygon()
      71             : {
      72        1111 :     delete[] (char*) pPointAry;
      73        1111 :     delete[] pFlagAry;
      74        1111 :     if ( bDeleteOldPoints )
      75           0 :         delete[] (char*) pOldPointAry;
      76        1111 : }
      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        1111 : void ImpXPolygon::Resize( sal_uInt16 nNewSize, sal_Bool bDeletePoints )
      95             : {
      96        1111 :     if( nNewSize == nSize )
      97        1111 :         return;
      98             : 
      99        1111 :     sal_uInt8*   pOldFlagAry  = pFlagAry;
     100        1111 :     sal_uInt16  nOldSize     = nSize;
     101             : 
     102        1111 :     CheckPointDelete();
     103        1111 :     pOldPointAry = pPointAry;
     104             : 
     105             :     // Round the new size to a multiple of nResize, if
     106             :     // the object was not newly created (nSize != 0)
     107        1111 :     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        1111 :     nSize     = nNewSize;
     114        1111 :     pPointAry = (Point*)new char[ nSize*sizeof( Point ) ];
     115        1111 :     memset( pPointAry, 0, nSize*sizeof( Point ) );
     116             : 
     117             :     // create flag array
     118        1111 :     pFlagAry = new sal_uInt8[ nSize ];
     119        1111 :     memset( pFlagAry, 0, nSize );
     120             : 
     121             :     // copy if needed
     122        1111 :     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[] (char*) pOldPointAry;
     139           0 :         else                    bDeleteOldPoints = sal_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          60 : void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
     170             : {
     171          60 :     CheckPointDelete();
     172             : 
     173          60 :     if( (nPos + nCount) <= nPoints )
     174             :     {
     175          60 :         sal_uInt16 nMove = nPoints - nPos - nCount;
     176             : 
     177          60 :         if( nMove )
     178             :         {
     179           8 :             memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
     180          12 :                      nMove * sizeof(Point) );
     181           4 :             memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
     182             :         }
     183          60 :         memset( &pPointAry[nPoints - nCount], 0, nCount * sizeof( Point ) );
     184          60 :         memset( &pFlagAry [nPoints - nCount], 0, nCount );
     185          60 :         nPoints = nPoints - nCount;
     186             :     }
     187          60 : }
     188             : 
     189         989 : XPolygon::XPolygon( sal_uInt16 nSize, sal_uInt16 nResize )
     190             : {
     191         989 :     pImpXPolygon = new ImpXPolygon( nSize, nResize );
     192         989 : }
     193             : 
     194         967 : XPolygon::XPolygon( const XPolygon& rXPoly )
     195             : {
     196         967 :     pImpXPolygon = rXPoly.pImpXPolygon;
     197         967 :     pImpXPolygon->nRefCount++;
     198         967 : }
     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           6 : XPolygon::XPolygon(const Rectangle& rRect, long nRx, long nRy)
     217             : {
     218           6 :     pImpXPolygon = new ImpXPolygon(17);
     219           6 :     long nWh = (rRect.GetWidth()  - 1) / 2;
     220           6 :     long nHh = (rRect.GetHeight() - 1) / 2;
     221             : 
     222           6 :     if ( nRx > nWh )    nRx = nWh;
     223           6 :     if ( nRy > nHh )    nRy = nHh;
     224             : 
     225             :     // negate Rx => circle clockwise
     226           6 :     nRx = -nRx;
     227             : 
     228             :     // factor for control points of the Bézier curve: 8/3 * (sin(45g) - 0.5)
     229           6 :     long    nXHdl = (long)(0.552284749 * nRx);
     230           6 :     long    nYHdl = (long)(0.552284749 * nRy);
     231           6 :     sal_uInt16  nPos = 0;
     232             : 
     233           6 :     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           4 :         pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
     267           4 :         pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
     268           4 :         pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
     269           4 :         pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
     270             :     }
     271           6 :     pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
     272           6 :     pImpXPolygon->nPoints = nPos + 1;
     273           6 : }
     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 :     sal_Bool    bLoopEnd = sal_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             :     } 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        2076 : XPolygon::~XPolygon()
     317             : {
     318        2076 :     if( pImpXPolygon->nRefCount > 1 )
     319        1080 :         pImpXPolygon->nRefCount--;
     320             :     else
     321         996 :         delete pImpXPolygon;
     322        2076 : }
     323             : 
     324             : /// check reference counter and decouple if > 1
     325        2709 : void XPolygon::CheckReference()
     326             : {
     327        2709 :     if( pImpXPolygon->nRefCount > 1 )
     328             :     {
     329           2 :         pImpXPolygon->nRefCount--;
     330           2 :         pImpXPolygon = new ImpXPolygon( *pImpXPolygon );
     331             :     }
     332        2709 : }
     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         643 : sal_uInt16 XPolygon::GetPointCount() const
     358             : {
     359         643 :     pImpXPolygon->CheckPointDelete();
     360         643 :     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          60 : void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
     390             : {
     391          60 :     CheckReference();
     392          60 :     pImpXPolygon->Remove( nPos, nCount );
     393          60 : }
     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          90 : Rectangle XPolygon::GetBoundRect() const
     413             : {
     414          90 :     pImpXPolygon->CheckPointDelete();
     415          90 :     Rectangle aRetval;
     416             : 
     417          90 :     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          89 :         const basegfx::B2DRange aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
     426             :         aRetval = Rectangle(
     427             :             FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
     428          89 :             FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
     429             :     }
     430             : 
     431          90 :     return aRetval;
     432             : }
     433             : 
     434         695 : const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
     435             : {
     436             :     DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
     437             : 
     438         695 :     pImpXPolygon->CheckPointDelete();
     439         695 :     return pImpXPolygon->pPointAry[nPos];
     440             : }
     441             : 
     442        2415 : Point& XPolygon::operator[]( sal_uInt16 nPos )
     443             : {
     444        2415 :     pImpXPolygon->CheckPointDelete();
     445        2415 :     CheckReference();
     446             : 
     447        2415 :     if( nPos >= pImpXPolygon->nSize )
     448             :     {
     449             :         DBG_ASSERT(pImpXPolygon->nResize, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
     450           0 :         pImpXPolygon->Resize(nPos + 1, sal_False);
     451             :     }
     452        2415 :     if( nPos >= pImpXPolygon->nPoints )
     453        1752 :         pImpXPolygon->nPoints = nPos + 1;
     454             : 
     455        2415 :     return pImpXPolygon->pPointAry[nPos];
     456             : }
     457             : 
     458         115 : XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
     459             : {
     460         115 :     pImpXPolygon->CheckPointDelete();
     461             : 
     462         115 :     rXPoly.pImpXPolygon->nRefCount++;
     463             : 
     464         115 :     if( pImpXPolygon->nRefCount > 1 )
     465           0 :         pImpXPolygon->nRefCount--;
     466             :     else
     467         115 :         delete pImpXPolygon;
     468             : 
     469         115 :     pImpXPolygon = rXPoly.pImpXPolygon;
     470         115 :     return *this;
     471             : }
     472             : 
     473           0 : bool XPolygon::operator==( const XPolygon& rXPoly ) const
     474             : {
     475           0 :     pImpXPolygon->CheckPointDelete();
     476           0 :     if (rXPoly.pImpXPolygon==pImpXPolygon) return true;
     477           0 :     return *rXPoly.pImpXPolygon == *pImpXPolygon;
     478             : }
     479             : 
     480           0 : bool XPolygon::operator!=( const XPolygon& rXPoly ) const
     481             : {
     482           0 :     pImpXPolygon->CheckPointDelete();
     483           0 :     if (rXPoly.pImpXPolygon==pImpXPolygon) return false;
     484           0 :     return *rXPoly.pImpXPolygon != *pImpXPolygon;
     485             : }
     486             : 
     487             : /// get the flags for the point at the given position
     488        1263 : XPolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
     489             : {
     490        1263 :     pImpXPolygon->CheckPointDelete();
     491        1263 :     return (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
     492             : }
     493             : 
     494             : /// set the flags for the point at the given position
     495          64 : void XPolygon::SetFlags( sal_uInt16 nPos, XPolyFlags eFlags )
     496             : {
     497          64 :     pImpXPolygon->CheckPointDelete();
     498          64 :     CheckReference();
     499          64 :     pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) eFlags;
     500          64 : }
     501             : 
     502             : /// short path to read the CONTROL flag directly (TODO: better explain what the sense behind this flag is!)
     503           0 : bool XPolygon::IsControl(sal_uInt16 nPos) const
     504             : {
     505           0 :     return ( (XPolyFlags) pImpXPolygon->pFlagAry[nPos] == XPOLY_CONTROL );
     506             : }
     507             : 
     508             : /// short path to read the SMOOTH and SYMMTR flag directly (TODO: better explain what the sense behind these flags is!)
     509           0 : bool XPolygon::IsSmooth(sal_uInt16 nPos) const
     510             : {
     511           0 :     XPolyFlags eFlag = (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
     512           0 :     return ( eFlag == XPOLY_SMOOTH || eFlag == XPOLY_SYMMTR );
     513             : }
     514             : 
     515             : /** calculate the euclidean distance between two points
     516             :  *
     517             :  * @param nP1 The first point
     518             :  * @param nP2 The second point
     519             :  */
     520           0 : double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
     521             : {
     522           0 :     const Point& rP1 = pImpXPolygon->pPointAry[nP1];
     523           0 :     const Point& rP2 = pImpXPolygon->pPointAry[nP2];
     524           0 :     double fDx = rP2.X() - rP1.X();
     525           0 :     double fDy = rP2.Y() - rP1.Y();
     526           0 :     return sqrt(fDx * fDx + fDy * fDy);
     527             : }
     528             : 
     529           0 : void XPolygon::SubdivideBezier(sal_uInt16 nPos, bool bCalcFirst, double fT)
     530             : {
     531           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     532           0 :     double  fT2 = fT * fT;
     533           0 :     double  fT3 = fT * fT2;
     534           0 :     double  fU = 1.0 - fT;
     535           0 :     double  fU2 = fU * fU;
     536           0 :     double  fU3 = fU * fU2;
     537           0 :     sal_uInt16  nIdx = nPos;
     538             :     short   nPosInc, nIdxInc;
     539             : 
     540           0 :     if ( bCalcFirst )
     541             :     {
     542           0 :         nPos += 3;
     543           0 :         nPosInc = -1;
     544           0 :         nIdxInc = 0;
     545             :     }
     546             :     else
     547             :     {
     548           0 :         nPosInc = 1;
     549           0 :         nIdxInc = 1;
     550             :     }
     551           0 :     pPoints[nPos].X() = (long) (fU3 *       pPoints[nIdx  ].X() +
     552           0 :                                 fT  * fU2 * pPoints[nIdx+1].X() * 3 +
     553           0 :                                 fT2 * fU  * pPoints[nIdx+2].X() * 3 +
     554           0 :                                 fT3 *       pPoints[nIdx+3].X());
     555           0 :     pPoints[nPos].Y() = (long) (fU3 *       pPoints[nIdx  ].Y() +
     556           0 :                                 fT  * fU2 * pPoints[nIdx+1].Y() * 3 +
     557           0 :                                 fT2 * fU  * pPoints[nIdx+2].Y() * 3 +
     558           0 :                                 fT3 *       pPoints[nIdx+3].Y());
     559           0 :     nPos = nPos + nPosInc;
     560           0 :     nIdx = nIdx + nIdxInc;
     561           0 :     pPoints[nPos].X() = (long) (fU2 *       pPoints[nIdx  ].X() +
     562           0 :                                 fT  * fU *  pPoints[nIdx+1].X() * 2 +
     563           0 :                                 fT2 *       pPoints[nIdx+2].X());
     564           0 :     pPoints[nPos].Y() = (long) (fU2 *       pPoints[nIdx  ].Y() +
     565           0 :                                 fT  * fU *  pPoints[nIdx+1].Y() * 2 +
     566           0 :                                 fT2 *       pPoints[nIdx+2].Y());
     567           0 :     nPos = nPos + nPosInc;
     568           0 :     nIdx = nIdx + nIdxInc;
     569           0 :     pPoints[nPos].X() = (long) (fU * pPoints[nIdx  ].X() +
     570           0 :                                 fT * pPoints[nIdx+1].X());
     571           0 :     pPoints[nPos].Y() = (long) (fU * pPoints[nIdx  ].Y() +
     572           0 :                                 fT * pPoints[nIdx+1].Y());
     573           0 : }
     574             : 
     575             : /// Generate a Bézier arc
     576           8 : void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
     577             :                          long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
     578             :                          sal_uInt16 nQuad, sal_uInt16 nFirst)
     579             : {
     580           8 :     Point* pPoints = pImpXPolygon->pPointAry;
     581           8 :     pPoints[nFirst  ] = rCenter;
     582           8 :     pPoints[nFirst+3] = rCenter;
     583             : 
     584           8 :     if ( nQuad == 1 || nQuad == 2 )
     585             :     {
     586           4 :         nRx   = -nRx; nXHdl = -nXHdl;
     587             :     }
     588           8 :     if ( nQuad == 0 || nQuad == 1 )
     589             :     {
     590           4 :         nRy   = -nRy; nYHdl = -nYHdl;
     591             :     }
     592             : 
     593           8 :     if ( nQuad == 0 || nQuad == 2 )
     594             :     {
     595           4 :         pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
     596             :     }
     597             :     else
     598             :     {
     599           4 :         pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
     600             :     }
     601           8 :     pPoints[nFirst+1] = pPoints[nFirst];
     602           8 :     pPoints[nFirst+2] = pPoints[nFirst+3];
     603             : 
     604           8 :     if ( nQuad == 0 || nQuad == 2 )
     605             :     {
     606           4 :         pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
     607             :     }
     608             :     else
     609             :     {
     610           4 :         pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
     611             :     }
     612           8 :     if ( nStart > 0 )
     613           0 :         SubdivideBezier(nFirst, false, (double)nStart / 900);
     614           8 :     if ( nEnd < 900 )
     615           0 :         SubdivideBezier(nFirst, true, (double)(nEnd-nStart) / (900-nStart));
     616           8 :     SetFlags(nFirst+1, XPOLY_CONTROL);
     617           8 :     SetFlags(nFirst+2, XPOLY_CONTROL);
     618           8 : }
     619             : 
     620           0 : bool XPolygon::CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2)
     621             : {
     622           0 :     if ( nStart == 3600 ) nStart = 0;
     623           0 :     if ( nEnd == 0 ) nEnd = 3600;
     624           0 :     sal_uInt16 nStPrev = nStart;
     625           0 :     sal_uInt16 nMax = (nStart / 900 + 1) * 900;
     626           0 :     sal_uInt16 nMin = nMax - 900;
     627             : 
     628           0 :     if ( nEnd >= nMax || nEnd <= nStart )   nA2 = 900;
     629           0 :     else                                    nA2 = nEnd - nMin;
     630           0 :     nA1 = nStart - nMin;
     631           0 :     nStart = nMax;
     632             : 
     633             :     // returns true when the last segment was calculated
     634           0 :     return (nStPrev < nEnd && nStart >= nEnd);
     635             : }
     636             : 
     637             : /** Calculate a smooth transition to connect two Bézier curves
     638             :  *
     639             :  * This is done by projecting the corresponding point onto a line between
     640             :  * two other points.
     641             :  *
     642             :  * @param nCenter The point at the end or beginning of the curve.
     643             :  *                If nCenter is at the end of the polygon the point is moved
     644             :  *                to the opposite side.
     645             :  * @param nDrag The moved point that specifies the relocation.
     646             :  * @param nPnt The point to modify.
     647             :  */
     648           0 : void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 nPnt)
     649             : {
     650           0 :     CheckReference();
     651             : 
     652             :     // If nPoint is no control point, i.e. cannot be moved, than
     653             :     // move nDrag instead on the line between nCenter and nPnt
     654           0 :     if ( !IsControl(nPnt) )
     655             :     {
     656           0 :         sal_uInt16 nTmp = nDrag;
     657           0 :         nDrag = nPnt;
     658           0 :         nPnt = nTmp;
     659             :     }
     660           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     661           0 :     Point   aDiff   = pPoints[nDrag] - pPoints[nCenter];
     662           0 :     double  fDiv    = CalcDistance(nCenter, nDrag);
     663             : 
     664           0 :     if ( fDiv )
     665             :     {
     666           0 :         double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
     667             :         // keep the length if SMOOTH
     668           0 :         if ( GetFlags(nCenter) == XPOLY_SMOOTH || !IsControl(nDrag) )
     669             :         {
     670           0 :             aDiff.X() = (long) (fRatio * aDiff.X());
     671           0 :             aDiff.Y() = (long) (fRatio * aDiff.Y());
     672             :         }
     673           0 :         pPoints[nPnt] = pPoints[nCenter] - aDiff;
     674             :     }
     675           0 : }
     676             : 
     677             : /** Calculate tangent between two Bézier curves
     678             :  *
     679             :  * @param nCenter start or end point of the curves
     680             :  * @param nPrev previous reference point
     681             :  * @param nNext next reference point
     682             :  */
     683           0 : void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNext)
     684             : {
     685           0 :     CheckReference();
     686             : 
     687           0 :     double fAbsLen = CalcDistance(nNext, nPrev);
     688             : 
     689           0 :     if ( fAbsLen )
     690             :     {
     691           0 :         const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
     692           0 :         Point&  rNext = pImpXPolygon->pPointAry[nNext];
     693           0 :         Point&  rPrev = pImpXPolygon->pPointAry[nPrev];
     694           0 :         Point   aDiff = rNext - rPrev;
     695           0 :         double  fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
     696           0 :         double  fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
     697             : 
     698             :         // same length for both sides if SYMMTR
     699           0 :         if ( GetFlags(nCenter) == XPOLY_SYMMTR )
     700             :         {
     701           0 :             fPrevLen = (fNextLen + fPrevLen) / 2;
     702           0 :             fNextLen = fPrevLen;
     703             :         }
     704           0 :         rNext.X() = rCenter.X() + (long) (fNextLen * aDiff.X());
     705           0 :         rNext.Y() = rCenter.Y() + (long) (fNextLen * aDiff.Y());
     706           0 :         rPrev.X() = rCenter.X() - (long) (fPrevLen * aDiff.X());
     707           0 :         rPrev.Y() = rCenter.Y() - (long) (fPrevLen * aDiff.Y());
     708             :     }
     709           0 : }
     710             : 
     711             : /// convert four polygon points into a Bézier curve
     712           0 : void XPolygon::PointsToBezier(sal_uInt16 nFirst)
     713             : {
     714             :     double  nFullLength, nPart1Length, nPart2Length;
     715             :     double  fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
     716             :     double  fTx1, fTx2, fTy1, fTy2;
     717             :     double  fT1, fU1, fT2, fU2, fV;
     718           0 :     Point*  pPoints = pImpXPolygon->pPointAry;
     719             : 
     720           0 :     if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
     721           0 :          IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
     722           0 :         return;
     723             : 
     724           0 :     CheckReference();
     725             : 
     726           0 :     fTx1 = pPoints[nFirst+1].X();
     727           0 :     fTy1 = pPoints[nFirst+1].Y();
     728           0 :     fTx2 = pPoints[nFirst+2].X();
     729           0 :     fTy2 = pPoints[nFirst+2].Y();
     730           0 :     fX0  = pPoints[nFirst  ].X();
     731           0 :     fY0  = pPoints[nFirst  ].Y();
     732           0 :     fX3  = pPoints[nFirst+3].X();
     733           0 :     fY3  = pPoints[nFirst+3].Y();
     734             : 
     735           0 :     nPart1Length = CalcDistance(nFirst, nFirst+1);
     736           0 :     nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
     737           0 :     nFullLength  = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
     738           0 :     if ( nFullLength < 20 )
     739           0 :         return;
     740             : 
     741           0 :     if ( nPart2Length == nFullLength )
     742           0 :         nPart2Length -= 1;
     743           0 :     if ( nPart1Length == nFullLength )
     744           0 :         nPart1Length = nPart2Length - 1;
     745           0 :     if ( nPart1Length <= 0 )
     746           0 :         nPart1Length = 1;
     747           0 :     if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
     748           0 :         nPart2Length = nPart1Length + 1;
     749             : 
     750           0 :     fT1 = nPart1Length / nFullLength;
     751           0 :     fU1 = 1.0 - fT1;
     752           0 :     fT2 = nPart2Length / nFullLength;
     753           0 :     fU2 = 1.0 - fT2;
     754           0 :     fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
     755             : 
     756           0 :     fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
     757           0 :     fX1 /= fV;
     758           0 :     fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
     759           0 :     fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
     760             : 
     761           0 :     fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
     762           0 :     fY1 /= fV;
     763           0 :     fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
     764           0 :     fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
     765             : 
     766           0 :     fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
     767           0 :     fX2 -= fX1 * fU2 / fT2;
     768           0 :     fX2 -= fX3 * fT2 / (fU2 * 3);
     769             : 
     770           0 :     fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
     771           0 :     fY2 -= fY1 * fU2 / fT2;
     772           0 :     fY2 -= fY3 * fT2 / (fU2 * 3);
     773             : 
     774           0 :     pPoints[nFirst+1] = Point((long) fX1, (long) fY1);
     775           0 :     pPoints[nFirst+2] = Point((long) fX2, (long) fY2);
     776           0 :     SetFlags(nFirst+1, XPOLY_CONTROL);
     777           0 :     SetFlags(nFirst+2, XPOLY_CONTROL);
     778             : }
     779             : 
     780             : /// scale in X- and/or Y-direction
     781           0 : void XPolygon::Scale(double fSx, double fSy)
     782             : {
     783           0 :     pImpXPolygon->CheckPointDelete();
     784           0 :     CheckReference();
     785             : 
     786           0 :     sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
     787             : 
     788           0 :     for (sal_uInt16 i = 0; i < nPntCnt; i++)
     789             :     {
     790           0 :         Point& rPnt = pImpXPolygon->pPointAry[i];
     791           0 :         rPnt.X() = (long)(fSx * rPnt.X());
     792           0 :         rPnt.Y() = (long)(fSy * rPnt.Y());
     793             :     }
     794           0 : }
     795             : 
     796             : /**
     797             :  * Distort a polygon by scaling its coordinates relative to a reference
     798             :  * rectangle into an arbitrary rectangle.
     799             :  *
     800             :  * Mapping between polygon corners and reference rectangle:
     801             :  *     0: top left     0----1
     802             :  *     1: top right    |    |
     803             :  *     2: bottom right 3----2
     804             :  *     3: bottom left
     805             :  */
     806           0 : void XPolygon::Distort(const Rectangle& rRefRect,
     807             :                        const XPolygon& rDistortedRect)
     808             : {
     809           0 :     pImpXPolygon->CheckPointDelete();
     810           0 :     CheckReference();
     811             : 
     812             :     long    Xr, Wr;
     813             :     long    Yr, Hr;
     814             : 
     815           0 :     Xr = rRefRect.Left();
     816           0 :     Yr = rRefRect.Top();
     817           0 :     Wr = rRefRect.GetWidth();
     818           0 :     Hr = rRefRect.GetHeight();
     819             : 
     820           0 :     if ( Wr && Hr )
     821             :     {
     822             :         long    X1, X2, X3, X4;
     823             :         long    Y1, Y2, Y3, Y4;
     824             :         DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
     825             :                    "Distort: rectangle to small");
     826             : 
     827           0 :         X1 = rDistortedRect[0].X();
     828           0 :         Y1 = rDistortedRect[0].Y();
     829           0 :         X2 = rDistortedRect[1].X();
     830           0 :         Y2 = rDistortedRect[1].Y();
     831           0 :         X3 = rDistortedRect[3].X();
     832           0 :         Y3 = rDistortedRect[3].Y();
     833           0 :         X4 = rDistortedRect[2].X();
     834           0 :         Y4 = rDistortedRect[2].Y();
     835             : 
     836           0 :         sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
     837             : 
     838           0 :         for (sal_uInt16 i = 0; i < nPntCnt; i++)
     839             :         {
     840             :             double  fTx, fTy, fUx, fUy;
     841           0 :             Point& rPnt = pImpXPolygon->pPointAry[i];
     842             : 
     843           0 :             fTx = (double)(rPnt.X() - Xr) / Wr;
     844           0 :             fTy = (double)(rPnt.Y() - Yr) / Hr;
     845           0 :             fUx = 1.0 - fTx;
     846           0 :             fUy = 1.0 - fTy;
     847             : 
     848           0 :             rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) +
     849           0 :                                 fTy * (fUx * X3 + fTx * X4) );
     850           0 :             rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) +
     851           0 :                                 fTx * (fUy * Y2 + fTy * Y4) );
     852             :         }
     853             :     }
     854           0 : }
     855             : 
     856         155 : basegfx::B2DPolygon XPolygon::getB2DPolygon() const
     857             : {
     858             :     // #i74631# use tools Polygon class for conversion to not have the code doubled
     859             :     // here. This needs one more conversion but avoids different convertors in
     860             :     // the long run
     861             :     DBG_ASSERT(pImpXPolygon != 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
     862         155 :     const Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry);
     863             : 
     864         155 :     return aSource.getB2DPolygon();
     865             : }
     866             : 
     867         113 : XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
     868             : {
     869             :     // #i74631# use tools Polygon class for conversion to not have the code doubled
     870             :     // here. This needs one more conversion but avoids different convertors in
     871             :     // the long run
     872             : 
     873         113 :     const Polygon aSource(rPolygon);
     874         113 :     sal_uInt16 nSize = aSource.GetSize();
     875         113 :     pImpXPolygon = new ImpXPolygon( nSize );
     876         113 :     pImpXPolygon->nPoints = nSize;
     877             : 
     878        1755 :     for( sal_uInt16 i = 0; i < nSize;  i++ )
     879             :     {
     880        1642 :         pImpXPolygon->pPointAry[i] = aSource[i];
     881        1642 :         pImpXPolygon->pFlagAry[i] = (sal_uInt8) aSource.GetFlags( i );
     882         113 :     }
     883         113 : }
     884             : 
     885             : // XPolyPolygon
     886             : 
     887           0 : ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon& rImpXPolyPoly ) :
     888           0 :                      aXPolyList( rImpXPolyPoly.aXPolyList )
     889             : {
     890           0 :     nRefCount = 1;
     891             : 
     892             :     // duplicate elements
     893           0 :     for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
     894           0 :         aXPolyList[ i ] = new XPolygon( *aXPolyList[ i ] );
     895           0 : }
     896             : 
     897         156 : ImpXPolyPolygon::~ImpXPolyPolygon()
     898             : {
     899         179 :     for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
     900         101 :         delete aXPolyList[ i ];
     901          78 :     aXPolyList.clear();
     902          78 : }
     903             : 
     904           0 : bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon& rImpXPolyPoly) const
     905             : {
     906           0 :     size_t nAnz = aXPolyList.size();
     907           0 :     const XPolygonList& rCmpList = rImpXPolyPoly.aXPolyList;
     908           0 :     if ( nAnz != rCmpList.size() ) return false;
     909           0 :     bool bEq=true;
     910           0 :     for ( size_t i = nAnz; i > 0 && bEq; )
     911             :     {
     912           0 :         i--;
     913           0 :         bEq = ( *aXPolyList[ i ] == *rCmpList[ i ] );
     914             :     }
     915           0 :     return bEq;
     916             : }
     917             : 
     918           3 : XPolyPolygon::XPolyPolygon( sal_uInt16 /*nInitSize*/, sal_uInt16 /*nResize*/ )
     919             : {
     920           3 :     pImpXPolyPolygon = new ImpXPolyPolygon();
     921           3 : }
     922             : 
     923           0 : XPolyPolygon::XPolyPolygon( const XPolyPolygon& rXPolyPoly )
     924             : {
     925           0 :     pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
     926           0 :     pImpXPolyPolygon->nRefCount++;
     927           0 : }
     928             : 
     929          78 : XPolyPolygon::~XPolyPolygon()
     930             : {
     931          78 :     if( pImpXPolyPolygon->nRefCount > 1 )
     932           3 :         pImpXPolyPolygon->nRefCount--;
     933             :     else
     934          75 :         delete pImpXPolyPolygon;
     935          78 : }
     936             : 
     937             : /// check reference counter and decouple if > 1
     938         101 : void XPolyPolygon::CheckReference()
     939             : {
     940         101 :     if( pImpXPolyPolygon->nRefCount > 1 )
     941             :     {
     942           0 :         pImpXPolyPolygon->nRefCount--;
     943           0 :         pImpXPolyPolygon = new ImpXPolyPolygon( *pImpXPolyPolygon );
     944             :     }
     945         101 : }
     946             : 
     947         101 : void XPolyPolygon::Insert( const XPolygon& rXPoly, sal_uInt16 nPos )
     948             : {
     949         101 :     CheckReference();
     950         101 :     XPolygon* pXPoly = new XPolygon( rXPoly );
     951         101 :     if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
     952             :     {
     953           0 :         XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
     954           0 :         ::std::advance( it, nPos );
     955           0 :         pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
     956             :     }
     957             :     else
     958         101 :         pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
     959         101 : }
     960             : 
     961             : /// insert all XPolygons of a XPolyPolygon
     962           0 : void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly, sal_uInt16 nPos )
     963             : {
     964           0 :     CheckReference();
     965             : 
     966           0 :     for ( size_t i = 0; i < rXPolyPoly.Count(); i++)
     967             :     {
     968           0 :         XPolygon* pXPoly = new XPolygon( rXPolyPoly[i] );
     969             : 
     970           0 :         if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
     971             :         {
     972           0 :             XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
     973           0 :             ::std::advance( it, nPos );
     974           0 :             pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
     975           0 :             nPos++;
     976             :         }
     977             :         else
     978           0 :             pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
     979             :     }
     980           0 : }
     981             : 
     982           0 : XPolygon XPolyPolygon::Remove( sal_uInt16 nPos )
     983             : {
     984           0 :     CheckReference();
     985           0 :     XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
     986           0 :     ::std::advance( it, nPos );
     987           0 :     XPolygon* pTmpXPoly = *it;
     988           0 :     pImpXPolyPolygon->aXPolyList.erase( it );
     989           0 :     XPolygon  aXPoly( *pTmpXPoly );
     990           0 :     delete pTmpXPoly;
     991           0 :     return aXPoly;
     992             : }
     993             : 
     994          86 : const XPolygon& XPolyPolygon::GetObject( sal_uInt16 nPos ) const
     995             : {
     996          86 :     return *(pImpXPolyPolygon->aXPolyList[ nPos ]);
     997             : }
     998             : 
     999           0 : void XPolyPolygon::Clear()
    1000             : {
    1001           0 :     if ( pImpXPolyPolygon->nRefCount > 1 )
    1002             :     {
    1003           0 :         pImpXPolyPolygon->nRefCount--;
    1004           0 :         pImpXPolyPolygon = new ImpXPolyPolygon();
    1005             :     }
    1006             :     else
    1007             :     {
    1008           0 :         for( size_t i = 0, n = pImpXPolyPolygon->aXPolyList.size(); i < n; ++i )
    1009           0 :             delete pImpXPolyPolygon->aXPolyList[ i ];
    1010           0 :         pImpXPolyPolygon->aXPolyList.clear();
    1011             :     }
    1012           0 : }
    1013             : 
    1014          72 : sal_uInt16 XPolyPolygon::Count() const
    1015             : {
    1016          72 :     return (sal_uInt16)(pImpXPolyPolygon->aXPolyList.size());
    1017             : }
    1018             : 
    1019           3 : Rectangle XPolyPolygon::GetBoundRect() const
    1020             : {
    1021           3 :     size_t nXPoly = pImpXPolyPolygon->aXPolyList.size();
    1022           3 :     Rectangle aRect;
    1023             : 
    1024          18 :     for ( size_t n = 0; n < nXPoly; n++ )
    1025             :     {
    1026          15 :         const XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList[ n ];
    1027          15 :         aRect.Union( pXPoly->GetBoundRect() );
    1028             :     }
    1029             : 
    1030           3 :     return aRect;
    1031             : }
    1032             : 
    1033           0 : XPolygon& XPolyPolygon::operator[]( sal_uInt16 nPos )
    1034             : {
    1035           0 :     CheckReference();
    1036           0 :     return *( pImpXPolyPolygon->aXPolyList[ nPos ] );
    1037             : }
    1038             : 
    1039           3 : XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& rXPolyPoly )
    1040             : {
    1041           3 :     rXPolyPoly.pImpXPolyPolygon->nRefCount++;
    1042             : 
    1043           3 :     if( pImpXPolyPolygon->nRefCount > 1 )
    1044           0 :         pImpXPolyPolygon->nRefCount--;
    1045             :     else
    1046           3 :         delete pImpXPolyPolygon;
    1047             : 
    1048           3 :     pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
    1049           3 :     return *this;
    1050             : }
    1051             : 
    1052           0 : bool XPolyPolygon::operator==( const XPolyPolygon& rXPolyPoly ) const
    1053             : {
    1054           0 :     if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return true;
    1055           0 :     return *pImpXPolyPolygon == *rXPolyPoly.pImpXPolyPolygon;
    1056             : }
    1057             : 
    1058           0 : bool XPolyPolygon::operator!=( const XPolyPolygon& rXPolyPoly ) const
    1059             : {
    1060           0 :     if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return false;
    1061           0 :     return *pImpXPolyPolygon != *rXPolyPoly.pImpXPolyPolygon;
    1062             : }
    1063             : 
    1064             : /**
    1065             :  * Distort a polygon by scaling its coordinates relative to a reference
    1066             :  * rectangle into an arbitrary rectangle.
    1067             :  *
    1068             :  * Mapping between polygon corners and reference rectangle:
    1069             :  *     0: top left     0----1
    1070             :  *     1: top right    |    |
    1071             :  *     2: bottom right 3----2
    1072             :  *     3: bottom left
    1073             :  */
    1074           0 : void XPolyPolygon::Distort(const Rectangle& rRefRect,
    1075             :                            const XPolygon& rDistortedRect)
    1076             : {
    1077           0 :     CheckReference();
    1078             : 
    1079           0 :     for (size_t i = 0; i < Count(); i++)
    1080           0 :         pImpXPolyPolygon->aXPolyList[ i ]->Distort(rRefRect, rDistortedRect);
    1081           0 : }
    1082             : 
    1083           0 : basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
    1084             : {
    1085           0 :     basegfx::B2DPolyPolygon aRetval;
    1086             : 
    1087           0 :     for(sal_uInt16 a(0L); a < Count(); a++)
    1088             :     {
    1089           0 :         const XPolygon& rPoly = (*this)[a];
    1090           0 :         aRetval.append(rPoly.getB2DPolygon());
    1091             :     }
    1092             : 
    1093           0 :     return aRetval;
    1094             : }
    1095             : 
    1096          75 : XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
    1097             : {
    1098          75 :     pImpXPolyPolygon = new ImpXPolyPolygon();
    1099             : 
    1100         176 :     for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
    1101             :     {
    1102         101 :         basegfx::B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
    1103         202 :         XPolygon aNewPoly(aCandidate);
    1104         101 :         Insert(aNewPoly);
    1105         101 :     }
    1106          75 : }
    1107             : 
    1108             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10