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

Generated by: LCOV version 1.11