LCOV - code coverage report
Current view: top level - tools/source/generic - poly2.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 270 338 79.9 %
Date: 2014-11-03 Functions: 32 37 86.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #define POLY_CLIP_INT   0
      21             : #define POLY_CLIP_UNION 1
      22             : #define POLY_CLIP_DIFF  2
      23             : #define POLY_CLIP_XOR   3
      24             : 
      25             : #include <rtl/math.hxx>
      26             : #include <poly.h>
      27             : #include <tools/poly.hxx>
      28             : #include <tools/debug.hxx>
      29             : #include <tools/stream.hxx>
      30             : #include <tools/vcompat.hxx>
      31             : #include <tools/gen.hxx>
      32             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      33             : #include <basegfx/polygon/b2dpolygon.hxx>
      34             : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
      35             : 
      36      340959 : ImplPolyPolygon::ImplPolyPolygon( sal_uInt16 nInitSize )
      37             : {
      38      340959 :     mnRefCount  = 1;
      39      340959 :     mnCount     = nInitSize;
      40      340959 :     mnSize      = nInitSize;
      41      340959 :     mnResize    = 16;
      42      340959 :     mpPolyAry   = new SVPPOLYGON[ nInitSize ];
      43      340959 : }
      44             : 
      45      212425 : ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon& rImplPolyPoly )
      46             : {
      47      212425 :     mnRefCount  = 1;
      48      212425 :     mnCount     = rImplPolyPoly.mnCount;
      49      212425 :     mnSize      = rImplPolyPoly.mnSize;
      50      212425 :     mnResize    = rImplPolyPoly.mnResize;
      51             : 
      52      212425 :     if ( rImplPolyPoly.mpPolyAry )
      53             :     {
      54      208589 :         mpPolyAry = new SVPPOLYGON[mnSize];
      55      422028 :         for ( sal_uInt16 i = 0; i < mnCount; i++ )
      56      213439 :             mpPolyAry[i] = new Polygon( *rImplPolyPoly.mpPolyAry[i] );
      57             :     }
      58             :     else
      59        3836 :         mpPolyAry = NULL;
      60      212425 : }
      61             : 
      62      739396 : ImplPolyPolygon::~ImplPolyPolygon()
      63             : {
      64      739396 :     if ( mpPolyAry )
      65             :     {
      66     1437371 :         for ( sal_uInt16 i = 0; i < mnCount; i++ )
      67      735356 :             delete mpPolyAry[i];
      68      702015 :         delete[] mpPolyAry;
      69             :     }
      70      739396 : }
      71             : 
      72             : namespace tools {
      73             : 
      74      179372 : PolyPolygon::PolyPolygon( sal_uInt16 nInitSize, sal_uInt16 nResize )
      75             : {
      76      179372 :     if ( nInitSize > MAX_POLYGONS )
      77           0 :         nInitSize = MAX_POLYGONS;
      78      179372 :     else if ( !nInitSize )
      79           0 :         nInitSize = 1;
      80      179372 :     if ( nResize > MAX_POLYGONS )
      81           0 :         nResize = MAX_POLYGONS;
      82      179372 :     else if ( !nResize )
      83           0 :         nResize = 1;
      84      179372 :     mpImplPolyPolygon = new ImplPolyPolygon( nInitSize, nResize );
      85      179372 : }
      86             : 
      87      284801 : PolyPolygon::PolyPolygon( const Polygon& rPoly )
      88             : {
      89      284801 :     if ( rPoly.GetSize() )
      90             :     {
      91      284801 :         mpImplPolyPolygon = new ImplPolyPolygon( 1 );
      92      284801 :         mpImplPolyPolygon->mpPolyAry[0] = new Polygon( rPoly );
      93             :     }
      94             :     else
      95           0 :         mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
      96      284801 : }
      97             : 
      98      415301 : PolyPolygon::PolyPolygon( const tools::PolyPolygon& rPolyPoly )
      99             : {
     100             :     DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
     101             : 
     102      415301 :     mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
     103      415301 :     mpImplPolyPolygon->mnRefCount++;
     104      415301 : }
     105             : 
     106      940964 : PolyPolygon::~PolyPolygon()
     107             : {
     108      940964 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     109      219054 :         mpImplPolyPolygon->mnRefCount--;
     110             :     else
     111      721910 :         delete mpImplPolyPolygon;
     112      940964 : }
     113             : 
     114      162438 : void PolyPolygon::Insert( const Polygon& rPoly, sal_uInt16 nPos )
     115             : {
     116      162438 :     if ( mpImplPolyPolygon->mnCount >= MAX_POLYGONS )
     117      162438 :         return;
     118             : 
     119      162438 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     120             :     {
     121           0 :         mpImplPolyPolygon->mnRefCount--;
     122           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     123             :     }
     124             : 
     125      162438 :     if ( nPos > mpImplPolyPolygon->mnCount )
     126      162402 :         nPos = mpImplPolyPolygon->mnCount;
     127             : 
     128      162438 :     if ( !mpImplPolyPolygon->mpPolyAry )
     129      152505 :         mpImplPolyPolygon->mpPolyAry = new SVPPOLYGON[mpImplPolyPolygon->mnSize];
     130        9933 :     else if ( mpImplPolyPolygon->mnCount == mpImplPolyPolygon->mnSize )
     131             :     {
     132          84 :         sal_uInt16      nOldSize = mpImplPolyPolygon->mnSize;
     133          84 :         sal_uInt16      nNewSize = nOldSize + mpImplPolyPolygon->mnResize;
     134             :         SVPPOLYGON* pNewAry;
     135             : 
     136          84 :         if ( nNewSize >= MAX_POLYGONS )
     137           0 :             nNewSize = MAX_POLYGONS;
     138          84 :         pNewAry = new SVPPOLYGON[nNewSize];
     139          84 :         memcpy( pNewAry, mpImplPolyPolygon->mpPolyAry, nPos*sizeof(SVPPOLYGON) );
     140         168 :         memcpy( pNewAry+nPos+1, mpImplPolyPolygon->mpPolyAry+nPos,
     141         252 :                 (nOldSize-nPos)*sizeof(SVPPOLYGON) );
     142          84 :         delete[] mpImplPolyPolygon->mpPolyAry;
     143          84 :         mpImplPolyPolygon->mpPolyAry = pNewAry;
     144          84 :         mpImplPolyPolygon->mnSize = nNewSize;
     145             :     }
     146        9849 :     else if ( nPos < mpImplPolyPolygon->mnCount )
     147             :     {
     148           0 :         memmove( mpImplPolyPolygon->mpPolyAry+nPos+1,
     149             :                  mpImplPolyPolygon->mpPolyAry+nPos,
     150           0 :                  (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
     151             :     }
     152             : 
     153      162438 :     mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
     154      162438 :     mpImplPolyPolygon->mnCount++;
     155             : }
     156             : 
     157          16 : void PolyPolygon::Remove( sal_uInt16 nPos )
     158             : {
     159             :     assert(nPos < Count() && "PolyPolygon::Remove(): nPos >= nSize");
     160             : 
     161          16 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     162             :     {
     163           0 :         mpImplPolyPolygon->mnRefCount--;
     164           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     165             :     }
     166             : 
     167          16 :     delete mpImplPolyPolygon->mpPolyAry[nPos];
     168          16 :     mpImplPolyPolygon->mnCount--;
     169          16 :     memmove( mpImplPolyPolygon->mpPolyAry+nPos,
     170          32 :              mpImplPolyPolygon->mpPolyAry+nPos+1,
     171          64 :              (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
     172          16 : }
     173             : 
     174           6 : void PolyPolygon::Replace( const Polygon& rPoly, sal_uInt16 nPos )
     175             : {
     176             :     assert(nPos < Count() && "PolyPolygon::Replace(): nPos >= nSize");
     177             : 
     178           6 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     179             :     {
     180           0 :         mpImplPolyPolygon->mnRefCount--;
     181           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     182             :     }
     183             : 
     184           6 :     delete mpImplPolyPolygon->mpPolyAry[nPos];
     185           6 :     mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
     186           6 : }
     187             : 
     188      553861 : const Polygon& PolyPolygon::GetObject( sal_uInt16 nPos ) const
     189             : {
     190             :     assert(nPos < Count() && "PolyPolygon::GetObject(): nPos >= nSize");
     191             : 
     192      553861 :     return *(mpImplPolyPolygon->mpPolyAry[nPos]);
     193             : }
     194             : 
     195      283544 : bool PolyPolygon::IsRect() const
     196             : {
     197      283544 :     bool bIsRect = false;
     198      283544 :     if ( Count() == 1 )
     199      283434 :         bIsRect = mpImplPolyPolygon->mpPolyAry[ 0 ]->IsRect();
     200      283544 :     return bIsRect;
     201             : }
     202             : 
     203         416 : void PolyPolygon::Clear()
     204             : {
     205         416 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     206             :     {
     207          44 :         mpImplPolyPolygon->mnRefCount--;
     208             :         mpImplPolyPolygon = new ImplPolyPolygon( mpImplPolyPolygon->mnResize,
     209          44 :                                                  mpImplPolyPolygon->mnResize );
     210             :     }
     211             :     else
     212             :     {
     213         372 :         if ( mpImplPolyPolygon->mpPolyAry )
     214             :         {
     215          76 :             for ( sal_uInt16 i = 0; i < mpImplPolyPolygon->mnCount; i++ )
     216          38 :                 delete mpImplPolyPolygon->mpPolyAry[i];
     217          38 :             delete[] mpImplPolyPolygon->mpPolyAry;
     218          38 :             mpImplPolyPolygon->mpPolyAry = NULL;
     219          38 :             mpImplPolyPolygon->mnCount   = 0;
     220          38 :             mpImplPolyPolygon->mnSize    = mpImplPolyPolygon->mnResize;
     221             :         }
     222             :     }
     223         416 : }
     224             : 
     225         204 : void PolyPolygon::Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData )
     226             : {
     227         204 :     if(nOptimizeFlags && Count())
     228             :     {
     229             :         // #115630# ImplDrawHatch does not work with beziers included in the polypolygon, take care of that
     230         204 :         bool bIsCurve(false);
     231             : 
     232         408 :         for(sal_uInt16 a(0); !bIsCurve && a < Count(); a++)
     233             :         {
     234         204 :             if((*this)[a].HasFlags())
     235             :             {
     236           0 :                 bIsCurve = true;
     237             :             }
     238             :         }
     239             : 
     240         204 :         if(bIsCurve)
     241             :         {
     242             :             OSL_ENSURE(false, "Optimize does *not* support curves, falling back to AdaptiveSubdivide()...");
     243           0 :             tools::PolyPolygon aPolyPoly;
     244             : 
     245           0 :             AdaptiveSubdivide(aPolyPoly);
     246           0 :             aPolyPoly.Optimize(nOptimizeFlags, pData);
     247           0 :             *this = aPolyPoly;
     248             :         }
     249             :         else
     250             :         {
     251             :             double      fArea;
     252         204 :             const bool  bEdges = ( nOptimizeFlags & POLY_OPTIMIZE_EDGES ) == POLY_OPTIMIZE_EDGES;
     253         204 :             sal_uInt16      nPercent = 0;
     254             : 
     255         204 :             if( bEdges )
     256             :             {
     257           0 :                 const Rectangle aBound( GetBoundRect() );
     258             : 
     259           0 :                 fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
     260           0 :                 nPercent = pData ? pData->GetPercentValue() : 50;
     261           0 :                 nOptimizeFlags &= ~POLY_OPTIMIZE_EDGES;
     262             :             }
     263             : 
     264             :             // watch for ref counter
     265         204 :             if( mpImplPolyPolygon->mnRefCount > 1 )
     266             :             {
     267           0 :                 mpImplPolyPolygon->mnRefCount--;
     268           0 :                 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     269             :             }
     270             : 
     271             :             // Optimize polygons
     272         408 :             for( sal_uInt16 i = 0, nPolyCount = mpImplPolyPolygon->mnCount; i < nPolyCount; i++ )
     273             :             {
     274         204 :                 if( bEdges )
     275             :                 {
     276           0 :                     mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( POLY_OPTIMIZE_NO_SAME );
     277           0 :                     Polygon::ImplReduceEdges( *( mpImplPolyPolygon->mpPolyAry[ i ] ), fArea, nPercent );
     278             :                 }
     279             : 
     280         204 :                 if( nOptimizeFlags )
     281         204 :                     mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( nOptimizeFlags, pData );
     282             :             }
     283             :         }
     284             :     }
     285         204 : }
     286             : 
     287         258 : void PolyPolygon::AdaptiveSubdivide( tools::PolyPolygon& rResult, const double d ) const
     288             : {
     289         258 :     rResult.Clear();
     290             : 
     291         258 :     Polygon aPolygon;
     292             : 
     293        1176 :     for( sal_uInt16 i = 0; i < mpImplPolyPolygon->mnCount; i++ )
     294             :     {
     295         918 :         mpImplPolyPolygon->mpPolyAry[ i ]->AdaptiveSubdivide( aPolygon, d );
     296         918 :         rResult.Insert( aPolygon );
     297         258 :     }
     298         258 : }
     299             : 
     300        1389 : tools::PolyPolygon PolyPolygon::SubdivideBezier( const tools::PolyPolygon& rPolyPoly )
     301             : {
     302        1389 :     sal_uInt16 i, nPolys = rPolyPoly.Count();
     303        1389 :     tools::PolyPolygon aPolyPoly( nPolys );
     304        6003 :     for( i=0; i<nPolys; ++i )
     305        4614 :         aPolyPoly.Insert( Polygon::SubdivideBezier( rPolyPoly.GetObject(i) ) );
     306             : 
     307        1389 :     return aPolyPoly;
     308             : }
     309             : 
     310             : 
     311           0 : void PolyPolygon::GetIntersection( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const
     312             : {
     313           0 :     ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_INT );
     314           0 : }
     315             : 
     316         154 : void PolyPolygon::GetUnion( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const
     317             : {
     318         154 :     ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_UNION );
     319         154 : }
     320             : 
     321         154 : void PolyPolygon::ImplDoOperation( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult, sal_uIntPtr nOperation ) const
     322             : {
     323             :     // Convert to B2DPolyPolygon, temporarily. It might be
     324             :     // advantageous in the future, to have a tools::PolyPolygon adaptor that
     325             :     // just simulates a B2DPolyPolygon here...
     326         154 :     basegfx::B2DPolyPolygon aMergePolyPolygonA( getB2DPolyPolygon() );
     327         308 :     basegfx::B2DPolyPolygon aMergePolyPolygonB( rPolyPoly.getB2DPolyPolygon() );
     328             : 
     329             :     // normalize the two polypolygons before. Force properly oriented
     330             :     // polygons.
     331         154 :     aMergePolyPolygonA = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA );
     332         154 :     aMergePolyPolygonB = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB );
     333             : 
     334         154 :     switch( nOperation )
     335             :     {
     336             :         // All code extracted from svx/source/svdraw/svedtv2.cxx
     337             : 
     338             :         case POLY_CLIP_UNION:
     339             :         {
     340             :             // merge A and B (OR)
     341         154 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
     342         154 :             break;
     343             :         }
     344             : 
     345             :         case POLY_CLIP_DIFF:
     346             :         {
     347             :             // subtract B from A (DIFF)
     348           0 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
     349           0 :             break;
     350             :         }
     351             : 
     352             :         case POLY_CLIP_XOR:
     353             :         {
     354             :             // compute XOR between poly A and B
     355           0 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
     356           0 :             break;
     357             :         }
     358             : 
     359             :         default:
     360             :         case POLY_CLIP_INT:
     361             :         {
     362             :             // cut poly 1 against polys 2..n (AND)
     363           0 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
     364           0 :             break;
     365             :         }
     366             :     }
     367             : 
     368         308 :     rResult = tools::PolyPolygon( aMergePolyPolygonA );
     369         154 : }
     370             : 
     371     1028085 : sal_uInt16 PolyPolygon::Count() const
     372             : {
     373     1028085 :     return mpImplPolyPolygon->mnCount;
     374             : }
     375             : 
     376       29338 : void PolyPolygon::Move( long nHorzMove, long nVertMove )
     377             : {
     378             :     // Required for DrawEngine
     379       29338 :     if( nHorzMove || nVertMove )
     380             :     {
     381       28836 :         if ( mpImplPolyPolygon->mnRefCount > 1 )
     382             :         {
     383       27190 :             mpImplPolyPolygon->mnRefCount--;
     384       27190 :             mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     385             :         }
     386             : 
     387             :         // move points
     388       28836 :         sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
     389       59054 :         for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     390       30218 :             mpImplPolyPolygon->mpPolyAry[i]->Move( nHorzMove, nVertMove );
     391             :     }
     392       29338 : }
     393             : 
     394           0 : void PolyPolygon::Translate( const Point& rTrans )
     395             : {
     396           0 :     if( mpImplPolyPolygon->mnRefCount > 1 )
     397             :     {
     398           0 :         mpImplPolyPolygon->mnRefCount--;
     399           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     400             :     }
     401             : 
     402             :     // move points
     403           0 :     for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
     404           0 :         mpImplPolyPolygon->mpPolyAry[ i ]->Translate( rTrans );
     405           0 : }
     406             : 
     407        1696 : void PolyPolygon::Scale( double fScaleX, double fScaleY )
     408             : {
     409        1696 :     if( mpImplPolyPolygon->mnRefCount > 1 )
     410             :     {
     411          80 :         mpImplPolyPolygon->mnRefCount--;
     412          80 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     413             :     }
     414             : 
     415             :     // Move points
     416        1776 :     for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
     417          80 :         mpImplPolyPolygon->mpPolyAry[ i ]->Scale( fScaleX, fScaleY );
     418        1696 : }
     419             : 
     420           0 : void PolyPolygon::Rotate( const Point& rCenter, sal_uInt16 nAngle10 )
     421             : {
     422           0 :     nAngle10 %= 3600;
     423             : 
     424           0 :     if( nAngle10 )
     425             :     {
     426           0 :         const double fAngle = F_PI1800 * nAngle10;
     427           0 :         Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
     428             :     }
     429           0 : }
     430             : 
     431         400 : void PolyPolygon::Rotate( const Point& rCenter, double fSin, double fCos )
     432             : {
     433         400 :     if( mpImplPolyPolygon->mnRefCount > 1 )
     434             :     {
     435           0 :         mpImplPolyPolygon->mnRefCount--;
     436           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     437             :     }
     438             : 
     439             :     // move points
     440        1002 :     for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
     441         602 :         mpImplPolyPolygon->mpPolyAry[ i ]->Rotate( rCenter, fSin, fCos );
     442         400 : }
     443             : 
     444          26 : void PolyPolygon::Clip( const Rectangle& rRect )
     445             : {
     446          26 :     sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
     447             :     sal_uInt16 i;
     448             : 
     449          26 :     if ( !nPolyCount )
     450          26 :         return;
     451             : 
     452          26 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     453             :     {
     454          14 :         mpImplPolyPolygon->mnRefCount--;
     455          14 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     456             :     }
     457             : 
     458             :     // Clip every polygon, deleting the empty ones
     459         368 :     for ( i = 0; i < nPolyCount; i++ )
     460         342 :         mpImplPolyPolygon->mpPolyAry[i]->Clip( rRect );
     461         394 :     while ( nPolyCount )
     462             :     {
     463         342 :         if ( GetObject( nPolyCount-1 ).GetSize() <= 2 )
     464          16 :             Remove( nPolyCount-1 );
     465         342 :         nPolyCount--;
     466             :     }
     467             : }
     468             : 
     469      269565 : Rectangle PolyPolygon::GetBoundRect() const
     470             : {
     471      269565 :     long    nXMin=0, nXMax=0, nYMin=0, nYMax=0;
     472      269565 :     bool    bFirst = true;
     473      269565 :     sal_uInt16  nPolyCount = mpImplPolyPolygon->mnCount;
     474             : 
     475      543626 :     for ( sal_uInt16 n = 0; n < nPolyCount; n++ )
     476             :     {
     477      274061 :         const Polygon*  pPoly = mpImplPolyPolygon->mpPolyAry[n];
     478      274061 :         const Point*    pAry = pPoly->GetConstPointAry();
     479      274061 :         sal_uInt16          nPointCount = pPoly->GetSize();
     480             : 
     481     2074514 :         for ( sal_uInt16 i = 0; i < nPointCount; i++ )
     482             :         {
     483     1800453 :             const Point* pPt = &pAry[ i ];
     484             : 
     485     1800453 :             if ( bFirst )
     486             :             {
     487      269565 :                 nXMin = nXMax = pPt->X();
     488      269565 :                 nYMin = nYMax = pPt->Y();
     489      269565 :                 bFirst = false;
     490             :             }
     491             :             else
     492             :             {
     493     1530888 :                 if ( pPt->X() < nXMin )
     494       52154 :                     nXMin = pPt->X();
     495     1530888 :                 if ( pPt->X() > nXMax )
     496      286345 :                     nXMax = pPt->X();
     497     1530888 :                 if ( pPt->Y() < nYMin )
     498       32028 :                     nYMin = pPt->Y();
     499     1530888 :                 if ( pPt->Y() > nYMax )
     500      299143 :                     nYMax = pPt->Y();
     501             :             }
     502             :         }
     503             :     }
     504             : 
     505      269565 :     if ( !bFirst )
     506      269565 :         return Rectangle( nXMin, nYMin, nXMax, nYMax );
     507             :     else
     508           0 :         return Rectangle();
     509             : }
     510             : 
     511      212730 : Polygon& PolyPolygon::operator[]( sal_uInt16 nPos )
     512             : {
     513             :     assert(nPos < Count() && "PolyPolygon::[](): nPos >= nSize");
     514             : 
     515      212730 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     516             :     {
     517      185141 :         mpImplPolyPolygon->mnRefCount--;
     518      185141 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     519             :     }
     520             : 
     521      212730 :     return *(mpImplPolyPolygon->mpPolyAry[nPos]);
     522             : }
     523             : 
     524       18218 : PolyPolygon& PolyPolygon::operator=( const tools::PolyPolygon& rPolyPoly )
     525             : {
     526       18218 :     if (this == &rPolyPoly)
     527         254 :         return *this;
     528             : 
     529             :     DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
     530             : 
     531       17964 :     rPolyPoly.mpImplPolyPolygon->mnRefCount++;
     532             : 
     533       17964 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     534        1742 :         mpImplPolyPolygon->mnRefCount--;
     535             :     else
     536       16222 :         delete mpImplPolyPolygon;
     537             : 
     538       17964 :     mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
     539       17964 :     return *this;
     540             : }
     541             : 
     542           0 : bool PolyPolygon::operator==( const tools::PolyPolygon& rPolyPoly ) const
     543             : {
     544           0 :     if ( rPolyPoly.mpImplPolyPolygon == mpImplPolyPolygon )
     545           0 :         return true;
     546             :     else
     547           0 :         return false;
     548             : }
     549             : 
     550           0 : bool PolyPolygon::IsEqual( const tools::PolyPolygon& rPolyPoly ) const
     551             : {
     552           0 :     bool bIsEqual = true;
     553           0 :     if ( Count() != rPolyPoly.Count() )
     554           0 :         bIsEqual = false;
     555             :     else
     556             :     {
     557             :         sal_uInt16 i;
     558           0 :         for ( i = 0; i < Count(); i++ )
     559             :         {
     560           0 :             if (!GetObject( i ).IsEqual( rPolyPoly.GetObject( i ) ) )
     561             :             {
     562           0 :                 bIsEqual = false;
     563           0 :                 break;
     564             :             }
     565             :         }
     566             :     }
     567           0 :     return bIsEqual;
     568             : }
     569             : 
     570         996 : SvStream& ReadPolyPolygon( SvStream& rIStream, tools::PolyPolygon& rPolyPoly )
     571             : {
     572             :     DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
     573             : 
     574             :     Polygon* pPoly;
     575         996 :     sal_uInt16 nPolyCount(0);
     576             : 
     577             :     // Read number of polygons
     578         996 :     rIStream.ReadUInt16( nPolyCount );
     579             : 
     580         996 :     if( nPolyCount )
     581             :     {
     582         996 :         if ( rPolyPoly.mpImplPolyPolygon->mnRefCount > 1 )
     583           0 :             rPolyPoly.mpImplPolyPolygon->mnRefCount--;
     584             :         else
     585         996 :             delete rPolyPoly.mpImplPolyPolygon;
     586             : 
     587         996 :         rPolyPoly.mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
     588             : 
     589        3128 :         for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     590             :         {
     591        2132 :             pPoly = new Polygon;
     592        2132 :             ReadPolygon( rIStream, *pPoly );
     593        2132 :             rPolyPoly.mpImplPolyPolygon->mpPolyAry[i] = pPoly;
     594             :         }
     595             :     }
     596             :     else
     597           0 :         rPolyPoly = tools::PolyPolygon();
     598             : 
     599         996 :     return rIStream;
     600             : }
     601             : 
     602         238 : SvStream& WritePolyPolygon( SvStream& rOStream, const tools::PolyPolygon& rPolyPoly )
     603             : {
     604             :     DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
     605             : 
     606             :     // Write number of polygons
     607         238 :     sal_uInt16 nPolyCount = rPolyPoly.mpImplPolyPolygon->mnCount;
     608         238 :     rOStream.WriteUInt16( nPolyCount );
     609             : 
     610             :     // output polygons
     611         836 :     for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     612         598 :         WritePolygon( rOStream, *(rPolyPoly.mpImplPolyPolygon->mpPolyAry[i]) );
     613             : 
     614         238 :     return rOStream;
     615             : }
     616             : 
     617        5720 : void PolyPolygon::Read( SvStream& rIStream )
     618             : {
     619        5720 :     VersionCompat aCompat( rIStream, STREAM_READ );
     620             : 
     621             :     DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
     622             : 
     623             :     Polygon* pPoly;
     624        5720 :     sal_uInt16 nPolyCount(0);
     625             : 
     626             :     // Read number of polygons
     627        5720 :     rIStream.ReadUInt16( nPolyCount );
     628             : 
     629        5720 :     if( nPolyCount )
     630             :     {
     631         268 :         if ( mpImplPolyPolygon->mnRefCount > 1 )
     632           0 :             mpImplPolyPolygon->mnRefCount--;
     633             :         else
     634         268 :             delete mpImplPolyPolygon;
     635             : 
     636         268 :         mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
     637             : 
     638         852 :         for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     639             :         {
     640         584 :             pPoly = new Polygon;
     641         584 :             pPoly->ImplRead( rIStream );
     642         584 :             mpImplPolyPolygon->mpPolyAry[i] = pPoly;
     643             :         }
     644             :     }
     645             :     else
     646        5452 :         *this = tools::PolyPolygon();
     647        5720 : }
     648             : 
     649       12586 : void PolyPolygon::Write( SvStream& rOStream ) const
     650             : {
     651       12586 :     VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
     652             : 
     653             :     DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
     654             : 
     655             :     // Write number of polygons
     656       12586 :     sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
     657       12586 :     rOStream.WriteUInt16( nPolyCount );
     658             : 
     659             :     // Output polygons
     660       13756 :     for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     661       13756 :         mpImplPolyPolygon->mpPolyAry[i]->ImplWrite( rOStream );
     662       12586 : }
     663             : 
     664             : // convert to basegfx::B2DPolyPolygon and return
     665        5627 : basegfx::B2DPolyPolygon PolyPolygon::getB2DPolyPolygon() const
     666             : {
     667        5627 :     basegfx::B2DPolyPolygon aRetval;
     668             : 
     669       13559 :     for(sal_uInt16 a(0); a < mpImplPolyPolygon->mnCount; a++)
     670             :     {
     671        7932 :         Polygon* pCandidate = mpImplPolyPolygon->mpPolyAry[a];
     672        7932 :         aRetval.append(pCandidate->getB2DPolygon());
     673             :     }
     674             : 
     675        5627 :     return aRetval;
     676             : }
     677             : 
     678             : // constructor to convert from basegfx::B2DPolyPolygon
     679       61490 : PolyPolygon::PolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
     680             : {
     681       61490 :     const sal_uInt16 nCount(sal_uInt16(rPolyPolygon.count()));
     682             :     DBG_ASSERT(sal_uInt32(nCount) == rPolyPolygon.count(),
     683             :         "PolyPolygon::PolyPolygon: Too many sub-polygons in given basegfx::B2DPolyPolygon (!)");
     684             : 
     685       61490 :     if ( nCount )
     686             :     {
     687       54894 :         mpImplPolyPolygon = new ImplPolyPolygon( nCount );
     688             : 
     689      126910 :         for(sal_uInt16 a(0); a < nCount; a++)
     690             :         {
     691       72016 :             basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(sal_uInt32(a)));
     692       72016 :             mpImplPolyPolygon->mpPolyAry[a] = new Polygon( aCandidate );
     693       72016 :         }
     694             :     }
     695             :     else
     696             :     {
     697        6596 :         mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
     698             :     }
     699       61490 : }
     700             : 
     701             : } /* namespace tools */
     702             : 
     703             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10