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

Generated by: LCOV version 1.10