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

Generated by: LCOV version 1.10