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

Generated by: LCOV version 1.10