LCOV - code coverage report
Current view: top level - tools/source/generic - poly.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 492 896 54.9 %
Date: 2012-08-25 Functions: 44 75 58.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 301 910 33.1 %

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

Generated by: LCOV version 1.10