LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/tools/source/generic - poly2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 195 328 59.5 %
Date: 2013-07-09 Functions: 24 36 66.7 %
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             : DBG_NAME( PolyPolygon )
      37             : 
      38      173488 : ImplPolyPolygon::ImplPolyPolygon( sal_uInt16 nInitSize )
      39             : {
      40      173488 :     mnRefCount  = 1;
      41      173488 :     mnCount     = nInitSize;
      42      173488 :     mnSize      = nInitSize;
      43      173488 :     mnResize    = 16;
      44      173488 :     mpPolyAry   = new SVPPOLYGON[ nInitSize ];
      45      173488 : }
      46             : 
      47       66212 : ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon& rImplPolyPoly )
      48             : {
      49       66212 :     mnRefCount  = 1;
      50       66212 :     mnCount     = rImplPolyPoly.mnCount;
      51       66212 :     mnSize      = rImplPolyPoly.mnSize;
      52       66212 :     mnResize    = rImplPolyPoly.mnResize;
      53             : 
      54       66212 :     if ( rImplPolyPoly.mpPolyAry )
      55             :     {
      56       65935 :         mpPolyAry = new SVPPOLYGON[mnSize];
      57      133910 :         for ( sal_uInt16 i = 0; i < mnCount; i++ )
      58       67975 :             mpPolyAry[i] = new Polygon( *rImplPolyPoly.mpPolyAry[i] );
      59             :     }
      60             :     else
      61         277 :         mpPolyAry = NULL;
      62       66212 : }
      63             : 
      64      260340 : ImplPolyPolygon::~ImplPolyPolygon()
      65             : {
      66      260340 :     if ( mpPolyAry )
      67             :     {
      68      508563 :         for ( sal_uInt16 i = 0; i < mnCount; i++ )
      69      259640 :             delete mpPolyAry[i];
      70      248923 :         delete[] mpPolyAry;
      71             :     }
      72      260340 : }
      73             : 
      74       20343 : PolyPolygon::PolyPolygon( sal_uInt16 nInitSize, sal_uInt16 nResize )
      75             : {
      76             :     DBG_CTOR( PolyPolygon, NULL );
      77             : 
      78       20343 :     if ( nInitSize > MAX_POLYGONS )
      79           0 :         nInitSize = MAX_POLYGONS;
      80       20343 :     else if ( !nInitSize )
      81           0 :         nInitSize = 1;
      82       20343 :     if ( nResize > MAX_POLYGONS )
      83           0 :         nResize = MAX_POLYGONS;
      84       20343 :     else if ( !nResize )
      85           0 :         nResize = 1;
      86       20343 :     mpImplPolyPolygon = new ImplPolyPolygon( nInitSize, nResize );
      87       20343 : }
      88             : 
      89        2367 : PolyPolygon::PolyPolygon( const Polygon& rPoly )
      90             : {
      91             :     DBG_CTOR( PolyPolygon, NULL );
      92             : 
      93        2367 :     if ( rPoly.GetSize() )
      94             :     {
      95        2367 :         mpImplPolyPolygon = new ImplPolyPolygon( 1 );
      96        2367 :         mpImplPolyPolygon->mpPolyAry[0] = new Polygon( rPoly );
      97             :     }
      98             :     else
      99           0 :         mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
     100        2367 : }
     101             : 
     102      116476 : PolyPolygon::PolyPolygon( const PolyPolygon& rPolyPoly )
     103             : {
     104             :     DBG_CTOR( PolyPolygon, NULL );
     105             :     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
     106             :     DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
     107             : 
     108      116476 :     mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
     109      116476 :     mpImplPolyPolygon->mnRefCount++;
     110      116476 : }
     111             : 
     112      310593 : PolyPolygon::~PolyPolygon()
     113             : {
     114             :     DBG_DTOR( PolyPolygon, NULL );
     115             : 
     116      310593 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     117       51275 :         mpImplPolyPolygon->mnRefCount--;
     118             :     else
     119      259318 :         delete mpImplPolyPolygon;
     120      310593 : }
     121             : 
     122       13694 : void PolyPolygon::Insert( const Polygon& rPoly, sal_uInt16 nPos )
     123             : {
     124             :     DBG_CHKTHIS( PolyPolygon, NULL );
     125             : 
     126       13694 :     if ( mpImplPolyPolygon->mnCount >= MAX_POLYGONS )
     127       13694 :         return;
     128             : 
     129       13694 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     130             :     {
     131           0 :         mpImplPolyPolygon->mnRefCount--;
     132           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     133             :     }
     134             : 
     135       13694 :     if ( nPos > mpImplPolyPolygon->mnCount )
     136       13689 :         nPos = mpImplPolyPolygon->mnCount;
     137             : 
     138       13694 :     if ( !mpImplPolyPolygon->mpPolyAry )
     139        9506 :         mpImplPolyPolygon->mpPolyAry = new SVPPOLYGON[mpImplPolyPolygon->mnSize];
     140        4188 :     else if ( mpImplPolyPolygon->mnCount == mpImplPolyPolygon->mnSize )
     141             :     {
     142           0 :         sal_uInt16      nOldSize = mpImplPolyPolygon->mnSize;
     143           0 :         sal_uInt16      nNewSize = nOldSize + mpImplPolyPolygon->mnResize;
     144             :         SVPPOLYGON* pNewAry;
     145             : 
     146           0 :         if ( nNewSize >= MAX_POLYGONS )
     147           0 :             nNewSize = MAX_POLYGONS;
     148           0 :         pNewAry = new SVPPOLYGON[nNewSize];
     149           0 :         memcpy( pNewAry, mpImplPolyPolygon->mpPolyAry, nPos*sizeof(SVPPOLYGON) );
     150           0 :         memcpy( pNewAry+nPos+1, mpImplPolyPolygon->mpPolyAry+nPos,
     151           0 :                 (nOldSize-nPos)*sizeof(SVPPOLYGON) );
     152           0 :         delete[] mpImplPolyPolygon->mpPolyAry;
     153           0 :         mpImplPolyPolygon->mpPolyAry = pNewAry;
     154           0 :         mpImplPolyPolygon->mnSize = nNewSize;
     155             :     }
     156        4188 :     else if ( nPos < mpImplPolyPolygon->mnCount )
     157             :     {
     158           0 :         memmove( mpImplPolyPolygon->mpPolyAry+nPos+1,
     159             :                  mpImplPolyPolygon->mpPolyAry+nPos,
     160           0 :                  (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
     161             :     }
     162             : 
     163       13694 :     mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
     164       13694 :     mpImplPolyPolygon->mnCount++;
     165             : }
     166             : 
     167           0 : void PolyPolygon::Remove( sal_uInt16 nPos )
     168             : {
     169             :     DBG_CHKTHIS( PolyPolygon, NULL );
     170             :     DBG_ASSERT( nPos < Count(), "PolyPolygon::Remove(): nPos >= nSize" );
     171             : 
     172           0 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     173             :     {
     174           0 :         mpImplPolyPolygon->mnRefCount--;
     175           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     176             :     }
     177             : 
     178           0 :     delete mpImplPolyPolygon->mpPolyAry[nPos];
     179           0 :     mpImplPolyPolygon->mnCount--;
     180           0 :     memmove( mpImplPolyPolygon->mpPolyAry+nPos,
     181           0 :              mpImplPolyPolygon->mpPolyAry+nPos+1,
     182           0 :              (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
     183           0 : }
     184             : 
     185           0 : void PolyPolygon::Replace( const Polygon& rPoly, sal_uInt16 nPos )
     186             : {
     187             :     DBG_CHKTHIS( PolyPolygon, NULL );
     188             :     DBG_ASSERT( nPos < Count(), "PolyPolygon::Replace(): nPos >= nSize" );
     189             : 
     190           0 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     191             :     {
     192           0 :         mpImplPolyPolygon->mnRefCount--;
     193           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     194             :     }
     195             : 
     196           0 :     delete mpImplPolyPolygon->mpPolyAry[nPos];
     197           0 :     mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
     198           0 : }
     199             : 
     200      239958 : const Polygon& PolyPolygon::GetObject( sal_uInt16 nPos ) const
     201             : {
     202             :     DBG_CHKTHIS( PolyPolygon, NULL );
     203             :     DBG_ASSERT( nPos < Count(), "PolyPolygon::GetObject(): nPos >= nSize" );
     204             : 
     205      239958 :     return *(mpImplPolyPolygon->mpPolyAry[nPos]);
     206             : }
     207             : 
     208        2993 : bool PolyPolygon::IsRect() const
     209             : {
     210        2993 :     bool bIsRect = false;
     211        2993 :     if ( Count() == 1 )
     212        2885 :         bIsRect = mpImplPolyPolygon->mpPolyAry[ 0 ]->IsRect();
     213        2993 :     return bIsRect;
     214             : }
     215             : 
     216          51 : void PolyPolygon::Clear()
     217             : {
     218             :     DBG_CHKTHIS( PolyPolygon, NULL );
     219             : 
     220          51 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     221             :     {
     222          10 :         mpImplPolyPolygon->mnRefCount--;
     223             :         mpImplPolyPolygon = new ImplPolyPolygon( mpImplPolyPolygon->mnResize,
     224          10 :                                                  mpImplPolyPolygon->mnResize );
     225             :     }
     226             :     else
     227             :     {
     228          41 :         if ( mpImplPolyPolygon->mpPolyAry )
     229             :         {
     230          12 :             for ( sal_uInt16 i = 0; i < mpImplPolyPolygon->mnCount; i++ )
     231           6 :                 delete mpImplPolyPolygon->mpPolyAry[i];
     232           6 :             delete[] mpImplPolyPolygon->mpPolyAry;
     233           6 :             mpImplPolyPolygon->mpPolyAry = NULL;
     234           6 :             mpImplPolyPolygon->mnCount   = 0;
     235           6 :             mpImplPolyPolygon->mnSize    = mpImplPolyPolygon->mnResize;
     236             :         }
     237             :     }
     238          51 : }
     239             : 
     240         240 : void PolyPolygon::Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData )
     241             : {
     242             :     DBG_CHKTHIS( PolyPolygon, NULL );
     243             : 
     244         240 :     if(nOptimizeFlags && Count())
     245             :     {
     246             :         // #115630# ImplDrawHatch does not work with beziers included in the polypolygon, take care of that
     247         238 :         bool bIsCurve(false);
     248             : 
     249         476 :         for(sal_uInt16 a(0); !bIsCurve && a < Count(); a++)
     250             :         {
     251         238 :             if((*this)[a].HasFlags())
     252             :             {
     253           0 :                 bIsCurve = true;
     254             :             }
     255             :         }
     256             : 
     257         238 :         if(bIsCurve)
     258             :         {
     259             :             OSL_ENSURE(false, "Optimize does *not* support curves, falling back to AdaptiveSubdivide()...");
     260           0 :             PolyPolygon aPolyPoly;
     261             : 
     262           0 :             AdaptiveSubdivide(aPolyPoly);
     263           0 :             aPolyPoly.Optimize(nOptimizeFlags, pData);
     264           0 :             *this = aPolyPoly;
     265             :         }
     266             :         else
     267             :         {
     268             :             double      fArea;
     269         238 :             const bool  bEdges = ( nOptimizeFlags & POLY_OPTIMIZE_EDGES ) == POLY_OPTIMIZE_EDGES;
     270         238 :             sal_uInt16      nPercent = 0;
     271             : 
     272         238 :             if( bEdges )
     273             :             {
     274           0 :                 const Rectangle aBound( GetBoundRect() );
     275             : 
     276           0 :                 fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
     277           0 :                 nPercent = pData ? pData->GetPercentValue() : 50;
     278           0 :                 nOptimizeFlags &= ~POLY_OPTIMIZE_EDGES;
     279             :             }
     280             : 
     281             :             // watch for ref counter
     282         238 :             if( mpImplPolyPolygon->mnRefCount > 1 )
     283             :             {
     284           0 :                 mpImplPolyPolygon->mnRefCount--;
     285           0 :                 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     286             :             }
     287             : 
     288             :             // Optimize polygons
     289         476 :             for( sal_uInt16 i = 0, nPolyCount = mpImplPolyPolygon->mnCount; i < nPolyCount; i++ )
     290             :             {
     291         238 :                 if( bEdges )
     292             :                 {
     293           0 :                     mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( POLY_OPTIMIZE_NO_SAME );
     294           0 :                     Polygon::ImplReduceEdges( *( mpImplPolyPolygon->mpPolyAry[ i ] ), fArea, nPercent );
     295             :                 }
     296             : 
     297         238 :                 if( nOptimizeFlags )
     298         238 :                     mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( nOptimizeFlags, pData );
     299             :             }
     300             :         }
     301             :     }
     302         240 : }
     303             : 
     304          22 : void PolyPolygon::AdaptiveSubdivide( PolyPolygon& rResult, const double d ) const
     305             : {
     306             :     DBG_CHKTHIS( PolyPolygon, NULL );
     307             : 
     308          22 :     rResult.Clear();
     309             : 
     310          22 :     Polygon aPolygon;
     311             : 
     312          52 :     for( sal_uInt16 i = 0; i < mpImplPolyPolygon->mnCount; i++ )
     313             :     {
     314          30 :         mpImplPolyPolygon->mpPolyAry[ i ]->AdaptiveSubdivide( aPolygon, d );
     315          30 :         rResult.Insert( aPolygon );
     316          22 :     }
     317          22 : }
     318             : 
     319           0 : void PolyPolygon::GetIntersection( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
     320             : {
     321           0 :     ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_INT );
     322           0 : }
     323             : 
     324           7 : void PolyPolygon::GetUnion( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
     325             : {
     326           7 :     ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_UNION );
     327           7 : }
     328             : 
     329           7 : void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, sal_uIntPtr nOperation ) const
     330             : {
     331             :     // Convert to B2DPolyPolygon, temporarily. It might be
     332             :     // advantageous in the future, to have a PolyPolygon adaptor that
     333             :     // just simulates a B2DPolyPolygon here...
     334           7 :     basegfx::B2DPolyPolygon aMergePolyPolygonA( getB2DPolyPolygon() );
     335          14 :     basegfx::B2DPolyPolygon aMergePolyPolygonB( rPolyPoly.getB2DPolyPolygon() );
     336             : 
     337             :     // normalize the two polypolygons before. Force properly oriented
     338             :     // polygons.
     339           7 :     aMergePolyPolygonA = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA );
     340           7 :     aMergePolyPolygonB = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB );
     341             : 
     342           7 :     switch( nOperation )
     343             :     {
     344             :         // All code extracted from svx/source/svdraw/svedtv2.cxx
     345             : 
     346             :         case POLY_CLIP_UNION:
     347             :         {
     348             :             // merge A and B (OR)
     349           7 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
     350           7 :             break;
     351             :         }
     352             : 
     353             :         case POLY_CLIP_DIFF:
     354             :         {
     355             :             // substract B from A (DIFF)
     356           0 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
     357           0 :             break;
     358             :         }
     359             : 
     360             :         case POLY_CLIP_XOR:
     361             :         {
     362             :             // compute XOR between poly A and B
     363           0 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
     364           0 :             break;
     365             :         }
     366             : 
     367             :         default:
     368             :         case POLY_CLIP_INT:
     369             :         {
     370             :             // cut poly 1 against polys 2..n (AND)
     371           0 :             aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
     372           0 :             break;
     373             :         }
     374             :     }
     375             : 
     376          14 :     rResult = PolyPolygon( aMergePolyPolygonA );
     377           7 : }
     378             : 
     379      304875 : sal_uInt16 PolyPolygon::Count() const
     380             : {
     381             :     DBG_CHKTHIS( PolyPolygon, NULL );
     382      304875 :     return mpImplPolyPolygon->mnCount;
     383             : }
     384             : 
     385       18299 : void PolyPolygon::Move( long nHorzMove, long nVertMove )
     386             : {
     387             :     DBG_CHKTHIS( PolyPolygon, NULL );
     388             : 
     389             :     // Required for DrawEngine
     390       18299 :     if( nHorzMove || nVertMove )
     391             :     {
     392       18299 :         if ( mpImplPolyPolygon->mnRefCount > 1 )
     393             :         {
     394       18198 :             mpImplPolyPolygon->mnRefCount--;
     395       18198 :             mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     396             :         }
     397             : 
     398             :         // move points
     399       18299 :         sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
     400       38203 :         for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     401       19904 :             mpImplPolyPolygon->mpPolyAry[i]->Move( nHorzMove, nVertMove );
     402             :     }
     403       18299 : }
     404             : 
     405           0 : void PolyPolygon::Translate( const Point& rTrans )
     406             : {
     407             :     DBG_CHKTHIS( PolyPolygon, NULL );
     408             : 
     409           0 :     if( mpImplPolyPolygon->mnRefCount > 1 )
     410             :     {
     411           0 :         mpImplPolyPolygon->mnRefCount--;
     412           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     413             :     }
     414             : 
     415             :     // move points
     416           0 :     for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
     417           0 :         mpImplPolyPolygon->mpPolyAry[ i ]->Translate( rTrans );
     418           0 : }
     419             : 
     420           0 : void PolyPolygon::Scale( double fScaleX, double fScaleY )
     421             : {
     422             :     DBG_CHKTHIS( PolyPolygon, NULL );
     423             : 
     424           0 :     if( mpImplPolyPolygon->mnRefCount > 1 )
     425             :     {
     426           0 :         mpImplPolyPolygon->mnRefCount--;
     427           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     428             :     }
     429             : 
     430             :     // Move points
     431           0 :     for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
     432           0 :         mpImplPolyPolygon->mpPolyAry[ i ]->Scale( fScaleX, fScaleY );
     433           0 : }
     434             : 
     435           0 : void PolyPolygon::Rotate( const Point& rCenter, sal_uInt16 nAngle10 )
     436             : {
     437             :     DBG_CHKTHIS( PolyPolygon, NULL );
     438           0 :     nAngle10 %= 3600;
     439             : 
     440           0 :     if( nAngle10 )
     441             :     {
     442           0 :         const double fAngle = F_PI1800 * nAngle10;
     443           0 :         Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
     444             :     }
     445           0 : }
     446             : 
     447           0 : void PolyPolygon::Rotate( const Point& rCenter, double fSin, double fCos )
     448             : {
     449             :     DBG_CHKTHIS( PolyPolygon, NULL );
     450             : 
     451           0 :     if( mpImplPolyPolygon->mnRefCount > 1 )
     452             :     {
     453           0 :         mpImplPolyPolygon->mnRefCount--;
     454           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     455             :     }
     456             : 
     457             :     // move points
     458           0 :     for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
     459           0 :         mpImplPolyPolygon->mpPolyAry[ i ]->Rotate( rCenter, fSin, fCos );
     460           0 : }
     461             : 
     462           0 : void PolyPolygon::Clip( const Rectangle& rRect )
     463             : {
     464           0 :     sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
     465             :     sal_uInt16 i;
     466             : 
     467           0 :     if ( !nPolyCount )
     468           0 :         return;
     469             : 
     470           0 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     471             :     {
     472           0 :         mpImplPolyPolygon->mnRefCount--;
     473           0 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     474             :     }
     475             : 
     476             :     // Clip every polygon, deleting the empty ones
     477           0 :     for ( i = 0; i < nPolyCount; i++ )
     478           0 :         mpImplPolyPolygon->mpPolyAry[i]->Clip( rRect );
     479           0 :     while ( nPolyCount )
     480             :     {
     481           0 :         if ( GetObject( nPolyCount-1 ).GetSize() <= 2 )
     482           0 :             Remove( nPolyCount-1 );
     483           0 :         nPolyCount--;
     484             :     }
     485             : }
     486             : 
     487        3282 : Rectangle PolyPolygon::GetBoundRect() const
     488             : {
     489             :     DBG_CHKTHIS( PolyPolygon, NULL );
     490             : 
     491        3282 :     long    nXMin=0, nXMax=0, nYMin=0, nYMax=0;
     492        3282 :     bool    bFirst = true;
     493        3282 :     sal_uInt16  nPolyCount = mpImplPolyPolygon->mnCount;
     494             : 
     495        8302 :     for ( sal_uInt16 n = 0; n < nPolyCount; n++ )
     496             :     {
     497        5020 :         const Polygon*  pPoly = mpImplPolyPolygon->mpPolyAry[n];
     498        5020 :         const Point*    pAry = pPoly->GetConstPointAry();
     499        5020 :         sal_uInt16          nPointCount = pPoly->GetSize();
     500             : 
     501      103071 :         for ( sal_uInt16 i = 0; i < nPointCount; i++ )
     502             :         {
     503       98051 :             const Point* pPt = &pAry[ i ];
     504             : 
     505       98051 :             if ( bFirst )
     506             :             {
     507        3282 :                 nXMin = nXMax = pPt->X();
     508        3282 :                 nYMin = nYMax = pPt->Y();
     509        3282 :                 bFirst = false;
     510             :             }
     511             :             else
     512             :             {
     513       94769 :                 if ( pPt->X() < nXMin )
     514       14455 :                     nXMin = pPt->X();
     515       94769 :                 if ( pPt->X() > nXMax )
     516        2316 :                     nXMax = pPt->X();
     517       94769 :                 if ( pPt->Y() < nYMin )
     518        7321 :                     nYMin = pPt->Y();
     519       94769 :                 if ( pPt->Y() > nYMax )
     520        9195 :                     nYMax = pPt->Y();
     521             :             }
     522             :         }
     523             :     }
     524             : 
     525        3282 :     if ( !bFirst )
     526        3282 :         return Rectangle( nXMin, nYMin, nXMax, nYMax );
     527             :     else
     528           0 :         return Rectangle();
     529             : }
     530             : 
     531       48753 : Polygon& PolyPolygon::operator[]( sal_uInt16 nPos )
     532             : {
     533             :     DBG_CHKTHIS( PolyPolygon, NULL );
     534             :     DBG_ASSERT( nPos < Count(), "PolyPolygon::[](): nPos >= nSize" );
     535             : 
     536       48753 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     537             :     {
     538       48014 :         mpImplPolyPolygon->mnRefCount--;
     539       48014 :         mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
     540             :     }
     541             : 
     542       48753 :     return *(mpImplPolyPolygon->mpPolyAry[nPos]);
     543             : }
     544             : 
     545        1174 : PolyPolygon& PolyPolygon::operator=( const PolyPolygon& rPolyPoly )
     546             : {
     547             :     DBG_CHKTHIS( PolyPolygon, NULL );
     548             :     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
     549             :     DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
     550             : 
     551        1174 :     rPolyPoly.mpImplPolyPolygon->mnRefCount++;
     552             : 
     553        1174 :     if ( mpImplPolyPolygon->mnRefCount > 1 )
     554         153 :         mpImplPolyPolygon->mnRefCount--;
     555             :     else
     556        1021 :         delete mpImplPolyPolygon;
     557             : 
     558        1174 :     mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
     559        1174 :     return *this;
     560             : }
     561             : 
     562           0 : bool PolyPolygon::operator==( const PolyPolygon& rPolyPoly ) const
     563             : {
     564             :     DBG_CHKTHIS( PolyPolygon, NULL );
     565             :     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
     566             : 
     567           0 :     if ( rPolyPoly.mpImplPolyPolygon == mpImplPolyPolygon )
     568           0 :         return true;
     569             :     else
     570           0 :         return false;
     571             : }
     572             : 
     573           0 : bool PolyPolygon::IsEqual( const PolyPolygon& rPolyPoly ) const
     574             : {
     575           0 :     bool bIsEqual = true;
     576           0 :     if ( Count() != rPolyPoly.Count() )
     577           0 :         bIsEqual = false;
     578             :     else
     579             :     {
     580             :         sal_uInt16 i;
     581           0 :         for ( i = 0; i < Count(); i++ )
     582             :         {
     583           0 :             if (!GetObject( i ).IsEqual( rPolyPoly.GetObject( i ) ) )
     584             :             {
     585           0 :                 bIsEqual = false;
     586           0 :                 break;
     587             :             }
     588             :         }
     589             :     }
     590           0 :     return bIsEqual;
     591             : }
     592             : 
     593           0 : SvStream& operator>>( SvStream& rIStream, PolyPolygon& rPolyPoly )
     594             : {
     595             :     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
     596             :     DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
     597             : 
     598             :     Polygon* pPoly;
     599             :     sal_uInt16   nPolyCount;
     600             : 
     601             :     // read number of polygons
     602           0 :     rIStream >> nPolyCount;
     603             : 
     604           0 :     if( nPolyCount )
     605             :     {
     606           0 :         if ( rPolyPoly.mpImplPolyPolygon->mnRefCount > 1 )
     607           0 :             rPolyPoly.mpImplPolyPolygon->mnRefCount--;
     608             :         else
     609           0 :             delete rPolyPoly.mpImplPolyPolygon;
     610             : 
     611           0 :         rPolyPoly.mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
     612             : 
     613           0 :         for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     614             :         {
     615           0 :             pPoly = new Polygon;
     616           0 :             rIStream >> *pPoly;
     617           0 :             rPolyPoly.mpImplPolyPolygon->mpPolyAry[i] = pPoly;
     618             :         }
     619             :     }
     620             :     else
     621           0 :         rPolyPoly = PolyPolygon();
     622             : 
     623           0 :     return rIStream;
     624             : }
     625             : 
     626           0 : SvStream& operator<<( SvStream& rOStream, const PolyPolygon& rPolyPoly )
     627             : {
     628             :     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
     629             :     DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
     630             : 
     631             :     // Write number of polygons
     632           0 :     sal_uInt16 nPolyCount = rPolyPoly.mpImplPolyPolygon->mnCount;
     633           0 :     rOStream << nPolyCount;
     634             : 
     635             :     // output polygons
     636           0 :     for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     637           0 :         rOStream << *(rPolyPoly.mpImplPolyPolygon->mpPolyAry[i]);
     638             : 
     639           0 :     return rOStream;
     640             : }
     641             : 
     642         278 : void PolyPolygon::Read( SvStream& rIStream )
     643             : {
     644         278 :     VersionCompat aCompat( rIStream, STREAM_READ );
     645             : 
     646             :     DBG_CHKTHIS( PolyPolygon, NULL );
     647             :     DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
     648             : 
     649             :     Polygon* pPoly;
     650             :     sal_uInt16   nPolyCount;
     651             : 
     652             :     // Read number of polygons
     653         278 :     rIStream >> nPolyCount;
     654             : 
     655         278 :     if( nPolyCount )
     656             :     {
     657           1 :         if ( mpImplPolyPolygon->mnRefCount > 1 )
     658           0 :             mpImplPolyPolygon->mnRefCount--;
     659             :         else
     660           1 :             delete mpImplPolyPolygon;
     661             : 
     662           1 :         mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
     663             : 
     664           2 :         for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     665             :         {
     666           1 :             pPoly = new Polygon;
     667           1 :             pPoly->ImplRead( rIStream );
     668           1 :             mpImplPolyPolygon->mpPolyAry[i] = pPoly;
     669             :         }
     670             :     }
     671             :     else
     672         277 :         *this = PolyPolygon();
     673         278 : }
     674             : 
     675         566 : void PolyPolygon::Write( SvStream& rOStream ) const
     676             : {
     677         566 :     VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
     678             : 
     679             :     DBG_CHKTHIS( PolyPolygon, NULL );
     680             :     DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
     681             : 
     682             :     // Write number of polygons
     683         566 :     sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
     684         566 :     rOStream << nPolyCount;
     685             : 
     686             :     // Output polygons
     687         568 :     for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
     688         568 :         mpImplPolyPolygon->mpPolyAry[i]->ImplWrite( rOStream );
     689         566 : }
     690             : 
     691             : // convert to basegfx::B2DPolyPolygon and return
     692        1067 : basegfx::B2DPolyPolygon PolyPolygon::getB2DPolyPolygon() const
     693             : {
     694        1067 :     basegfx::B2DPolyPolygon aRetval;
     695             : 
     696        2671 :     for(sal_uInt16 a(0); a < mpImplPolyPolygon->mnCount; a++)
     697             :     {
     698        1604 :         Polygon* pCandidate = mpImplPolyPolygon->mpPolyAry[a];
     699        1604 :         aRetval.append(pCandidate->getB2DPolygon());
     700             :     }
     701             : 
     702        1067 :     return aRetval;
     703             : }
     704             : 
     705             : // constructor to convert from basegfx::B2DPolyPolygon
     706      171407 : PolyPolygon::PolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
     707             : {
     708             :     DBG_CTOR( PolyPolygon, NULL );
     709      171407 :     const sal_uInt16 nCount(sal_uInt16(rPolyPolygon.count()));
     710             :     DBG_ASSERT(sal_uInt32(nCount) == rPolyPolygon.count(),
     711             :         "PolyPolygon::PolyPolygon: Too many sub-polygons in given basegfx::B2DPolyPolygon (!)");
     712             : 
     713      171407 :     if ( nCount )
     714             :     {
     715      171120 :         mpImplPolyPolygon = new ImplPolyPolygon( nCount );
     716             : 
     717      346729 :         for(sal_uInt16 a(0); a < nCount; a++)
     718             :         {
     719      175609 :             basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(sal_uInt32(a)));
     720      175609 :             mpImplPolyPolygon->mpPolyAry[a] = new Polygon( aCandidate );
     721      175609 :         }
     722             :     }
     723             :     else
     724             :     {
     725         287 :         mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
     726             :     }
     727      171407 : }
     728             : 
     729             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10