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

Generated by: LCOV version 1.11