LCOV - code coverage report
Current view: top level - tools/source/generic - poly.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 593 914 64.9 %
Date: 2014-04-11 Functions: 50 75 66.7 %
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/bigint.hxx>
      22             : #include <tools/debug.hxx>
      23             : #include <tools/helpers.hxx>
      24             : #include <tools/stream.hxx>
      25             : #include <tools/vcompat.hxx>
      26             : #include <tools/gen.hxx>
      27             : #include <poly.h>
      28             : #include <tools/line.hxx>
      29             : #include <tools/vector2d.hxx>
      30             : #include <tools/poly.hxx>
      31             : #include <basegfx/polygon/b2dpolygon.hxx>
      32             : #include <basegfx/point/b2dpoint.hxx>
      33             : #include <basegfx/vector/b2dvector.hxx>
      34             : #include <basegfx/polygon/b2dpolygontools.hxx>
      35             : #include <basegfx/curve/b2dcubicbezier.hxx>
      36             : 
      37             : #include <vector>
      38             : #include <iterator>
      39             : #include <algorithm>
      40             : #include <cstring>
      41             : #include <limits.h>
      42             : #include <cmath>
      43             : 
      44             : #define EDGE_LEFT       1
      45             : #define EDGE_TOP        2
      46             : #define EDGE_RIGHT      4
      47             : #define EDGE_BOTTOM     8
      48             : #define EDGE_HORZ       (EDGE_RIGHT | EDGE_LEFT)
      49             : #define EDGE_VERT       (EDGE_TOP | EDGE_BOTTOM)
      50             : #define SMALL_DVALUE    0.0000001
      51             : #define FSQRT2          1.4142135623730950488016887242097
      52             : 
      53             : static ImplPolygonData aStaticImplPolygon =
      54             : {
      55             :     NULL, NULL, 0, 0
      56             : };
      57             : 
      58      483569 : ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, bool bFlags  )
      59             : {
      60      483569 :     if ( nInitSize )
      61             :     {
      62      483563 :         mpPointAry = (Point*)new char[(sal_uIntPtr)nInitSize*sizeof(Point)];
      63      483563 :         memset( mpPointAry, 0, (sal_uIntPtr)nInitSize*sizeof(Point) );
      64             :     }
      65             :     else
      66           6 :         mpPointAry = NULL;
      67             : 
      68      483569 :     if( bFlags )
      69             :     {
      70       15773 :         mpFlagAry = new sal_uInt8[ nInitSize ];
      71       15773 :         memset( mpFlagAry, 0, nInitSize );
      72             :     }
      73             :     else
      74      467796 :         mpFlagAry = NULL;
      75             : 
      76      483569 :     mnRefCount = 1;
      77      483569 :     mnPoints = nInitSize;
      78      483569 : }
      79             : 
      80      218408 : ImplPolygon::ImplPolygon( const ImplPolygon& rImpPoly )
      81             : {
      82      218408 :     if ( rImpPoly.mnPoints )
      83             :     {
      84      211968 :         mpPointAry = (Point*)new char[(sal_uIntPtr)rImpPoly.mnPoints*sizeof(Point)];
      85      211968 :         memcpy( mpPointAry, rImpPoly.mpPointAry, (sal_uIntPtr)rImpPoly.mnPoints*sizeof(Point) );
      86             : 
      87      211968 :         if( rImpPoly.mpFlagAry )
      88             :         {
      89        7329 :             mpFlagAry = new sal_uInt8[ rImpPoly.mnPoints ];
      90        7329 :             memcpy( mpFlagAry, rImpPoly.mpFlagAry, rImpPoly.mnPoints );
      91             :         }
      92             :         else
      93      204639 :             mpFlagAry = NULL;
      94             :     }
      95             :     else
      96             :     {
      97        6440 :         mpPointAry = NULL;
      98        6440 :         mpFlagAry = NULL;
      99             :     }
     100             : 
     101      218408 :     mnRefCount = 1;
     102      218408 :     mnPoints   = rImpPoly.mnPoints;
     103      218408 : }
     104             : 
     105        3507 : ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const sal_uInt8* pInitFlags )
     106             : {
     107        3507 :     if ( nInitSize )
     108             :     {
     109        3507 :         mpPointAry = (Point*)new char[(sal_uIntPtr)nInitSize*sizeof(Point)];
     110        3507 :         memcpy( mpPointAry, pInitAry, (sal_uIntPtr)nInitSize*sizeof( Point ) );
     111             : 
     112        3507 :         if( pInitFlags )
     113             :         {
     114        2432 :             mpFlagAry = new sal_uInt8[ nInitSize ];
     115        2432 :             memcpy( mpFlagAry, pInitFlags, nInitSize );
     116             :         }
     117             :         else
     118        1075 :             mpFlagAry = NULL;
     119             :     }
     120             :     else
     121             :     {
     122           0 :         mpPointAry = NULL;
     123           0 :         mpFlagAry  = NULL;
     124             :     }
     125             : 
     126        3507 :     mnRefCount = 1;
     127        3507 :     mnPoints   = nInitSize;
     128        3507 : }
     129             : 
     130      705423 : ImplPolygon::~ImplPolygon()
     131             : {
     132      705423 :     if ( mpPointAry )
     133             :     {
     134      705408 :         delete[] (char*) mpPointAry;
     135             :     }
     136             : 
     137      705423 :     if( mpFlagAry )
     138       25886 :         delete[] mpFlagAry;
     139      705423 : }
     140             : 
     141       55447 : void ImplPolygon::ImplSetSize( sal_uInt16 nNewSize, bool bResize )
     142             : {
     143       55447 :     if( mnPoints == nNewSize )
     144       55447 :         return;
     145             : 
     146             :     Point* pNewAry;
     147             : 
     148       55447 :     if ( nNewSize )
     149             :     {
     150       55447 :         pNewAry = (Point*)new char[(sal_uIntPtr)nNewSize*sizeof(Point)];
     151             : 
     152       55447 :         if ( bResize )
     153             :         {
     154             :             // Alte Punkte kopieren
     155       55444 :             if ( mnPoints < nNewSize )
     156             :             {
     157             :                 // Neue Punkte mit 0 initialisieren
     158       42044 :                 memset( pNewAry+mnPoints, 0, (sal_uIntPtr)(nNewSize-mnPoints)*sizeof(Point) );
     159       42044 :                 if ( mpPointAry )
     160       35613 :                     memcpy( pNewAry, mpPointAry, mnPoints*sizeof(Point) );
     161             :             }
     162             :             else
     163             :             {
     164       13400 :                 if ( mpPointAry )
     165       13400 :                     memcpy( pNewAry, mpPointAry, (sal_uIntPtr)nNewSize*sizeof(Point) );
     166             :             }
     167             :         }
     168             :     }
     169             :     else
     170           0 :         pNewAry = NULL;
     171             : 
     172       55447 :     if ( mpPointAry )
     173       49016 :         delete[] (char*) mpPointAry;
     174             : 
     175             :     // ggf. FlagArray beruecksichtigen
     176       55447 :     if( mpFlagAry )
     177             :     {
     178             :         sal_uInt8* pNewFlagAry;
     179             : 
     180       14893 :         if( nNewSize )
     181             :         {
     182       14893 :             pNewFlagAry = new sal_uInt8[ nNewSize ];
     183             : 
     184       14893 :             if( bResize )
     185             :             {
     186             :                 // Alte Flags kopieren
     187       14893 :                 if ( mnPoints < nNewSize )
     188             :                 {
     189             :                     // Neue Punkte mit 0 initialisieren
     190        1501 :                     memset( pNewFlagAry+mnPoints, 0, nNewSize-mnPoints );
     191        1501 :                     memcpy( pNewFlagAry, mpFlagAry, mnPoints );
     192             :                 }
     193             :                 else
     194       13392 :                     memcpy( pNewFlagAry, mpFlagAry, nNewSize );
     195             :             }
     196             :         }
     197             :         else
     198           0 :             pNewFlagAry = NULL;
     199             : 
     200       14893 :         delete[] mpFlagAry;
     201       14893 :         mpFlagAry  = pNewFlagAry;
     202             :     }
     203             : 
     204       55447 :     mpPointAry = pNewAry;
     205       55447 :     mnPoints   = nNewSize;
     206             : }
     207             : 
     208       30680 : void ImplPolygon::ImplSplit( sal_uInt16 nPos, sal_uInt16 nSpace, ImplPolygon* pInitPoly )
     209             : {
     210       30680 :     const sal_uIntPtr   nSpaceSize = nSpace * sizeof( Point );
     211             : 
     212             :     //Can't fit this in :-(, throw ?
     213       30680 :     if (mnPoints + nSpace > USHRT_MAX)
     214       30680 :         return;
     215             : 
     216       30680 :     const sal_uInt16    nNewSize = mnPoints + nSpace;
     217             : 
     218       30680 :     if( nPos >= mnPoints )
     219             :     {
     220             :         // Append at the back
     221       28900 :         nPos = mnPoints;
     222       28900 :         ImplSetSize( nNewSize, true );
     223             : 
     224       28900 :         if( pInitPoly )
     225             :         {
     226          21 :             memcpy( mpPointAry + nPos, pInitPoly->mpPointAry, nSpaceSize );
     227             : 
     228          21 :             if( pInitPoly->mpFlagAry )
     229          16 :                 memcpy( mpFlagAry + nPos, pInitPoly->mpFlagAry, nSpace );
     230             :         }
     231             :     }
     232             :     else
     233             :     {
     234        1780 :         const sal_uInt16    nSecPos = nPos + nSpace;
     235        1780 :         const sal_uInt16    nRest = mnPoints - nPos;
     236             : 
     237        1780 :         Point* pNewAry = (Point*) new char[ (sal_uIntPtr) nNewSize * sizeof( Point ) ];
     238             : 
     239        1780 :         memcpy( pNewAry, mpPointAry, nPos * sizeof( Point ) );
     240             : 
     241        1780 :         if( pInitPoly )
     242           0 :             memcpy( pNewAry + nPos, pInitPoly->mpPointAry, nSpaceSize );
     243             :         else
     244        1780 :             memset( pNewAry + nPos, 0, nSpaceSize );
     245             : 
     246        1780 :         memcpy( pNewAry + nSecPos, mpPointAry + nPos, nRest * sizeof( Point ) );
     247        1780 :         delete[] (char*) mpPointAry;
     248             : 
     249             :         // consider FlagArray
     250        1780 :         if( mpFlagAry )
     251             :         {
     252           0 :             sal_uInt8* pNewFlagAry = new sal_uInt8[ nNewSize ];
     253             : 
     254           0 :             memcpy( pNewFlagAry, mpFlagAry, nPos );
     255             : 
     256           0 :             if( pInitPoly && pInitPoly->mpFlagAry )
     257           0 :                 memcpy( pNewFlagAry + nPos, pInitPoly->mpFlagAry, nSpace );
     258             :             else
     259           0 :                 memset( pNewFlagAry + nPos, 0, nSpace );
     260             : 
     261           0 :             memcpy( pNewFlagAry + nSecPos, mpFlagAry + nPos, nRest );
     262           0 :             delete[] mpFlagAry;
     263           0 :             mpFlagAry = pNewFlagAry;
     264             :         }
     265             : 
     266        1780 :         mpPointAry = pNewAry;
     267        1780 :         mnPoints   = nNewSize;
     268             :     }
     269             : }
     270             : 
     271        4551 : void ImplPolygon::ImplCreateFlagArray()
     272             : {
     273        4551 :     if( !mpFlagAry )
     274             :     {
     275         261 :         mpFlagAry = new sal_uInt8[ mnPoints ];
     276         261 :         memset( mpFlagAry, 0, mnPoints );
     277             :     }
     278        4551 : }
     279             : 
     280     8136224 : inline void Polygon::ImplMakeUnique()
     281             : {
     282             :     // copy references if any exist
     283     8136224 :     if ( mpImplPolygon->mnRefCount != 1 )
     284             :     {
     285      218408 :         if ( mpImplPolygon->mnRefCount )
     286      211974 :             mpImplPolygon->mnRefCount--;
     287      218408 :         mpImplPolygon = new ImplPolygon( *mpImplPolygon );
     288             :     }
     289     8136224 : }
     290             : 
     291         936 : inline double ImplGetParameter( const Point& rCenter, const Point& rPt, double fWR, double fHR )
     292             : {
     293         936 :     const long nDX = rPt.X() - rCenter.X();
     294         936 :     double fAngle = atan2( -rPt.Y() + rCenter.Y(), ( ( nDX == 0L ) ? 0.000000001 : nDX ) );
     295             : 
     296         936 :     return atan2(fWR*sin(fAngle), fHR*cos(fAngle));
     297             : }
     298             : 
     299       29661 : Polygon::Polygon()
     300             : {
     301       29661 :     mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
     302       29661 : }
     303             : 
     304      106471 : Polygon::Polygon( sal_uInt16 nSize )
     305             : {
     306             : 
     307      106471 :     if ( nSize )
     308      106468 :         mpImplPolygon = new ImplPolygon( nSize );
     309             :     else
     310           3 :         mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
     311      106471 : }
     312             : 
     313        3507 : Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const sal_uInt8* pFlagAry )
     314             : {
     315             : 
     316        3507 :     if( nPoints )
     317        3507 :         mpImplPolygon = new ImplPolygon( nPoints, pPtAry, pFlagAry );
     318             :     else
     319           0 :         mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
     320        3507 : }
     321             : 
     322     1030814 : Polygon::Polygon( const Polygon& rPoly )
     323             : {
     324             :     DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < 0xFFFFFFFE, "Polygon: RefCount overflow" );
     325             : 
     326     1030814 :     mpImplPolygon = rPoly.mpImplPolygon;
     327     1030814 :     if ( mpImplPolygon->mnRefCount )
     328     1030783 :         mpImplPolygon->mnRefCount++;
     329     1030814 : }
     330             : 
     331       13353 : Polygon::Polygon( const Rectangle& rRect )
     332             : {
     333             : 
     334       13353 :     if ( rRect.IsEmpty() )
     335          84 :         mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
     336             :     else
     337             :     {
     338       13269 :         mpImplPolygon = new ImplPolygon( 5 );
     339       13269 :         mpImplPolygon->mpPointAry[0] = rRect.TopLeft();
     340       13269 :         mpImplPolygon->mpPointAry[1] = rRect.TopRight();
     341       13269 :         mpImplPolygon->mpPointAry[2] = rRect.BottomRight();
     342       13269 :         mpImplPolygon->mpPointAry[3] = rRect.BottomLeft();
     343       13269 :         mpImplPolygon->mpPointAry[4] = rRect.TopLeft();
     344             :     }
     345       13353 : }
     346             : 
     347        3751 : Polygon::Polygon( const Rectangle& rRect, sal_uIntPtr nHorzRound, sal_uIntPtr nVertRound )
     348             : {
     349        3751 :     if ( rRect.IsEmpty() )
     350           0 :         mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
     351             :     else
     352             :     {
     353        3751 :         Rectangle aRect( rRect );
     354        3751 :         aRect.Justify();            // SJ: i9140
     355             : 
     356        3751 :         nHorzRound = std::min( nHorzRound, (sal_uIntPtr) labs( aRect.GetWidth() >> 1 ) );
     357        3751 :         nVertRound = std::min( nVertRound, (sal_uIntPtr) labs( aRect.GetHeight() >> 1 ) );
     358             : 
     359        3751 :         if( !nHorzRound && !nVertRound )
     360             :         {
     361           0 :             mpImplPolygon = new ImplPolygon( 5 );
     362           0 :             mpImplPolygon->mpPointAry[0] = aRect.TopLeft();
     363           0 :             mpImplPolygon->mpPointAry[1] = aRect.TopRight();
     364           0 :             mpImplPolygon->mpPointAry[2] = aRect.BottomRight();
     365           0 :             mpImplPolygon->mpPointAry[3] = aRect.BottomLeft();
     366           0 :             mpImplPolygon->mpPointAry[4] = aRect.TopLeft();
     367             :         }
     368             :         else
     369             :         {
     370        3751 :             const Point     aTL( aRect.Left() + nHorzRound, aRect.Top() + nVertRound );
     371        3751 :             const Point     aTR( aRect.Right() - nHorzRound, aRect.Top() + nVertRound );
     372        3751 :             const Point     aBR( aRect.Right() - nHorzRound, aRect.Bottom() - nVertRound );
     373        3751 :             const Point     aBL( aRect.Left() + nHorzRound, aRect.Bottom() - nVertRound );
     374        3751 :             Polygon*        pEllipsePoly = new Polygon( Point(), nHorzRound, nVertRound );
     375        3751 :             sal_uInt16          i, nEnd, nSize4 = pEllipsePoly->GetSize() >> 2;
     376             : 
     377        3751 :             mpImplPolygon = new ImplPolygon( pEllipsePoly->GetSize() + 1 );
     378             : 
     379        3751 :             const Point*    pSrcAry = pEllipsePoly->GetConstPointAry();
     380        3751 :             Point*          pDstAry = mpImplPolygon->mpPointAry;
     381             : 
     382       33759 :             for( i = 0, nEnd = nSize4; i < nEnd; i++ )
     383       30008 :                 ( pDstAry[ i ] = pSrcAry[ i ] ) += aTR;
     384             : 
     385       33759 :             for( nEnd = nEnd + nSize4; i < nEnd; i++ )
     386       30008 :                 ( pDstAry[ i ] = pSrcAry[ i ] ) += aTL;
     387             : 
     388       33759 :             for( nEnd = nEnd + nSize4; i < nEnd; i++ )
     389       30008 :                 ( pDstAry[ i ] = pSrcAry[ i ] ) += aBL;
     390             : 
     391       33759 :             for( nEnd = nEnd + nSize4; i < nEnd; i++ )
     392       30008 :                 ( pDstAry[ i ] = pSrcAry[ i ] ) += aBR;
     393             : 
     394        3751 :             pDstAry[ nEnd ] = pDstAry[ 0 ];
     395        3751 :             delete pEllipsePoly;
     396             :         }
     397             :     }
     398        3751 : }
     399             : 
     400       14008 : Polygon::Polygon( const Point& rCenter, long nRadX, long nRadY, sal_uInt16 nPoints )
     401             : {
     402       14008 :     if( nRadX && nRadY )
     403             :     {
     404             :         // Compute default (depends on size)
     405       14008 :         if( !nPoints )
     406             :         {
     407       28016 :             nPoints = (sal_uInt16) ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
     408       28016 :                                  sqrt( (double) labs( nRadX * nRadY ) ) ) );
     409             : 
     410       14008 :             nPoints = (sal_uInt16) MinMax( nPoints, 32, 256 );
     411             : 
     412       14008 :             if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
     413           1 :                 nPoints >>= 1;
     414             :         }
     415             : 
     416             :         // Ceil number of points until divisible by four
     417       14008 :         mpImplPolygon = new ImplPolygon( nPoints = (nPoints + 3) & ~3 );
     418             : 
     419             :         Point* pPt;
     420             :         sal_uInt16 i;
     421       14008 :         sal_uInt16 nPoints2 = nPoints >> 1;
     422       14008 :         sal_uInt16 nPoints4 = nPoints >> 2;
     423             :         double nAngle;
     424       14008 :         double nAngleStep = F_PI2 / ( nPoints4 - 1 );
     425             : 
     426      130666 :         for( i=0, nAngle = 0.0; i < nPoints4; i++, nAngle += nAngleStep )
     427             :         {
     428      116658 :             long nX = FRound( nRadX * cos( nAngle ) );
     429      116658 :             long nY = FRound( -nRadY * sin( nAngle ) );
     430             : 
     431      116658 :             pPt = &(mpImplPolygon->mpPointAry[i]);
     432      116658 :             pPt->X() =  nX + rCenter.X();
     433      116658 :             pPt->Y() =  nY + rCenter.Y();
     434      116658 :             pPt = &(mpImplPolygon->mpPointAry[nPoints2-i-1]);
     435      116658 :             pPt->X() = -nX + rCenter.X();
     436      116658 :             pPt->Y() =  nY + rCenter.Y();
     437      116658 :             pPt = &(mpImplPolygon->mpPointAry[i+nPoints2]);
     438      116658 :             pPt->X() = -nX + rCenter.X();
     439      116658 :             pPt->Y() = -nY + rCenter.Y();
     440      116658 :             pPt = &(mpImplPolygon->mpPointAry[nPoints-i-1]);
     441      116658 :             pPt->X() =  nX + rCenter.X();
     442      116658 :             pPt->Y() = -nY + rCenter.Y();
     443       14008 :         }
     444             :     }
     445             :     else
     446           0 :         mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
     447       14008 : }
     448             : 
     449         476 : Polygon::Polygon( const Rectangle& rBound, const Point& rStart, const Point& rEnd,
     450             :                   PolyStyle eStyle, bool bFullCircle )
     451             : {
     452         476 :     const long  nWidth = rBound.GetWidth();
     453         476 :     const long  nHeight = rBound.GetHeight();
     454             : 
     455         476 :     if( ( nWidth > 1 ) && ( nHeight > 1 ) )
     456             :     {
     457         468 :         const Point aCenter( rBound.Center() );
     458         468 :         const long  nRadX = aCenter.X() - rBound.Left();
     459         468 :         const long  nRadY = aCenter.Y() - rBound.Top();
     460             :         sal_uInt16  nPoints;
     461             : 
     462         936 :         nPoints = (sal_uInt16) ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
     463         936 :                              sqrt( (double) labs( nRadX * nRadY ) ) ) );
     464             : 
     465         468 :         nPoints = (sal_uInt16) MinMax( nPoints, 32, 256 );
     466             : 
     467         468 :         if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
     468         468 :             nPoints >>= 1;
     469             : 
     470             :         // compute threshold
     471         468 :         const double    fRadX = nRadX;
     472         468 :         const double    fRadY = nRadY;
     473         468 :         const double    fCenterX = aCenter.X();
     474         468 :         const double    fCenterY = aCenter.Y();
     475         468 :         double          fStart = ImplGetParameter( aCenter, rStart, fRadX, fRadY );
     476         468 :         double          fEnd = ImplGetParameter( aCenter, rEnd, fRadX, fRadY );
     477         468 :         double          fDiff = fEnd - fStart;
     478             :         double          fStep;
     479             :         sal_uInt16      nStart;
     480             :         sal_uInt16      nEnd;
     481             : 
     482         468 :         if( fDiff < 0. )
     483         139 :             fDiff += F_2PI;
     484             : 
     485         468 :         if ( bFullCircle )
     486           0 :             fDiff = F_2PI;
     487             : 
     488             :         // Proportionally shrink number of points( fDiff / (2PI) );
     489         468 :         nPoints = std::max( (sal_uInt16) ( ( fDiff * 0.1591549 ) * nPoints ), (sal_uInt16) 16 );
     490         468 :         fStep = fDiff / ( nPoints - 1 );
     491             : 
     492         468 :         if( POLY_PIE == eStyle )
     493             :         {
     494           0 :             const Point aCenter2( FRound( fCenterX ), FRound( fCenterY ) );
     495             : 
     496           0 :             nStart = 1;
     497           0 :             nEnd = nPoints + 1;
     498           0 :             mpImplPolygon = new ImplPolygon( nPoints + 2 );
     499           0 :             mpImplPolygon->mpPointAry[ 0 ] = aCenter2;
     500           0 :             mpImplPolygon->mpPointAry[ nEnd ] = aCenter2;
     501             :         }
     502             :         else
     503             :         {
     504         468 :             mpImplPolygon = new ImplPolygon( ( POLY_CHORD == eStyle ) ? ( nPoints + 1 ) : nPoints );
     505         468 :             nStart = 0;
     506         468 :             nEnd = nPoints;
     507             :         }
     508             : 
     509       14971 :         for(; nStart < nEnd; nStart++, fStart += fStep )
     510             :         {
     511       14503 :             Point& rPt = mpImplPolygon->mpPointAry[ nStart ];
     512             : 
     513       14503 :             rPt.X() = FRound( fCenterX + fRadX * cos( fStart ) );
     514       14503 :             rPt.Y() = FRound( fCenterY - fRadY * sin( fStart ) );
     515             :         }
     516             : 
     517         468 :         if( POLY_CHORD == eStyle )
     518           0 :             mpImplPolygon->mpPointAry[ nPoints ] = mpImplPolygon->mpPointAry[ 0 ];
     519             :     }
     520             :     else
     521           8 :         mpImplPolygon = (ImplPolygon*) &aStaticImplPolygon;
     522         476 : }
     523             : 
     524           0 : Polygon::Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
     525             :                   const Point& rBezPt2, const Point& rCtrlPt2,
     526             :                   sal_uInt16 nPoints )
     527             : {
     528           0 :     nPoints = ( 0 == nPoints ) ? 25 : ( ( nPoints < 2 ) ? 2 : nPoints );
     529             : 
     530           0 :     const double    fInc = 1.0 / ( nPoints - 1 );
     531           0 :     double          fK_1 = 0.0, fK1_1 = 1.0;
     532             :     double          fK_2, fK_3, fK1_2, fK1_3, fK12, fK21;
     533           0 :     const double    fX0 = rBezPt1.X();
     534           0 :     const double    fY0 = rBezPt1.Y();
     535           0 :     const double    fX1 = 3.0 * rCtrlPt1.X();
     536           0 :     const double    fY1 = 3.0 * rCtrlPt1.Y();
     537           0 :     const double    fX2 = 3.0 * rCtrlPt2.X();
     538           0 :     const double    fY2 = 3.0 * rCtrlPt2.Y();
     539           0 :     const double    fX3 = rBezPt2.X();
     540           0 :     const double    fY3 = rBezPt2.Y();
     541             : 
     542           0 :     mpImplPolygon = new ImplPolygon( nPoints );
     543             : 
     544           0 :     for( sal_uInt16 i = 0; i < nPoints; i++, fK_1 += fInc, fK1_1 -= fInc )
     545             :     {
     546           0 :         Point& rPt = mpImplPolygon->mpPointAry[ i ];
     547             : 
     548           0 :         fK_2 = fK_1, fK_3 = ( fK_2 *= fK_1 ), fK_3 *= fK_1;
     549           0 :         fK1_2 = fK1_1, fK1_3 = ( fK1_2 *= fK1_1 ), fK1_3 *= fK1_1;
     550           0 :         fK12 = fK_1 * fK1_2, fK21 = fK_2 * fK1_1;
     551             : 
     552           0 :         rPt.X() = FRound( fK1_3 * fX0 + fK12 * fX1 + fK21 * fX2 + fK_3 * fX3 );
     553           0 :         rPt.Y() = FRound( fK1_3 * fY0 + fK12 * fY1 + fK21 * fY2 + fK_3 * fY3 );
     554             :     }
     555           0 : }
     556             : 
     557     1546903 : Polygon::~Polygon()
     558             : {
     559             : 
     560             :     // Remove if refcount == 0, otherwise decrement refcount
     561     1546903 :     if ( mpImplPolygon->mnRefCount )
     562             :     {
     563     1545394 :         if ( mpImplPolygon->mnRefCount > 1 )
     564      842370 :             mpImplPolygon->mnRefCount--;
     565             :         else
     566      703024 :             delete mpImplPolygon;
     567             :     }
     568     1546903 : }
     569             : 
     570     2124092 : const Point* Polygon::GetConstPointAry() const
     571             : {
     572     2124092 :     return (Point*)mpImplPolygon->mpPointAry;
     573             : }
     574             : 
     575       70626 : const sal_uInt8* Polygon::GetConstFlagAry() const
     576             : {
     577       70626 :     return mpImplPolygon->mpFlagAry;
     578             : }
     579             : 
     580       18406 : void Polygon::SetPoint( const Point& rPt, sal_uInt16 nPos )
     581             : {
     582             :     DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
     583             :                 "Polygon::SetPoint(): nPos >= nPoints" );
     584             : 
     585       18406 :     ImplMakeUnique();
     586       18406 :     mpImplPolygon->mpPointAry[nPos] = rPt;
     587       18406 : }
     588             : 
     589        4535 : void Polygon::SetFlags( sal_uInt16 nPos, PolyFlags eFlags )
     590             : {
     591             :     DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
     592             :                 "Polygon::SetFlags(): nPos >= nPoints" );
     593             : 
     594             :     // we do only want to create the flag array if there
     595             :     // is at least one flag different to POLY_NORMAL
     596        4535 :     if ( mpImplPolygon || ( eFlags != POLY_NORMAL ) )
     597             :     {
     598        4535 :         ImplMakeUnique();
     599        4535 :         mpImplPolygon->ImplCreateFlagArray();
     600        4535 :         mpImplPolygon->mpFlagAry[ nPos ] = (sal_uInt8) eFlags;
     601             :     }
     602        4535 : }
     603             : 
     604      336415 : const Point& Polygon::GetPoint( sal_uInt16 nPos ) const
     605             : {
     606             :     DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
     607             :                 "Polygon::GetPoint(): nPos >= nPoints" );
     608             : 
     609      336415 :     return mpImplPolygon->mpPointAry[nPos];
     610             : }
     611             : 
     612        6548 : PolyFlags Polygon::GetFlags( sal_uInt16 nPos ) const
     613             : {
     614             :     DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
     615             :                 "Polygon::GetFlags(): nPos >= nPoints" );
     616             :     return( mpImplPolygon->mpFlagAry ?
     617        5809 :             (PolyFlags) mpImplPolygon->mpFlagAry[ nPos ] :
     618       12357 :             POLY_NORMAL );
     619             : }
     620             : 
     621      360838 : bool Polygon::HasFlags() const
     622             : {
     623      360838 :     return mpImplPolygon->mpFlagAry != NULL;
     624             : }
     625             : 
     626        4424 : bool Polygon::IsRect() const
     627             : {
     628        4424 :     bool bIsRect = false;
     629        4424 :     if ( mpImplPolygon->mpFlagAry == NULL )
     630             :     {
     631        7871 :         if ( ( ( mpImplPolygon->mnPoints == 5 ) && ( mpImplPolygon->mpPointAry[ 0 ] == mpImplPolygon->mpPointAry[ 4 ] ) ) ||
     632        3899 :              ( mpImplPolygon->mnPoints == 4 ) )
     633             :         {
     634         161 :             if ( ( mpImplPolygon->mpPointAry[ 0 ].X() == mpImplPolygon->mpPointAry[ 3 ].X() ) &&
     635          30 :                  ( mpImplPolygon->mpPointAry[ 0 ].Y() == mpImplPolygon->mpPointAry[ 1 ].Y() ) &&
     636         103 :                  ( mpImplPolygon->mpPointAry[ 1 ].X() == mpImplPolygon->mpPointAry[ 2 ].X() ) &&
     637          15 :                  ( mpImplPolygon->mpPointAry[ 2 ].Y() == mpImplPolygon->mpPointAry[ 3 ].Y() ) )
     638          15 :                 bIsRect = true;
     639             :         }
     640             :     }
     641        4424 :     return bIsRect;
     642             : }
     643             : 
     644       13445 : void Polygon::SetSize( sal_uInt16 nNewSize )
     645             : {
     646       13445 :     if( nNewSize != mpImplPolygon->mnPoints )
     647             :     {
     648       13152 :         ImplMakeUnique();
     649       13152 :         mpImplPolygon->ImplSetSize( nNewSize );
     650             :     }
     651       13445 : }
     652             : 
     653     2657924 : sal_uInt16 Polygon::GetSize() const
     654             : {
     655     2657924 :     return mpImplPolygon->mnPoints;
     656             : }
     657             : 
     658           0 : void Polygon::Clear()
     659             : {
     660           0 :     if ( mpImplPolygon->mnRefCount )
     661             :     {
     662           0 :         if ( mpImplPolygon->mnRefCount > 1 )
     663           0 :             mpImplPolygon->mnRefCount--;
     664             :         else
     665           0 :             delete mpImplPolygon;
     666             :     }
     667             : 
     668           0 :     mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
     669           0 : }
     670             : 
     671         200 : double Polygon::CalcDistance( sal_uInt16 nP1, sal_uInt16 nP2 )
     672             : {
     673             :     DBG_ASSERT( nP1 < mpImplPolygon->mnPoints,
     674             :                 "Polygon::CalcDistance(): nPos1 >= nPoints" );
     675             :     DBG_ASSERT( nP2 < mpImplPolygon->mnPoints,
     676             :                 "Polygon::CalcDistance(): nPos2 >= nPoints" );
     677             : 
     678         200 :     const Point& rP1 = mpImplPolygon->mpPointAry[ nP1 ];
     679         200 :     const Point& rP2 = mpImplPolygon->mpPointAry[ nP2 ];
     680         200 :     const double fDx = rP2.X() - rP1.X();
     681         200 :     const double fDy = rP2.Y() - rP1.Y();
     682             : 
     683         200 :     return sqrt( fDx * fDx + fDy * fDy );
     684             : }
     685             : 
     686         282 : void Polygon::Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData )
     687             : {
     688             :     DBG_ASSERT( !mpImplPolygon->mpFlagAry, "Optimizing could fail with beziers!" );
     689             : 
     690         282 :     sal_uInt16 nSize = mpImplPolygon->mnPoints;
     691             : 
     692         282 :     if( nOptimizeFlags && nSize )
     693             :     {
     694         282 :         if( nOptimizeFlags & POLY_OPTIMIZE_EDGES )
     695             :         {
     696           0 :             const Rectangle aBound( GetBoundRect() );
     697           0 :             const double    fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
     698           0 :             const sal_uInt16    nPercent = pData ? pData->GetPercentValue() : 50;
     699             : 
     700           0 :             Optimize( POLY_OPTIMIZE_NO_SAME );
     701           0 :             ImplReduceEdges( *this, fArea, nPercent );
     702             :         }
     703         282 :         else if( nOptimizeFlags & ( POLY_OPTIMIZE_REDUCE | POLY_OPTIMIZE_NO_SAME ) )
     704             :         {
     705         282 :             Polygon         aNewPoly;
     706         282 :             const Point&    rFirst = mpImplPolygon->mpPointAry[ 0 ];
     707             :             sal_uIntPtr         nReduce;
     708             : 
     709         282 :             if( nOptimizeFlags & ( POLY_OPTIMIZE_REDUCE ) )
     710           0 :                 nReduce = pData ? pData->GetAbsValue() : 4UL;
     711             :             else
     712         282 :                 nReduce = 0UL;
     713             : 
     714         846 :             while( nSize && ( mpImplPolygon->mpPointAry[ nSize - 1 ] == rFirst ) )
     715         282 :                 nSize--;
     716             : 
     717         282 :             if( nSize > 1 )
     718             :             {
     719         282 :                 sal_uInt16 nLast = 0, nNewCount = 1;
     720             : 
     721         282 :                 aNewPoly.SetSize( nSize );
     722         282 :                 aNewPoly[ 0 ] = rFirst;
     723             : 
     724        1128 :                 for( sal_uInt16 i = 1; i < nSize; i++ )
     725             :                 {
     726        1692 :                     if( ( mpImplPolygon->mpPointAry[ i ] != mpImplPolygon->mpPointAry[ nLast ] ) &&
     727           0 :                         ( !nReduce || ( nReduce < (sal_uIntPtr) FRound( CalcDistance( nLast, i ) ) ) ) )
     728             :                     {
     729         846 :                         aNewPoly[ nNewCount++ ] = mpImplPolygon->mpPointAry[ nLast = i ];
     730             :                     }
     731             :                 }
     732             : 
     733         282 :                 if( nNewCount == 1 )
     734           0 :                     aNewPoly.Clear();
     735             :                 else
     736         282 :                     aNewPoly.SetSize( nNewCount );
     737             :             }
     738             : 
     739         282 :             *this = aNewPoly;
     740             :         }
     741             : 
     742         282 :         nSize = mpImplPolygon->mnPoints;
     743             : 
     744         282 :         if( nSize > 1 )
     745             :         {
     746         296 :             if( ( nOptimizeFlags & POLY_OPTIMIZE_CLOSE ) &&
     747          14 :                 ( mpImplPolygon->mpPointAry[ 0 ] != mpImplPolygon->mpPointAry[ nSize - 1 ] ) )
     748             :             {
     749          14 :                 SetSize( mpImplPolygon->mnPoints + 1 );
     750          14 :                 mpImplPolygon->mpPointAry[ mpImplPolygon->mnPoints - 1 ] = mpImplPolygon->mpPointAry[ 0 ];
     751             :             }
     752         268 :             else if( ( nOptimizeFlags & POLY_OPTIMIZE_OPEN ) &&
     753           0 :                      ( mpImplPolygon->mpPointAry[ 0 ] == mpImplPolygon->mpPointAry[ nSize - 1 ] ) )
     754             :             {
     755           0 :                 const Point& rFirst = mpImplPolygon->mpPointAry[ 0 ];
     756             : 
     757           0 :                 while( nSize && ( mpImplPolygon->mpPointAry[ nSize - 1 ] == rFirst ) )
     758           0 :                     nSize--;
     759             : 
     760           0 :                 SetSize( nSize );
     761             :             }
     762             :         }
     763             :     }
     764         282 : }
     765             : 
     766             : 
     767             : /** Recursively subdivide cubic bezier curve via deCasteljau.
     768             : 
     769             :    @param rPointIter
     770             :    Output iterator, where the subdivided polylines are written to.
     771             : 
     772             :    @param d
     773             :    Squared difference of curve to a straight line
     774             : 
     775             :    @param P*
     776             :    Exactly four points, interpreted as support and control points of
     777             :    a cubic bezier curve. Must be in device coordinates, since stop
     778             :    criterion is based on the following assumption: the device has a
     779             :    finite resolution, it is thus sufficient to stop subdivision if the
     780             :    curve does not deviate more than one pixel from a straight line.
     781             : 
     782             : */
     783      367507 : static void ImplAdaptiveSubdivide( ::std::back_insert_iterator< ::std::vector< Point > >& rPointIter,
     784             :                                    const double old_d2,
     785             :                                    int recursionDepth,
     786             :                                    const double d2,
     787             :                                    const double P1x, const double P1y,
     788             :                                    const double P2x, const double P2y,
     789             :                                    const double P3x, const double P3y,
     790             :                                    const double P4x, const double P4y )
     791             : {
     792             :     // Hard limit on recursion depth, empiric number.
     793             :     enum {maxRecursionDepth=128};
     794             : 
     795             :     // Perform bezier flatness test (lecture notes from R. Schaback,
     796             :     // Mathematics of Computer-Aided Design, Uni Goettingen, 2000)
     797             : 
     798             :     // ||P(t) - L(t)|| <= max     ||b_j - b_0 - j/n(b_n - b_0)||
     799             :     //                    0<=j<=n
     800             : 
     801             :     // What is calculated here is an upper bound to the distance from
     802             :     // a line through b_0 and b_3 (P1 and P4 in our notation) and the
     803             :     // curve. We can drop 0 and n from the running indices, since the
     804             :     // argument of max becomes zero for those cases.
     805      367507 :     const double fJ1x( P2x - P1x - 1.0/3.0*(P4x - P1x) );
     806      367507 :     const double fJ1y( P2y - P1y - 1.0/3.0*(P4y - P1y) );
     807      367507 :     const double fJ2x( P3x - P1x - 2.0/3.0*(P4x - P1x) );
     808      367507 :     const double fJ2y( P3y - P1y - 2.0/3.0*(P4y - P1y) );
     809      367507 :     const double distance2( ::std::max( fJ1x*fJ1x + fJ1y*fJ1y,
     810      735014 :                                         fJ2x*fJ2x + fJ2y*fJ2y) );
     811             : 
     812             :     // stop if error measure does not improve anymore. This is a
     813             :     // safety guard against floating point inaccuracies.
     814             :     // stop at recursion level 128. This is a safety guard against
     815             :     // floating point inaccuracies.
     816             :     // stop if distance from line is guaranteed to be bounded by d
     817      367507 :     if( old_d2 > d2 &&
     818      362075 :         recursionDepth < maxRecursionDepth &&
     819             :         distance2 >= d2 )
     820             :     {
     821             :         // deCasteljau bezier arc, split at t=0.5
     822             :         // Foley/vanDam, p. 508
     823      125525 :         const double L1x( P1x ),             L1y( P1y );
     824      125525 :         const double L2x( (P1x + P2x)*0.5 ), L2y( (P1y + P2y)*0.5 );
     825      125525 :         const double Hx ( (P2x + P3x)*0.5 ), Hy ( (P2y + P3y)*0.5 );
     826      125525 :         const double L3x( (L2x + Hx)*0.5 ),  L3y( (L2y + Hy)*0.5 );
     827      125525 :         const double R4x( P4x ),             R4y( P4y );
     828      125525 :         const double R3x( (P3x + P4x)*0.5 ), R3y( (P3y + P4y)*0.5 );
     829      125525 :         const double R2x( (Hx + R3x)*0.5 ),  R2y( (Hy + R3y)*0.5 );
     830      125525 :         const double R1x( (L3x + R2x)*0.5 ), R1y( (L3y + R2y)*0.5 );
     831      125525 :         const double L4x( R1x ),             L4y( R1y );
     832             : 
     833             :         // subdivide further
     834      125525 :         ++recursionDepth;
     835      125525 :         ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, L1x, L1y, L2x, L2y, L3x, L3y, L4x, L4y);
     836      125525 :         ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, R1x, R1y, R2x, R2y, R3x, R3y, R4x, R4y);
     837             :     }
     838             :     else
     839             :     {
     840             :         // requested resolution reached.
     841             :         // Add end points to output iterator.
     842             :         // order is preserved, since this is so to say depth first traversal.
     843      241982 :         *rPointIter++ = Point( FRound(P1x), FRound(P1y) );
     844             :     }
     845      367507 : }
     846             : 
     847       20918 : void Polygon::AdaptiveSubdivide( Polygon& rResult, const double d ) const
     848             : {
     849       20918 :     if( !mpImplPolygon->mpFlagAry )
     850             :     {
     851        4893 :         rResult = *this;
     852             :     }
     853             :     else
     854             :     {
     855             :         sal_uInt16 i;
     856       16025 :         sal_uInt16 nPts( GetSize() );
     857       16025 :         ::std::vector< Point > aPoints;
     858       16025 :         aPoints.reserve( nPts );
     859       16025 :         ::std::back_insert_iterator< ::std::vector< Point > > aPointIter( aPoints );
     860             : 
     861      218370 :         for(i=0; i<nPts;)
     862             :         {
     863      186320 :             if( ( i + 3 ) < nPts )
     864             :             {
     865      153114 :                 sal_uInt8 P1( mpImplPolygon->mpFlagAry[ i ] );
     866      153114 :                 sal_uInt8 P4( mpImplPolygon->mpFlagAry[ i + 3 ] );
     867             : 
     868      305430 :                 if( ( POLY_NORMAL == P1 || POLY_SMOOTH == P1 || POLY_SYMMTR == P1 ) &&
     869      269571 :                     ( POLY_CONTROL == mpImplPolygon->mpFlagAry[ i + 1 ] ) &&
     870      233712 :                     ( POLY_CONTROL == mpImplPolygon->mpFlagAry[ i + 2 ] ) &&
     871       26870 :                     ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) )
     872             :                 {
     873      116457 :                     ImplAdaptiveSubdivide( aPointIter, d*d+1.0, 0, d*d,
     874      232914 :                                            mpImplPolygon->mpPointAry[ i ].X(),   mpImplPolygon->mpPointAry[ i ].Y(),
     875      232914 :                                            mpImplPolygon->mpPointAry[ i+1 ].X(), mpImplPolygon->mpPointAry[ i+1 ].Y(),
     876      232914 :                                            mpImplPolygon->mpPointAry[ i+2 ].X(), mpImplPolygon->mpPointAry[ i+2 ].Y(),
     877      931656 :                                            mpImplPolygon->mpPointAry[ i+3 ].X(), mpImplPolygon->mpPointAry[ i+3 ].Y() );
     878      116457 :                     i += 3;
     879      116457 :                     continue;
     880             :                 }
     881             :             }
     882             : 
     883       69863 :             *aPointIter++ = mpImplPolygon->mpPointAry[ i++ ];
     884             : 
     885       69863 :             if (aPoints.size() >= SAL_MAX_UINT16)
     886             :             {
     887             :                 OSL_ENSURE(aPoints.size() < SAL_MAX_UINT16,
     888             :                     "Polygon::AdapativeSubdivision created polygon too many points;"
     889             :                     " using original polygon instead");
     890             : 
     891             :                 // The resulting polygon can not hold all the points
     892             :                 // that we have created so far.  Stop the subdivision
     893             :                 // and return a copy of the unmodified polygon.
     894           0 :                 rResult = *this;
     895       20918 :                 return;
     896             :             }
     897             :         }
     898             : 
     899             :         // fill result polygon
     900       16025 :         rResult = Polygon( (sal_uInt16)aPoints.size() ); // ensure sufficient size for copy
     901       16025 :         ::std::copy(aPoints.begin(), aPoints.end(), rResult.mpImplPolygon->mpPointAry);
     902             :     }
     903             : }
     904             : 
     905           0 : void Polygon::ImplReduceEdges( Polygon& rPoly, const double& rArea, sal_uInt16 nPercent )
     906             : {
     907           0 :     const double    fBound = 2000.0 * ( 100 - nPercent ) * 0.01;
     908           0 :     sal_uInt16      nNumNoChange = 0,
     909           0 :                     nNumRuns = 0;
     910             : 
     911           0 :     while( nNumNoChange < 2 )
     912             :     {
     913           0 :         sal_uInt16  nPntCnt = rPoly.GetSize(), nNewPos = 0;
     914           0 :         Polygon aNewPoly( nPntCnt );
     915           0 :         bool    bChangeInThisRun = false;
     916             : 
     917           0 :         for( sal_uInt16 n = 0; n < nPntCnt; n++ )
     918             :         {
     919           0 :             bool bDeletePoint = false;
     920             : 
     921           0 :             if( ( n + nNumRuns ) % 2 )
     922             :             {
     923           0 :                 sal_uInt16      nIndPrev = !n ? nPntCnt - 1 : n - 1;
     924           0 :                 sal_uInt16      nIndPrevPrev = !nIndPrev ? nPntCnt - 1 : nIndPrev - 1;
     925           0 :                 sal_uInt16      nIndNext = ( n == nPntCnt-1 ) ? 0 : n + 1;
     926           0 :                 sal_uInt16      nIndNextNext = ( nIndNext == nPntCnt - 1 ) ? 0 : nIndNext + 1;
     927           0 :                 Vector2D    aVec1( rPoly[ nIndPrev ] ); aVec1 -= rPoly[ nIndPrevPrev ];
     928           0 :                 Vector2D    aVec2( rPoly[ n ] ); aVec2 -= rPoly[ nIndPrev ];
     929           0 :                 Vector2D    aVec3( rPoly[ nIndNext ] ); aVec3 -= rPoly[ n ];
     930           0 :                 Vector2D    aVec4( rPoly[ nIndNextNext ] ); aVec4 -= rPoly[ nIndNext ];
     931           0 :                 double      fDist1 = aVec1.GetLength(), fDist2 = aVec2.GetLength();
     932           0 :                 double      fDist3 = aVec3.GetLength(), fDist4 = aVec4.GetLength();
     933           0 :                 double      fTurnB = aVec2.Normalize().Scalar( aVec3.Normalize() );
     934             : 
     935           0 :                 if( fabs( fTurnB ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnB ) > ( 1.0 - SMALL_DVALUE ) )
     936           0 :                     bDeletePoint = true;
     937             :                 else
     938             :                 {
     939           0 :                     Vector2D    aVecB( rPoly[ nIndNext ] );
     940           0 :                     double      fDistB = ( aVecB -= rPoly[ nIndPrev ] ).GetLength();
     941           0 :                     double      fLenWithB = fDist2 + fDist3;
     942           0 :                     double      fLenFact = ( fDistB != 0.0 ) ? fLenWithB / fDistB : 1.0;
     943           0 :                     double      fTurnPrev = aVec1.Normalize().Scalar( aVec2 );
     944           0 :                     double      fTurnNext = aVec3.Scalar( aVec4.Normalize() );
     945             :                     double      fGradPrev, fGradB, fGradNext;
     946             : 
     947           0 :                     if( fabs( fTurnPrev ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnPrev ) > ( 1.0 - SMALL_DVALUE ) )
     948           0 :                         fGradPrev = 0.0;
     949             :                     else
     950           0 :                         fGradPrev = acos( fTurnPrev ) / ( aVec1.IsNegative( aVec2 ) ? -F_PI180 : F_PI180 );
     951             : 
     952           0 :                     fGradB = acos( fTurnB ) / ( aVec2.IsNegative( aVec3 ) ? -F_PI180 : F_PI180 );
     953             : 
     954           0 :                     if( fabs( fTurnNext ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnNext ) > ( 1.0 - SMALL_DVALUE ) )
     955           0 :                         fGradNext = 0.0;
     956             :                     else
     957           0 :                         fGradNext = acos( fTurnNext ) / ( aVec3.IsNegative( aVec4 ) ? -F_PI180 : F_PI180 );
     958             : 
     959           0 :                     if( ( fGradPrev > 0.0 && fGradB < 0.0 && fGradNext > 0.0 ) ||
     960           0 :                         ( fGradPrev < 0.0 && fGradB > 0.0 && fGradNext < 0.0 ) )
     961             :                     {
     962           0 :                         if( ( fLenFact < ( FSQRT2 + SMALL_DVALUE ) ) &&
     963           0 :                             ( ( ( fDist1 + fDist4 ) / ( fDist2 + fDist3 ) ) * 2000.0 ) > fBound )
     964             :                         {
     965           0 :                             bDeletePoint = true;
     966             :                         }
     967             :                     }
     968             :                     else
     969             :                     {
     970           0 :                         double fRelLen = 1.0 - sqrt( fDistB / rArea );
     971             : 
     972           0 :                         if( fRelLen < 0.0 )
     973           0 :                             fRelLen = 0.0;
     974           0 :                         else if( fRelLen > 1.0 )
     975           0 :                             fRelLen = 1.0;
     976             : 
     977           0 :                         if( ( (sal_uInt32) ( ( ( fLenFact - 1.0 ) * 1000000.0 ) + 0.5 ) < fBound ) &&
     978           0 :                             ( fabs( fGradB ) <= ( fRelLen * fBound * 0.01 ) ) )
     979             :                         {
     980           0 :                             bDeletePoint = true;
     981             :                         }
     982           0 :                     }
     983           0 :                 }
     984             :             }
     985             : 
     986           0 :             if( !bDeletePoint )
     987           0 :                 aNewPoly[ nNewPos++ ] = rPoly[ n ];
     988             :             else
     989           0 :                 bChangeInThisRun = true;
     990             :         }
     991             : 
     992           0 :         if( bChangeInThisRun && nNewPos )
     993             :         {
     994           0 :             aNewPoly.SetSize( nNewPos );
     995           0 :             rPoly = aNewPoly;
     996           0 :             nNumNoChange = 0;
     997             :         }
     998             :         else
     999           0 :             nNumNoChange++;
    1000             : 
    1001           0 :         nNumRuns++;
    1002           0 :     }
    1003           0 : }
    1004             : 
    1005       49241 : void Polygon::Move( long nHorzMove, long nVertMove )
    1006             : {
    1007             :     // This check is required for DrawEngine
    1008       49241 :     if ( !nHorzMove && !nVertMove )
    1009       49295 :         return;
    1010             : 
    1011       49187 :     ImplMakeUnique();
    1012             : 
    1013             :     // Move points
    1014       49187 :     sal_uInt16 nCount = mpImplPolygon->mnPoints;
    1015     1557053 :     for ( sal_uInt16 i = 0; i < nCount; i++ )
    1016             :     {
    1017     1507866 :         Point* pPt = &(mpImplPolygon->mpPointAry[i]);
    1018     1507866 :         pPt->X() += nHorzMove;
    1019     1507866 :         pPt->Y() += nVertMove;
    1020             :     }
    1021             : }
    1022             : 
    1023           0 : void Polygon::Translate(const Point& rTrans)
    1024             : {
    1025           0 :     ImplMakeUnique();
    1026             : 
    1027           0 :     for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
    1028           0 :         mpImplPolygon->mpPointAry[ i ] += rTrans;
    1029           0 : }
    1030             : 
    1031         798 : void Polygon::Scale( double fScaleX, double fScaleY )
    1032             : {
    1033         798 :     ImplMakeUnique();
    1034             : 
    1035       19950 :     for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
    1036             :     {
    1037       19152 :         Point& rPnt = mpImplPolygon->mpPointAry[i];
    1038       19152 :         rPnt.X() = (long) ( fScaleX * rPnt.X() );
    1039       19152 :         rPnt.Y() = (long) ( fScaleY * rPnt.Y() );
    1040             :     }
    1041         798 : }
    1042             : 
    1043     1521502 : void Polygon::Rotate( const Point& rCenter, sal_uInt16 nAngle10 )
    1044             : {
    1045     1521502 :     nAngle10 %= 3600;
    1046             : 
    1047     1521502 :     if( nAngle10 )
    1048             :     {
    1049      326484 :         const double fAngle = F_PI1800 * nAngle10;
    1050      326484 :         Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
    1051             :     }
    1052     1521502 : }
    1053             : 
    1054      326484 : void Polygon::Rotate( const Point& rCenter, double fSin, double fCos )
    1055             : {
    1056      326484 :     ImplMakeUnique();
    1057             : 
    1058             :     long nX, nY;
    1059      326484 :     long nCenterX = rCenter.X();
    1060      326484 :     long nCenterY = rCenter.Y();
    1061             : 
    1062     1645096 :     for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
    1063             :     {
    1064     1318612 :         Point& rPt = mpImplPolygon->mpPointAry[ i ];
    1065             : 
    1066     1318612 :         nX = rPt.X() - nCenterX;
    1067     1318612 :         nY = rPt.Y() - nCenterY;
    1068     1318612 :         rPt.X() = (long) FRound( fCos * nX + fSin * nY ) + nCenterX;
    1069     1318612 :         rPt.Y() = -(long) FRound( fSin * nX - fCos * nY ) + nCenterY;
    1070             :     }
    1071      326484 : }
    1072             : 
    1073           0 : class ImplPointFilter
    1074             : {
    1075             : public:
    1076             :     virtual void LastPoint() = 0;
    1077             :     virtual void Input( const Point& rPoint ) = 0;
    1078             : 
    1079             : protected:
    1080           0 :     ~ImplPointFilter() {}
    1081             : };
    1082             : 
    1083             : class ImplPolygonPointFilter : public ImplPointFilter
    1084             : {
    1085             : public:
    1086             :     ImplPolygon*    mpPoly;     // Don't remove, assigned by polygon
    1087             :     sal_uInt16      mnSize;
    1088             : 
    1089           0 :                     ImplPolygonPointFilter( sal_uInt16 nDestSize ) :
    1090           0 :                         mnSize( 0 )
    1091             :                     {
    1092           0 :                         mpPoly = new ImplPolygon( nDestSize );
    1093           0 :                     }
    1094             : 
    1095           0 :     virtual         ~ImplPolygonPointFilter() {}
    1096             : 
    1097             :     virtual void    LastPoint() SAL_OVERRIDE;
    1098             :     virtual void    Input( const Point& rPoint ) SAL_OVERRIDE;
    1099             : };
    1100             : 
    1101           0 : void ImplPolygonPointFilter::Input( const Point& rPoint )
    1102             : {
    1103           0 :     if ( !mnSize || (rPoint != mpPoly->mpPointAry[mnSize-1]) )
    1104             :     {
    1105           0 :         mnSize++;
    1106           0 :         if ( mnSize > mpPoly->mnPoints )
    1107           0 :             mpPoly->ImplSetSize( mnSize );
    1108           0 :         mpPoly->mpPointAry[mnSize-1] = rPoint;
    1109             :     }
    1110           0 : }
    1111             : 
    1112           0 : void ImplPolygonPointFilter::LastPoint()
    1113             : {
    1114           0 :     if ( mnSize < mpPoly->mnPoints )
    1115           0 :         mpPoly->ImplSetSize( mnSize );
    1116           0 : };
    1117             : 
    1118             : class ImplEdgePointFilter : public ImplPointFilter
    1119             : {
    1120             :     Point               maFirstPoint;
    1121             :     Point               maLastPoint;
    1122             :     ImplPointFilter&    mrNextFilter;
    1123             :     const long          mnLow;
    1124             :     const long          mnHigh;
    1125             :     const int           mnEdge;
    1126             :     int                 mnLastOutside;
    1127             :     bool                mbFirst;
    1128             : 
    1129             : public:
    1130           0 :                         ImplEdgePointFilter( int nEdge, long nLow, long nHigh,
    1131             :                                              ImplPointFilter& rNextFilter ) :
    1132             :                             mrNextFilter( rNextFilter ),
    1133             :                             mnLow( nLow ),
    1134             :                             mnHigh( nHigh ),
    1135             :                             mnEdge( nEdge ),
    1136             :                             mnLastOutside( 0 ),
    1137           0 :                             mbFirst( true )
    1138             :                         {
    1139           0 :                         }
    1140             : 
    1141           0 :     virtual             ~ImplEdgePointFilter() {}
    1142             : 
    1143             :     Point               EdgeSection( const Point& rPoint, int nEdge ) const;
    1144             :     int                 VisibleSide( const Point& rPoint ) const;
    1145           0 :     bool                IsPolygon() const
    1146           0 :                             { return maFirstPoint == maLastPoint; }
    1147             : 
    1148             :     virtual void        Input( const Point& rPoint ) SAL_OVERRIDE;
    1149             :     virtual void        LastPoint() SAL_OVERRIDE;
    1150             : };
    1151             : 
    1152           0 : inline int ImplEdgePointFilter::VisibleSide( const Point& rPoint ) const
    1153             : {
    1154           0 :     if ( mnEdge & EDGE_HORZ )
    1155             :     {
    1156           0 :         return rPoint.X() < mnLow ? EDGE_LEFT :
    1157           0 :                                      rPoint.X() > mnHigh ? EDGE_RIGHT : 0;
    1158             :     }
    1159             :     else
    1160             :     {
    1161           0 :         return rPoint.Y() < mnLow ? EDGE_TOP :
    1162           0 :                                      rPoint.Y() > mnHigh ? EDGE_BOTTOM : 0;
    1163             :     }
    1164             : }
    1165             : 
    1166           0 : Point ImplEdgePointFilter::EdgeSection( const Point& rPoint, int nEdge ) const
    1167             : {
    1168           0 :     long lx = maLastPoint.X();
    1169           0 :     long ly = maLastPoint.Y();
    1170           0 :     long md = rPoint.X() - lx;
    1171           0 :     long mn = rPoint.Y() - ly;
    1172             :     long nNewX;
    1173             :     long nNewY;
    1174             : 
    1175           0 :     if ( nEdge & EDGE_VERT )
    1176             :     {
    1177           0 :         nNewY = (nEdge == EDGE_TOP) ? mnLow : mnHigh;
    1178           0 :         long dy = nNewY - ly;
    1179           0 :         if ( !md )
    1180           0 :             nNewX = lx;
    1181           0 :         else if ( (LONG_MAX / std::abs(md)) >= std::abs(dy) )
    1182           0 :             nNewX = (dy * md) / mn + lx;
    1183             :         else
    1184             :         {
    1185           0 :             BigInt ady = dy;
    1186           0 :             ady *= md;
    1187           0 :             if( ady.IsNeg() )
    1188           0 :                 if( mn < 0 )
    1189           0 :                     ady += mn/2;
    1190             :                 else
    1191           0 :                     ady -= (mn-1)/2;
    1192             :             else
    1193           0 :                 if( mn < 0 )
    1194           0 :                     ady -= (mn+1)/2;
    1195             :                 else
    1196           0 :                     ady += mn/2;
    1197           0 :             ady /= mn;
    1198           0 :             nNewX = (long)ady + lx;
    1199             :         }
    1200             :     }
    1201             :     else
    1202             :     {
    1203           0 :         nNewX = (nEdge == EDGE_LEFT) ? mnLow : mnHigh;
    1204           0 :         long dx = nNewX - lx;
    1205           0 :         if ( !mn )
    1206           0 :             nNewY = ly;
    1207           0 :         else if ( (LONG_MAX / std::abs(mn)) >= std::abs(dx) )
    1208           0 :             nNewY = (dx * mn) / md + ly;
    1209             :         else
    1210             :         {
    1211           0 :             BigInt adx = dx;
    1212           0 :             adx *= mn;
    1213           0 :             if( adx.IsNeg() )
    1214           0 :                 if( md < 0 )
    1215           0 :                     adx += md/2;
    1216             :                 else
    1217           0 :                     adx -= (md-1)/2;
    1218             :             else
    1219           0 :                 if( md < 0 )
    1220           0 :                     adx -= (md+1)/2;
    1221             :                 else
    1222           0 :                     adx += md/2;
    1223           0 :             adx /= md;
    1224           0 :             nNewY = (long)adx + ly;
    1225             :         }
    1226             :     }
    1227             : 
    1228           0 :     return Point( nNewX, nNewY );
    1229             : }
    1230             : 
    1231           0 : void ImplEdgePointFilter::Input( const Point& rPoint )
    1232             : {
    1233           0 :     int nOutside = VisibleSide( rPoint );
    1234             : 
    1235           0 :     if ( mbFirst )
    1236             :     {
    1237           0 :         maFirstPoint = rPoint;
    1238           0 :         mbFirst      = false;
    1239           0 :         if ( !nOutside )
    1240           0 :             mrNextFilter.Input( rPoint );
    1241             :     }
    1242           0 :     else if ( rPoint == maLastPoint )
    1243           0 :         return;
    1244           0 :     else if ( !nOutside )
    1245             :     {
    1246           0 :         if ( mnLastOutside )
    1247           0 :             mrNextFilter.Input( EdgeSection( rPoint, mnLastOutside ) );
    1248           0 :         mrNextFilter.Input( rPoint );
    1249             :     }
    1250           0 :     else if ( !mnLastOutside )
    1251           0 :         mrNextFilter.Input( EdgeSection( rPoint, nOutside ) );
    1252           0 :     else if ( nOutside != mnLastOutside )
    1253             :     {
    1254           0 :         mrNextFilter.Input( EdgeSection( rPoint, mnLastOutside ) );
    1255           0 :         mrNextFilter.Input( EdgeSection( rPoint, nOutside ) );
    1256             :     }
    1257             : 
    1258           0 :     maLastPoint    = rPoint;
    1259           0 :     mnLastOutside  = nOutside;
    1260             : }
    1261             : 
    1262           0 : void ImplEdgePointFilter::LastPoint()
    1263             : {
    1264           0 :     if ( !mbFirst )
    1265             :     {
    1266           0 :         int nOutside = VisibleSide( maFirstPoint );
    1267             : 
    1268           0 :         if ( nOutside != mnLastOutside )
    1269           0 :             Input( maFirstPoint );
    1270           0 :         mrNextFilter.LastPoint();
    1271             :     }
    1272           0 : }
    1273             : 
    1274           0 : void Polygon::Clip( const Rectangle& rRect, bool bPolygon )
    1275             : {
    1276             :     // #105251# Justify rect befor edge filtering
    1277           0 :     Rectangle               aJustifiedRect( rRect );
    1278           0 :     aJustifiedRect.Justify();
    1279             : 
    1280           0 :     sal_uInt16                  nSourceSize = mpImplPolygon->mnPoints;
    1281           0 :     ImplPolygonPointFilter  aPolygon( nSourceSize );
    1282           0 :     ImplEdgePointFilter     aHorzFilter( EDGE_HORZ, aJustifiedRect.Left(), aJustifiedRect.Right(),
    1283           0 :                                          aPolygon );
    1284           0 :     ImplEdgePointFilter     aVertFilter( EDGE_VERT, aJustifiedRect.Top(), aJustifiedRect.Bottom(),
    1285           0 :                                          aHorzFilter );
    1286             : 
    1287           0 :     for ( sal_uInt16 i = 0; i < nSourceSize; i++ )
    1288           0 :         aVertFilter.Input( mpImplPolygon->mpPointAry[i] );
    1289           0 :     if ( bPolygon || aVertFilter.IsPolygon() )
    1290           0 :         aVertFilter.LastPoint();
    1291             :     else
    1292           0 :         aPolygon.LastPoint();
    1293             : 
    1294             :     // Delete old ImpPolygon-data and assign from ImpPolygonPointFilter
    1295           0 :     if ( mpImplPolygon->mnRefCount )
    1296             :     {
    1297           0 :         if ( mpImplPolygon->mnRefCount > 1 )
    1298           0 :             mpImplPolygon->mnRefCount--;
    1299             :         else
    1300           0 :             delete mpImplPolygon;
    1301             :     }
    1302           0 :     mpImplPolygon = aPolygon.mpPoly;
    1303           0 : }
    1304             : 
    1305        3148 : Rectangle Polygon::GetBoundRect() const
    1306             : {
    1307             :     // Removing the assert. Bezier curves have the attribute that each single
    1308             :     // curve segment defined by four points can not exit the four-point polygon
    1309             :     // defined by that points. This allows to say that the curve segment can also
    1310             :     // never leave the Range of it's defining points.
    1311             :     // The result is that Polygon::GetBoundRect() may not create the minimal
    1312             :     // BoundRect of the Polygon (to get that, use basegfx::B2DPolygon classes),
    1313             :     // but will always create a valid BoundRect, at least as long as this method
    1314             :     // 'blindly' travels over all points, including control points.
    1315             : 
    1316             :     // DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetBoundRect could fail with beziers!" );
    1317             : 
    1318        3148 :     sal_uInt16  nCount = mpImplPolygon->mnPoints;
    1319        3148 :     if( ! nCount )
    1320          84 :         return Rectangle();
    1321             : 
    1322             :     long    nXMin, nXMax, nYMin, nYMax;
    1323             : 
    1324        3064 :     const Point* pPt = &(mpImplPolygon->mpPointAry[0]);
    1325        3064 :     nXMin = nXMax = pPt->X();
    1326        3064 :     nYMin = nYMax = pPt->Y();
    1327             : 
    1328       52329 :     for ( sal_uInt16 i = 0; i < nCount; i++ )
    1329             :     {
    1330       49265 :         pPt = &(mpImplPolygon->mpPointAry[i]);
    1331             : 
    1332       49265 :         if ( pPt->X() < nXMin )
    1333        6941 :             nXMin = pPt->X();
    1334       49265 :         if ( pPt->X() > nXMax )
    1335        9830 :             nXMax = pPt->X();
    1336       49265 :         if ( pPt->Y() < nYMin )
    1337        4581 :             nYMin = pPt->Y();
    1338       49265 :         if ( pPt->Y() > nYMax )
    1339       13880 :             nYMax = pPt->Y();
    1340             :     }
    1341             : 
    1342        3064 :     return Rectangle( nXMin, nYMin, nXMax, nYMax );
    1343             : }
    1344             : 
    1345           0 : double Polygon::GetSignedArea() const
    1346             : {
    1347             :     DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetArea could fail with beziers!" );
    1348             : 
    1349           0 :     double fArea = 0.0;
    1350             : 
    1351           0 :     if( mpImplPolygon->mnPoints > 2 )
    1352             :     {
    1353           0 :         const sal_uInt16 nCount1 = mpImplPolygon->mnPoints - 1;
    1354             : 
    1355           0 :         for( sal_uInt16 i = 0; i < nCount1; )
    1356             :         {
    1357           0 :             const Point& rPt = mpImplPolygon->mpPointAry[ i ];
    1358           0 :             const Point& rPt1 = mpImplPolygon->mpPointAry[ ++i ];
    1359           0 :             fArea += ( rPt.X() - rPt1.X() ) * ( rPt.Y() + rPt1.Y() );
    1360             :         }
    1361             : 
    1362           0 :         const Point& rPt = mpImplPolygon->mpPointAry[ nCount1 ];
    1363           0 :         const Point& rPt0 = mpImplPolygon->mpPointAry[ 0 ];
    1364           0 :         fArea += ( rPt.X() - rPt0.X() ) * ( rPt.Y() + rPt0.Y() );
    1365             :     }
    1366             : 
    1367           0 :     return fArea;
    1368             : }
    1369             : 
    1370           0 : bool Polygon::IsInside( const Point& rPoint ) const
    1371             : {
    1372             :     DBG_ASSERT( !mpImplPolygon->mpFlagAry, "IsInside could fail with beziers!" );
    1373             : 
    1374           0 :     const Rectangle aBound( GetBoundRect() );
    1375           0 :     const Line      aLine( rPoint, Point( aBound.Right() + 100L, rPoint.Y() ) );
    1376           0 :     sal_uInt16          nCount = mpImplPolygon->mnPoints;
    1377           0 :     sal_uInt16          nPCounter = 0;
    1378             : 
    1379           0 :     if ( ( nCount > 2 ) && aBound.IsInside( rPoint ) )
    1380             :     {
    1381           0 :         Point   aPt1( mpImplPolygon->mpPointAry[ 0 ] );
    1382           0 :         Point   aIntersection;
    1383           0 :         Point   aLastIntersection;
    1384             : 
    1385           0 :         while ( ( aPt1 == mpImplPolygon->mpPointAry[ nCount - 1 ] ) && ( nCount > 3 ) )
    1386           0 :             nCount--;
    1387             : 
    1388           0 :         for ( sal_uInt16 i = 1; i <= nCount; i++ )
    1389             :         {
    1390           0 :             const Point& rPt2 = mpImplPolygon->mpPointAry[ ( i < nCount ) ? i : 0 ];
    1391             : 
    1392           0 :             if ( aLine.Intersection( Line( aPt1, rPt2 ), aIntersection ) )
    1393             :             {
    1394             :                 // This avoids insertion of double intersections
    1395           0 :                 if ( nPCounter )
    1396             :                 {
    1397           0 :                     if ( aIntersection != aLastIntersection )
    1398             :                     {
    1399           0 :                         aLastIntersection = aIntersection;
    1400           0 :                         nPCounter++;
    1401             :                     }
    1402             :                 }
    1403             :                 else
    1404             :                 {
    1405           0 :                     aLastIntersection = aIntersection;
    1406           0 :                     nPCounter++;
    1407             :                 }
    1408             :             }
    1409             : 
    1410           0 :             aPt1 = rPt2;
    1411             :         }
    1412             :     }
    1413             : 
    1414             :     // is inside, if number of intersection points is odd
    1415           0 :     return ( ( nPCounter & 1 ) == 1 );
    1416             : }
    1417             : 
    1418           0 : bool Polygon::IsRightOrientated() const
    1419             : {
    1420           0 :     return GetSignedArea() >= 0.0;
    1421             : }
    1422             : 
    1423       30659 : void Polygon::Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags )
    1424             : {
    1425       30659 :     ImplMakeUnique();
    1426             : 
    1427       30659 :     if( nPos >= mpImplPolygon->mnPoints )
    1428       28879 :         nPos = mpImplPolygon->mnPoints;
    1429             : 
    1430       30659 :     mpImplPolygon->ImplSplit( nPos, 1 );
    1431       30659 :     mpImplPolygon->mpPointAry[ nPos ] = rPt;
    1432             : 
    1433       30659 :     if( POLY_NORMAL != eFlags )
    1434             :     {
    1435           0 :         mpImplPolygon->ImplCreateFlagArray();
    1436           0 :         mpImplPolygon->mpFlagAry[ nPos ] = (sal_uInt8) eFlags;
    1437             :     }
    1438       30659 : }
    1439             : 
    1440          21 : void Polygon::Insert( sal_uInt16 nPos, const Polygon& rPoly )
    1441             : {
    1442          21 :     const sal_uInt16 nInsertCount = rPoly.mpImplPolygon->mnPoints;
    1443             : 
    1444          21 :     if( nInsertCount )
    1445             :     {
    1446          21 :         ImplMakeUnique();
    1447             : 
    1448          21 :         if( nPos >= mpImplPolygon->mnPoints )
    1449          21 :             nPos = mpImplPolygon->mnPoints;
    1450             : 
    1451          21 :         if( rPoly.mpImplPolygon->mpFlagAry )
    1452          16 :             mpImplPolygon->ImplCreateFlagArray();
    1453             : 
    1454          21 :         mpImplPolygon->ImplSplit( nPos, nInsertCount, rPoly.mpImplPolygon );
    1455             :     }
    1456          21 : }
    1457             : 
    1458     7692982 : Point& Polygon::operator[]( sal_uInt16 nPos )
    1459             : {
    1460             :     DBG_ASSERT( nPos < mpImplPolygon->mnPoints, "Polygon::[]: nPos >= nPoints" );
    1461             : 
    1462     7692982 :     ImplMakeUnique();
    1463     7692982 :     return mpImplPolygon->mpPointAry[nPos];
    1464             : }
    1465             : 
    1466       77961 : Polygon& Polygon::operator=( const Polygon& rPoly )
    1467             : {
    1468             :     DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < 0xFFFFFFFE, "Polygon: RefCount overflow" );
    1469             : 
    1470             :     // Increase refcounter before assigning
    1471             :     // Note: RefCount == 0 for static objects
    1472       77961 :     if ( rPoly.mpImplPolygon->mnRefCount )
    1473       77955 :         rPoly.mpImplPolygon->mnRefCount++;
    1474             : 
    1475             :     // Delete if recount == 0, otherwise decrement
    1476       77961 :     if ( mpImplPolygon->mnRefCount )
    1477             :     {
    1478       56793 :         if ( mpImplPolygon->mnRefCount > 1 )
    1479       54394 :             mpImplPolygon->mnRefCount--;
    1480             :         else
    1481        2399 :             delete mpImplPolygon;
    1482             :     }
    1483             : 
    1484       77961 :     mpImplPolygon = rPoly.mpImplPolygon;
    1485       77961 :     return *this;
    1486             : }
    1487             : 
    1488           0 : bool Polygon::operator==( const Polygon& rPoly ) const
    1489             : {
    1490             : 
    1491           0 :     if ( (rPoly.mpImplPolygon == mpImplPolygon) )
    1492           0 :         return true;
    1493             :     else
    1494           0 :         return false;
    1495             : }
    1496             : 
    1497           0 : bool Polygon::IsEqual( const Polygon& rPoly ) const
    1498             : {
    1499           0 :     bool bIsEqual = true;
    1500             :     sal_uInt16 i;
    1501           0 :     if ( GetSize() != rPoly.GetSize() )
    1502           0 :         bIsEqual = false;
    1503             :     else
    1504             :     {
    1505           0 :         for ( i = 0; i < GetSize(); i++ )
    1506             :         {
    1507           0 :             if ( ( GetPoint( i ) != rPoly.GetPoint( i ) ) ||
    1508           0 :                 ( GetFlags( i ) != rPoly.GetFlags( i ) ) )
    1509             :             {
    1510           0 :                 bIsEqual = false;
    1511           0 :                 break;
    1512             :             }
    1513             :         }
    1514             :     }
    1515           0 :     return bIsEqual;
    1516             : }
    1517             : 
    1518         694 : SvStream& ReadPolygon( SvStream& rIStream, Polygon& rPoly )
    1519             : {
    1520             :     DBG_ASSERTWARNING( rIStream.GetVersion(), "Polygon::>> - Solar-Version not set on rIStream" );
    1521             : 
    1522             :     sal_uInt16          i;
    1523         694 :     sal_uInt16          nPoints(0);
    1524             : 
    1525             :     // read all points and create array
    1526         694 :     rIStream.ReadUInt16( nPoints );
    1527         694 :     if ( rPoly.mpImplPolygon->mnRefCount != 1 )
    1528             :     {
    1529         691 :         if ( rPoly.mpImplPolygon->mnRefCount )
    1530           0 :             rPoly.mpImplPolygon->mnRefCount--;
    1531         691 :         rPoly.mpImplPolygon = new ImplPolygon( nPoints );
    1532             :     }
    1533             :     else
    1534           3 :         rPoly.mpImplPolygon->ImplSetSize( nPoints, false );
    1535             : 
    1536             :     {
    1537             :         // Determine whether we need to write through operators
    1538             : #if (SAL_TYPES_SIZEOFLONG) == 4
    1539             : #ifdef OSL_BIGENDIAN
    1540             :         if ( rIStream.GetNumberFormatInt() == NUMBERFORMAT_INT_BIGENDIAN )
    1541             : #else
    1542         694 :         if ( rIStream.GetNumberFormatInt() == NUMBERFORMAT_INT_LITTLEENDIAN )
    1543             : #endif
    1544         694 :             rIStream.Read( rPoly.mpImplPolygon->mpPointAry, nPoints*sizeof(Point) );
    1545             :         else
    1546             : #endif
    1547             :         {
    1548           0 :             for( i = 0; i < nPoints; i++ )
    1549             :             {
    1550             :                 //fdo#39428 SvStream no longer supports operator>>(long&)
    1551           0 :                 sal_Int32 nTmpX(0), nTmpY(0);
    1552           0 :                 rIStream.ReadInt32( nTmpX ).ReadInt32( nTmpY );
    1553           0 :                 rPoly.mpImplPolygon->mpPointAry[i].X() = nTmpX;
    1554           0 :                 rPoly.mpImplPolygon->mpPointAry[i].Y() = nTmpY;
    1555             :             }
    1556             :         }
    1557             :     }
    1558             : 
    1559         694 :     return rIStream;
    1560             : }
    1561             : 
    1562        5532 : SvStream& WritePolygon( SvStream& rOStream, const Polygon& rPoly )
    1563             : {
    1564             :     DBG_ASSERTWARNING( rOStream.GetVersion(), "Polygon::<< - Solar-Version not set on rOStream" );
    1565             : 
    1566             :     sal_uInt16          i;
    1567        5532 :     sal_uInt16          nPoints = rPoly.GetSize();
    1568             : 
    1569             :     // Write number of points
    1570        5532 :     rOStream.WriteUInt16( nPoints );
    1571             : 
    1572             :     {
    1573             :         // Determine whether we need to write through operators
    1574             : #if (SAL_TYPES_SIZEOFLONG) == 4
    1575             : #ifdef OSL_BIGENDIAN
    1576             :         if ( rOStream.GetNumberFormatInt() == NUMBERFORMAT_INT_BIGENDIAN )
    1577             : #else
    1578        5532 :         if ( rOStream.GetNumberFormatInt() == NUMBERFORMAT_INT_LITTLEENDIAN )
    1579             : #endif
    1580             :         {
    1581        5532 :             if ( nPoints )
    1582        5514 :                 rOStream.Write( rPoly.mpImplPolygon->mpPointAry, nPoints*sizeof(Point) );
    1583             :         }
    1584             :         else
    1585             : #endif
    1586             :         {
    1587           0 :             for( i = 0; i < nPoints; i++ )
    1588             :             {
    1589             :                 //fdo#39428 SvStream no longer supports operator<<(long)
    1590           0 :                 rOStream.WriteInt32( sal::static_int_cast<sal_Int32>( rPoly.mpImplPolygon->mpPointAry[i].X() ) )
    1591           0 :                         .WriteInt32( sal::static_int_cast<sal_Int32>( rPoly.mpImplPolygon->mpPointAry[i].Y() ) );
    1592             :             }
    1593             :         }
    1594             :     }
    1595             : 
    1596        5532 :     return rOStream;
    1597             : }
    1598             : 
    1599         652 : void Polygon::ImplRead( SvStream& rIStream )
    1600             : {
    1601         652 :     sal_uInt8 bHasPolyFlags(0);
    1602             : 
    1603         652 :     ReadPolygon( rIStream, *this );
    1604         652 :     rIStream.ReadUChar( bHasPolyFlags );
    1605             : 
    1606         652 :     if ( bHasPolyFlags )
    1607             :     {
    1608          91 :         mpImplPolygon->mpFlagAry = new sal_uInt8[ mpImplPolygon->mnPoints ];
    1609          91 :         rIStream.Read( mpImplPolygon->mpFlagAry, mpImplPolygon->mnPoints );
    1610             :     }
    1611         652 : }
    1612             : 
    1613         562 : void Polygon::Read( SvStream& rIStream )
    1614             : {
    1615         562 :     VersionCompat aCompat( rIStream, STREAM_READ );
    1616             : 
    1617         562 :     ImplRead( rIStream );
    1618         562 : }
    1619             : 
    1620        1848 : void Polygon::ImplWrite( SvStream& rOStream ) const
    1621             : {
    1622        1848 :     bool bHasPolyFlags = mpImplPolygon->mpFlagAry != NULL;
    1623        1848 :     WritePolygon( rOStream, *this );
    1624        1848 :     rOStream.WriteUChar(sal_uInt8(bHasPolyFlags));
    1625             : 
    1626        1848 :     if ( bHasPolyFlags )
    1627         289 :         rOStream.Write( mpImplPolygon->mpFlagAry, mpImplPolygon->mnPoints );
    1628        1848 : }
    1629             : 
    1630        1651 : void Polygon::Write( SvStream& rOStream ) const
    1631             : {
    1632        1651 :     VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
    1633             : 
    1634        1651 :     ImplWrite( rOStream );
    1635        1651 : }
    1636             : 
    1637             : // #i74631#/#i115917# numerical correction method for B2DPolygon
    1638       23791 : void impCorrectContinuity(basegfx::B2DPolygon& roPolygon, sal_uInt32 nIndex, sal_uInt8 nCFlag)
    1639             : {
    1640       23791 :     const sal_uInt32 nPointCount(roPolygon.count());
    1641             :     OSL_ENSURE(nIndex < nPointCount, "impCorrectContinuity: index access out of range (!)");
    1642             : 
    1643       23791 :     if(nIndex < nPointCount && (POLY_SMOOTH == nCFlag || POLY_SYMMTR == nCFlag))
    1644             :     {
    1645        2480 :         if(roPolygon.isPrevControlPointUsed(nIndex) && roPolygon.isNextControlPointUsed(nIndex))
    1646             :         {
    1647             :             // #i115917# Patch from osnola (modified, thanks for showing the porblem)
    1648             : 
    1649             :             // The correction is needed because an integer polygon with control points
    1650             :             // is converted to double precision. When C1 or C2 is used the involved vectors
    1651             :             // may not have the same directions/lengths since these come from integer coordinates
    1652             :             //  and may have been snapped to different nearest integer coordinates. The snap error
    1653             :             // is in the range of +-1 in y and y, thus 0.0 <= error <= sqrt(2.0). Nonetheless,
    1654             :             // it needs to be corrected to be able to detect the continuity in this points
    1655             :             // correctly.
    1656             : 
    1657             :             // We only have the integer data here (already in double precision form, but no mantisses
    1658             :             // used), so the best correction is to use:
    1659             : 
    1660             :             // for C1: The longest vector since it potentially has best preserved the original vector.
    1661             :             //         Even better the sum of the vectors, weighted by their length. This gives the
    1662             :             //         normal vector addition to get the vector itself, lengths need to be preserved.
    1663             :             // for C2: The mediated vector(s) since both should be the same, but mirrored
    1664             : 
    1665             :             // extract the point and vectors
    1666        2319 :             const basegfx::B2DPoint aPoint(roPolygon.getB2DPoint(nIndex));
    1667        4638 :             const basegfx::B2DVector aNext(roPolygon.getNextControlPoint(nIndex) - aPoint);
    1668        4638 :             const basegfx::B2DVector aPrev(aPoint - roPolygon.getPrevControlPoint(nIndex));
    1669             : 
    1670             :             // calculate common direction vector, normalize
    1671        4638 :             const basegfx::B2DVector aDirection(aNext + aPrev);
    1672             : 
    1673        2319 :             if(POLY_SMOOTH == nCFlag)
    1674             :             {
    1675             :                 // C1: apply common direction vector, preserve individual lengths
    1676         824 :                 const double fInvDirectionLen(1.0 / aDirection.getLength());
    1677         824 :                 roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + (aDirection * (aNext.getLength() * fInvDirectionLen))));
    1678         824 :                 roPolygon.setPrevControlPoint(nIndex, basegfx::B2DPoint(aPoint - (aDirection * (aPrev.getLength() * fInvDirectionLen))));
    1679             :             }
    1680             :             else // POLY_SYMMTR
    1681             :             {
    1682             :                 // C2: get mediated length. Taking half of the unnormalized direction would be
    1683             :                 // an approximation, but not correct.
    1684        1495 :                 const double fMedLength((aNext.getLength() + aPrev.getLength()) * (0.5 / aDirection.getLength()));
    1685        1495 :                 const basegfx::B2DVector aScaledDirection(aDirection * fMedLength);
    1686             : 
    1687             :                 // Bring Direction to correct length and apply
    1688        1495 :                 roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + aScaledDirection));
    1689        1495 :                 roPolygon.setPrevControlPoint(nIndex, basegfx::B2DPoint(aPoint - aScaledDirection));
    1690        2319 :             }
    1691             :         }
    1692             :     }
    1693       23791 : }
    1694             : 
    1695             : // convert to basegfx::B2DPolygon and return
    1696        4425 : basegfx::B2DPolygon Polygon::getB2DPolygon() const
    1697             : {
    1698        4425 :     basegfx::B2DPolygon aRetval;
    1699        4425 :     const sal_uInt16 nCount(mpImplPolygon->mnPoints);
    1700             : 
    1701        4425 :     if(nCount)
    1702             :     {
    1703        4422 :         if(mpImplPolygon->mpFlagAry)
    1704             :         {
    1705             :             // handling for curves. Add start point
    1706        1981 :             const Point aStartPoint(mpImplPolygon->mpPointAry[0]);
    1707        1981 :             sal_uInt8 nPointFlag(mpImplPolygon->mpFlagAry[0]);
    1708        1981 :             aRetval.append(basegfx::B2DPoint(aStartPoint.X(), aStartPoint.Y()));
    1709        1981 :             Point aControlA, aControlB;
    1710             : 
    1711       30646 :             for(sal_uInt16 a(1); a < nCount;)
    1712             :             {
    1713       26684 :                 bool bControlA(false);
    1714       26684 :                 bool bControlB(false);
    1715             : 
    1716       26684 :                 if(POLY_CONTROL == mpImplPolygon->mpFlagAry[a])
    1717             :                 {
    1718       21916 :                     aControlA = mpImplPolygon->mpPointAry[a++];
    1719       21916 :                     bControlA = true;
    1720             :                 }
    1721             : 
    1722       26684 :                 if(a < nCount && POLY_CONTROL == mpImplPolygon->mpFlagAry[a])
    1723             :                 {
    1724       21916 :                     aControlB = mpImplPolygon->mpPointAry[a++];
    1725       21916 :                     bControlB = true;
    1726             :                 }
    1727             : 
    1728             :                 // assert invalid polygons
    1729             :                 OSL_ENSURE(bControlA == bControlB, "Polygon::getB2DPolygon: Invalid source polygon (!)");
    1730             :                 (void)bControlB;
    1731             : 
    1732       26684 :                 if(a < nCount)
    1733             :                 {
    1734       26684 :                     const Point aEndPoint(mpImplPolygon->mpPointAry[a]);
    1735             : 
    1736       26684 :                     if(bControlA)
    1737             :                     {
    1738             :                         // bezier edge, add
    1739             :                         aRetval.appendBezierSegment(
    1740       43832 :                             basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
    1741       43832 :                             basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
    1742      109580 :                             basegfx::B2DPoint(aEndPoint.X(), aEndPoint.Y()));
    1743             : 
    1744       21916 :                         impCorrectContinuity(aRetval, aRetval.count() - 2, nPointFlag);
    1745             :                     }
    1746             :                     else
    1747             :                     {
    1748             :                         // no bezier edge, add end point
    1749        4768 :                         aRetval.append(basegfx::B2DPoint(aEndPoint.X(), aEndPoint.Y()));
    1750             :                     }
    1751             : 
    1752       26684 :                     nPointFlag = mpImplPolygon->mpFlagAry[a++];
    1753             :                 }
    1754             :             }
    1755             : 
    1756             :             // if exist, remove double first/last points, set closed and correct control points
    1757        1981 :             basegfx::tools::checkClosed(aRetval);
    1758             : 
    1759        1981 :             if(aRetval.isClosed())
    1760             :             {
    1761             :                 // closeWithGeometryChange did really close, so last point(s) were removed.
    1762             :                 // Correct the continuity in the changed point
    1763        1875 :                 impCorrectContinuity(aRetval, 0, mpImplPolygon->mpFlagAry[0]);
    1764             :             }
    1765             :         }
    1766             :         else
    1767             :         {
    1768             :             // extra handling for non-curves (most-used case) for speedup
    1769      121975 :             for(sal_uInt16 a(0); a < nCount; a++)
    1770             :             {
    1771             :                 // get point and add
    1772      119534 :                 const Point aPoint(mpImplPolygon->mpPointAry[a]);
    1773      119534 :                 aRetval.append(basegfx::B2DPoint(aPoint.X(), aPoint.Y()));
    1774             :             }
    1775             : 
    1776             :             // set closed flag
    1777        2441 :             basegfx::tools::checkClosed(aRetval);
    1778             :         }
    1779             :     }
    1780             : 
    1781        4425 :     return aRetval;
    1782             : }
    1783             : 
    1784             : // constructor to convert from basegfx::B2DPolygon
    1785             : // #i76891# Needed to change from adding all control points (even for unused
    1786             : // edges) and creating a fixed-size Polygon in the first run to creating the
    1787             : // minimal Polygon. This requires a temporary Point- and Flag-Array for curves
    1788             : // and a memcopy at ImplPolygon creation, but contains no zero-controlpoints
    1789             : // for straight edges.
    1790      344923 : Polygon::Polygon(const basegfx::B2DPolygon& rPolygon)
    1791      344923 : :   mpImplPolygon(0)
    1792             : {
    1793      344923 :     const bool bCurve(rPolygon.areControlPointsUsed());
    1794      344923 :     const bool bClosed(rPolygon.isClosed());
    1795      344923 :     sal_uInt32 nB2DLocalCount(rPolygon.count());
    1796             : 
    1797      344923 :     if(bCurve)
    1798             :     {
    1799             :         // #127979# Reduce source point count hard to the limit of the tools Polygon
    1800       15773 :         if(nB2DLocalCount > ((0x0000ffff / 3L) - 1L))
    1801             :         {
    1802             :             OSL_FAIL("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
    1803           0 :             nB2DLocalCount = ((0x0000ffff / 3L) - 1L);
    1804             :         }
    1805             : 
    1806             :         // calculate target point count
    1807       15773 :         const sal_uInt32 nLoopCount(bClosed ? nB2DLocalCount : (nB2DLocalCount ? nB2DLocalCount - 1L : 0L ));
    1808             : 
    1809       15773 :         if(nLoopCount)
    1810             :         {
    1811             :             // calculate maximum array size and allocate; prepare insert index
    1812       15773 :             const sal_uInt32 nMaxTargetCount((nLoopCount * 3) + 1);
    1813       15773 :             mpImplPolygon = new ImplPolygon(static_cast< sal_uInt16 >(nMaxTargetCount), true);
    1814             : 
    1815             :             // prepare insert index and current point
    1816       15773 :             sal_uInt32 nArrayInsert(0);
    1817       15773 :             basegfx::B2DCubicBezier aBezier;
    1818       15773 :             aBezier.setStartPoint(rPolygon.getB2DPoint(0));
    1819             : 
    1820      185767 :             for(sal_uInt32 a(0L); a < nLoopCount; a++)
    1821             :             {
    1822             :                 // add current point (always) and remember StartPointIndex for evtl. later corrections
    1823      169994 :                 const Point aStartPoint(FRound(aBezier.getStartPoint().getX()), FRound(aBezier.getStartPoint().getY()));
    1824      169994 :                 const sal_uInt32 nStartPointIndex(nArrayInsert);
    1825      169994 :                 mpImplPolygon->mpPointAry[nStartPointIndex] = aStartPoint;
    1826      169994 :                 mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_NORMAL;
    1827      169994 :                 nArrayInsert++;
    1828             : 
    1829             :                 // prepare next segment
    1830      169994 :                 const sal_uInt32 nNextIndex((a + 1) % nB2DLocalCount);
    1831      169994 :                 aBezier.setEndPoint(rPolygon.getB2DPoint(nNextIndex));
    1832      169994 :                 aBezier.setControlPointA(rPolygon.getNextControlPoint(a));
    1833      169994 :                 aBezier.setControlPointB(rPolygon.getPrevControlPoint(nNextIndex));
    1834             : 
    1835      169994 :                 if(aBezier.isBezier())
    1836             :                 {
    1837             :                     // if one is used, add always two control points due to the old schema
    1838      117936 :                     mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointA().getX()), FRound(aBezier.getControlPointA().getY()));
    1839      117936 :                     mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_CONTROL;
    1840      117936 :                     nArrayInsert++;
    1841             : 
    1842      117936 :                     mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointB().getX()), FRound(aBezier.getControlPointB().getY()));
    1843      117936 :                     mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_CONTROL;
    1844      117936 :                     nArrayInsert++;
    1845             :                 }
    1846             : 
    1847             :                 // test continuity with previous control point to set flag value
    1848      169994 :                 if(aBezier.getControlPointA() != aBezier.getStartPoint() && (bClosed || a))
    1849             :                 {
    1850      114732 :                     const basegfx::B2VectorContinuity eCont(rPolygon.getContinuityInPoint(a));
    1851             : 
    1852      114732 :                     if(basegfx::CONTINUITY_C1 == eCont)
    1853             :                     {
    1854       12080 :                         mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_SMOOTH;
    1855             :                     }
    1856      102652 :                     else if(basegfx::CONTINUITY_C2 == eCont)
    1857             :                     {
    1858       18648 :                         mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_SYMMTR;
    1859             :                     }
    1860             :                 }
    1861             : 
    1862             :                 // prepare next polygon step
    1863      169994 :                 aBezier.setStartPoint(aBezier.getEndPoint());
    1864             :             }
    1865             : 
    1866       15773 :             if(bClosed)
    1867             :             {
    1868             :                 // add first point again as closing point due to old definition
    1869       14646 :                 mpImplPolygon->mpPointAry[nArrayInsert] = mpImplPolygon->mpPointAry[0];
    1870       14646 :                 mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_NORMAL;
    1871       14646 :                 nArrayInsert++;
    1872             :             }
    1873             :             else
    1874             :             {
    1875             :                 // add last point as closing point
    1876        1127 :                 const basegfx::B2DPoint aClosingPoint(rPolygon.getB2DPoint(nB2DLocalCount - 1L));
    1877        1127 :                 const Point aEnd(FRound(aClosingPoint.getX()), FRound(aClosingPoint.getY()));
    1878        1127 :                 mpImplPolygon->mpPointAry[nArrayInsert] = aEnd;
    1879        1127 :                 mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_NORMAL;
    1880        1127 :                 nArrayInsert++;
    1881             :             }
    1882             : 
    1883             :             DBG_ASSERT(nArrayInsert <= nMaxTargetCount, "Polygon::Polygon from basegfx::B2DPolygon: wrong max point count estimation (!)");
    1884             : 
    1885       15773 :             if(nArrayInsert != nMaxTargetCount)
    1886             :             {
    1887       13392 :                 mpImplPolygon->ImplSetSize(static_cast< sal_uInt16 >(nArrayInsert), true);
    1888       15773 :             }
    1889             :         }
    1890             :     }
    1891             :     else
    1892             :     {
    1893             :         // #127979# Reduce source point count hard to the limit of the tools Polygon
    1894      329150 :         if(nB2DLocalCount > (0x0000ffff - 1L))
    1895             :         {
    1896             :             OSL_FAIL("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
    1897           0 :             nB2DLocalCount = (0x0000ffff - 1L);
    1898             :         }
    1899             : 
    1900      329150 :         if(nB2DLocalCount)
    1901             :         {
    1902             :             // point list creation
    1903      329141 :             const sal_uInt32 nTargetCount(nB2DLocalCount + (bClosed ? 1L : 0L));
    1904      329141 :             mpImplPolygon = new ImplPolygon( static_cast< sal_uInt16 >(nTargetCount) );
    1905      329141 :             sal_uInt16 nIndex(0);
    1906             : 
    1907     1676309 :             for(sal_uInt32 a(0L); a < nB2DLocalCount; a++)
    1908             :             {
    1909     1347168 :                 basegfx::B2DPoint aB2DPoint(rPolygon.getB2DPoint(a));
    1910     1347168 :                 Point aPoint(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY()));
    1911     1347168 :                 mpImplPolygon->mpPointAry[nIndex++] = aPoint;
    1912     1347168 :             }
    1913             : 
    1914      329141 :             if(bClosed)
    1915             :             {
    1916             :                 // add first point as closing point
    1917      196369 :                 mpImplPolygon->mpPointAry[nIndex] = mpImplPolygon->mpPointAry[0];
    1918             :             }
    1919             :         }
    1920             :     }
    1921             : 
    1922      344923 :     if(!mpImplPolygon)
    1923             :     {
    1924             :         // no content yet, create empty polygon
    1925           9 :         mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon);
    1926             :     }
    1927      344923 : }
    1928             : 
    1929             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10