LCOV - code coverage report
Current view: top level - vcl/source/gdi - region.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 809 1182 68.4 %
Date: 2012-08-25 Functions: 63 79 79.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 631 1469 43.0 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <limits.h>
      31                 :            : 
      32                 :            : #include <tools/vcompat.hxx>
      33                 :            : #include <tools/stream.hxx>
      34                 :            : #include <tools/debug.hxx>
      35                 :            : #include <tools/helpers.hxx>
      36                 :            : #include <vcl/region.hxx>
      37                 :            : #include <vcl/regband.hxx>
      38                 :            : 
      39                 :            : #include <region.h>
      40                 :            : 
      41                 :            : #include <basegfx/matrix/b2dhommatrix.hxx>
      42                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      43                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      44                 :            : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      45                 :            : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
      46                 :            : #include <basegfx/range/b2drange.hxx>
      47                 :            : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      48                 :            : 
      49                 :            : // =======================================================================
      50                 :            : //
      51                 :            : // ImplRegionBand
      52                 :            : //
      53                 :            : // Die Klassen RegionBand/ImplRegionBand speichert Regionen in Form von
      54                 :            : // Rechtecken ab. Die Region ist in Y-Richtung in Baendern unterteilt, die
      55                 :            : // wiederum ein oder mehrere Rechtecke mit der Hoehe des Bandes enthalten.
      56                 :            : //
      57                 :            : // Leere Baender werden entfernt.
      58                 :            : //
      59                 :            : // Polygone und PolyPolygone werden ebenfalls in Rechtecke zerlegt und in
      60                 :            : // der Baendern abgelegt. Hierzu werden alle Punkte der einzelnen Polygone
      61                 :            : // mit dem Bresenham-Algorithmus berechnet und in die Baender eingetragen.
      62                 :            : // Nach der vollstaendigen Berechung aller Kanten werden die entsprechenden
      63                 :            : // Rechntecke berechnet
      64                 :            : 
      65                 :            : // =======================================================================
      66                 :            : 
      67                 :        347 : static ImplRegionBase aImplNullRegion( 0 );
      68                 :        347 : static ImplRegionBase aImplEmptyRegion( 0 );
      69                 :            : 
      70                 :            : // =======================================================================
      71                 :            : 
      72                 :            : DBG_NAME( Region )
      73                 :            : DBG_NAMEEX( Polygon )
      74                 :            : DBG_NAMEEX( PolyPolygon )
      75                 :            : 
      76                 :            : namespace {
      77                 :            : 
      78                 :            : /** Return <TRUE/> when the given polygon is rectiliner and oriented so that
      79                 :            :     all sides are either horizontal or vertical.
      80                 :            : */
      81                 :         26 : bool ImplIsPolygonRectilinear (const PolyPolygon& rPolyPoly)
      82                 :            : {
      83                 :            :     // Iterate over all polygons.
      84                 :         26 :     const sal_uInt16 nPolyCount = rPolyPoly.Count();
      85         [ +  + ]:         60 :     for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
      86                 :            :     {
      87         [ +  - ]:         34 :         const Polygon&  aPoly = rPolyPoly.GetObject(nPoly);
      88                 :            : 
      89                 :            :         // Iterate over all edges of the current polygon.
      90         [ +  - ]:         34 :         const sal_uInt16 nSize = aPoly.GetSize();
      91                 :            : 
      92         [ -  + ]:         34 :         if (nSize < 2)
      93                 :          0 :             continue;
      94         [ +  - ]:         34 :         Point aPoint (aPoly.GetPoint(0));
      95                 :         34 :         const Point aLastPoint (aPoint);
      96         [ +  + ]:        170 :         for (sal_uInt16 nPoint = 1; nPoint < nSize; ++nPoint)
      97                 :            :         {
      98         [ +  - ]:        136 :             const Point aNextPoint (aPoly.GetPoint(nPoint));
      99                 :            :             // When there is at least one edge that is neither vertical nor
     100                 :            :             // horizontal then the entire polygon is not rectilinear (and
     101                 :            :             // oriented along primary axes.)
     102 [ +  + ][ -  + ]:        136 :             if (aPoint.X() != aNextPoint.X() && aPoint.Y() != aNextPoint.Y())
                 [ -  + ]
     103                 :          0 :                 return false;
     104                 :            : 
     105                 :        136 :             aPoint = aNextPoint;
     106                 :            :         }
     107                 :            :         // Compare closing edge.
     108 [ -  + ][ #  # ]:         34 :         if (aLastPoint.X() != aPoint.X() && aLastPoint.Y() != aPoint.Y())
                 [ -  + ]
     109                 :         34 :             return false;
     110                 :            :     }
     111                 :         26 :     return true;
     112                 :            : }
     113                 :            : 
     114                 :            : 
     115                 :            : 
     116                 :            : /** This function is similar to the ImplRegion::InsertBands() method.
     117                 :            :     It creates a minimal set of missing bands so that the entire vertical
     118                 :            :     interval from nTop to nBottom is covered by bands.
     119                 :            : */
     120                 :         68 : void ImplAddMissingBands (
     121                 :            :     ImplRegion* pImplRegion,
     122                 :            :     const long nTop,
     123                 :            :     const long nBottom)
     124                 :            : {
     125                 :            :     // Iterate over already existing bands and add missing bands atop the
     126                 :            :     // first and between two bands.
     127                 :         68 :     ImplRegionBand* pPreviousBand = NULL;
     128                 :         68 :     ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
     129                 :         68 :     long nCurrentTop (nTop);
     130 [ +  + ][ +  - ]:        118 :     while (pBand != NULL && nCurrentTop<nBottom)
                 [ +  + ]
     131                 :            :     {
     132         [ -  + ]:         50 :         if (nCurrentTop < pBand->mnYTop)
     133                 :            :         {
     134                 :            :             // Create new band above the current band.
     135                 :            :             ImplRegionBand* pAboveBand = new ImplRegionBand(
     136                 :            :                 nCurrentTop,
     137 [ #  # ][ #  # ]:          0 :                 ::std::min(nBottom,pBand->mnYTop-1));
                 [ #  # ]
     138                 :          0 :             pImplRegion->InsertBand(pPreviousBand, pAboveBand);
     139                 :            :         }
     140                 :            : 
     141                 :            :         // Adapt the top of the interval to prevent overlapping bands.
     142         [ +  - ]:         50 :         nCurrentTop = ::std::max(nTop, pBand->mnYBottom+1);
     143                 :            : 
     144                 :            :         // Advance to next band.
     145                 :         50 :         pPreviousBand = pBand;
     146                 :         50 :         pBand = pBand->mpNextBand;
     147                 :            :     }
     148                 :            : 
     149                 :            :     // We still have to cover two cases:
     150                 :            :     // 1. The region does not yet contain any bands.
     151                 :            :     // 2. The intervall nTop->nBottom extends past the bottom most band.
     152 [ +  + ][ -  + ]:         68 :     if (nCurrentTop <= nBottom
                 [ #  # ]
     153                 :            :         && (pBand==NULL || nBottom>pBand->mnYBottom))
     154                 :            :     {
     155                 :            :         // When there is no previous band then the new one will be the
     156                 :            :         // first.  Otherwise the new band is inserted behind the last band.
     157                 :            :         pImplRegion->InsertBand(
     158                 :            :             pPreviousBand,
     159                 :            :             new ImplRegionBand(
     160                 :            :                 nCurrentTop,
     161         [ +  - ]:         34 :                 nBottom));
     162                 :            :     }
     163                 :         68 : }
     164                 :            : 
     165                 :            : 
     166                 :            : 
     167                 :            : /** Convert a rectilinear polygon (that is oriented along the primary axes)
     168                 :            :     to a list of bands.  For this special form of polygon we can use an
     169                 :            :     optimization that prevents the creation of one band per y value.
     170                 :            :     However, it still is possible that some temporary bands are created that
     171                 :            :     later can be optimized away.
     172                 :            :     @param rPolyPolygon
     173                 :            :         A set of zero, one, or more polygons, nested or not, that are
     174                 :            :         converted into a list of bands.
     175                 :            :     @return
     176                 :            :         A new ImplRegion object is returned that contains the bands that
     177                 :            :         represent the given poly-polygon.
     178                 :            : */
     179                 :         26 : ImplRegion* ImplRectilinearPolygonToBands (const PolyPolygon& rPolyPoly)
     180                 :            : {
     181                 :            :     OSL_ASSERT(ImplIsPolygonRectilinear (rPolyPoly));
     182                 :            : 
     183                 :            :     // Create a new ImplRegion object as container of the bands.
     184         [ +  - ]:         26 :     ImplRegion* pImplRegion = new ImplRegion();
     185                 :         26 :     long nLineId = 0L;
     186                 :            : 
     187                 :            :     // Iterate over all polygons.
     188                 :         26 :     const sal_uInt16 nPolyCount = rPolyPoly.Count();
     189         [ +  + ]:         60 :     for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
     190                 :            :     {
     191         [ +  - ]:         34 :         const Polygon&  aPoly = rPolyPoly.GetObject(nPoly);
     192                 :            : 
     193                 :            :         // Iterate over all edges of the current polygon.
     194         [ +  - ]:         34 :         const sal_uInt16 nSize = aPoly.GetSize();
     195         [ -  + ]:         34 :         if (nSize < 2)
     196                 :          0 :             continue;
     197                 :            :         // Avoid fetching every point twice (each point is the start point
     198                 :            :         // of one and the end point of another edge.)
     199         [ +  - ]:         34 :         Point aStart (aPoly.GetPoint(0));
     200                 :         34 :         Point aEnd;
     201         [ +  + ]:        204 :         for (sal_uInt16 nPoint = 1; nPoint <= nSize; ++nPoint, aStart=aEnd)
     202                 :            :         {
     203                 :            :             // We take the implicit closing edge into account by mapping
     204                 :            :             // index nSize to 0.
     205         [ +  - ]:        170 :             aEnd = aPoly.GetPoint(nPoint%nSize);
     206         [ +  + ]:        170 :             if (aStart.Y() == aEnd.Y())
     207                 :            :             {
     208                 :            :                 // Horizontal lines are ignored.
     209                 :        102 :                 continue;
     210                 :            :             }
     211                 :            : 
     212                 :            :             // At this point the line has to be vertical.
     213                 :            :             OSL_ASSERT(aStart.X() == aEnd.X());
     214                 :            : 
     215                 :            :             // Sort y-coordinates to simplify the algorithm and store the
     216                 :            :             // direction seperately.  The direction is calculated as it is
     217                 :            :             // in other places (but seems to be the wrong way.)
     218         [ +  - ]:         68 :             const long nTop (::std::min(aStart.Y(), aEnd.Y()));
     219         [ +  - ]:         68 :             const long nBottom (::std::max(aStart.Y(), aEnd.Y()));
     220         [ +  + ]:         68 :             const LineType eLineType (aStart.Y() > aEnd.Y() ? LINE_DESCENDING : LINE_ASCENDING);
     221                 :            : 
     222                 :            :             // Make sure that the current line is covered by bands.
     223         [ +  - ]:         68 :             ImplAddMissingBands(pImplRegion, nTop,nBottom);
     224                 :            : 
     225                 :            :             // Find top-most band that may contain nTop.
     226                 :         68 :             ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
     227 [ +  - ][ +  + ]:         84 :             while (pBand!=NULL && pBand->mnYBottom < nTop)
                 [ +  + ]
     228                 :         16 :                 pBand = pBand->mpNextBand;
     229                 :         68 :             ImplRegionBand* pTopBand = pBand;
     230                 :            :             // If necessary split the band at nTop so that nTop is contained
     231                 :            :             // in the lower band.
     232 [ +  - ][ -  + ]:         68 :             if (pBand!=NULL
         [ #  # ][ #  # ]
     233                 :            :                    // Prevent the current band from becoming 0 pixel high
     234                 :            :                 && pBand->mnYTop<nTop
     235                 :            :                    // this allows the lowest pixel of the band to be split off
     236                 :            :                 && pBand->mnYBottom>=nTop
     237                 :            :                    // do not split a band that is just one pixel high
     238                 :            :                 && pBand->mnYTop<pBand->mnYBottom)
     239                 :            :             {
     240                 :            :                 // Split the top band.
     241         [ #  # ]:          0 :                 pTopBand = pBand->SplitBand(nTop);
     242                 :            :             }
     243                 :            : 
     244                 :            :             // Advance to band that may contain nBottom.
     245 [ +  - ][ -  + ]:         68 :             while (pBand!=NULL && pBand->mnYBottom < nBottom)
                 [ -  + ]
     246                 :          0 :                 pBand = pBand->mpNextBand;
     247                 :            :             // The lowest band may have to be split at nBottom so that
     248                 :            :             // nBottom itself remains in the upper band.
     249 [ +  - ][ +  - ]:         68 :             if (pBand!=NULL
         [ -  + ][ #  # ]
     250                 :            :                    // allow the current band becoming 1 pixel high
     251                 :            :                 && pBand->mnYTop<=nBottom
     252                 :            :                    // prevent splitting off a band that is 0 pixel high
     253                 :            :                 && pBand->mnYBottom>nBottom
     254                 :            :                    // do not split a band that is just one pixel high
     255                 :            :                 && pBand->mnYTop<pBand->mnYBottom)
     256                 :            :             {
     257                 :            :                 // Split the bottom band.
     258         [ #  # ]:          0 :                 pBand->SplitBand(nBottom+1);
     259                 :            :             }
     260                 :            : 
     261                 :            :             // Note that we remember the top band (in pTopBand) but not the
     262                 :            :             // bottom band.  The later can be determined by comparing y
     263                 :            :             // coordinates.
     264                 :            : 
     265                 :            :             // Add the x-value as point to all bands in the nTop->nBottom range.
     266 [ +  + ][ +  - ]:        136 :             for (pBand=pTopBand; pBand!=NULL&&pBand->mnYTop<=nBottom; pBand=pBand->mpNextBand)
                 [ +  + ]
     267         [ +  - ]:         68 :                 pBand->InsertPoint(aStart.X(), nLineId++, sal_True, eLineType);
     268                 :            :         }
     269                 :            :     }
     270                 :            : 
     271                 :         26 :     return pImplRegion;
     272                 :            : }
     273                 :            : 
     274                 :            : 
     275                 :            : 
     276                 :            : 
     277                 :            : /** Convert a general polygon (one for which ImplIsPolygonRectilinear()
     278                 :            :     returns <FALSE/>) to bands.
     279                 :            : */
     280                 :          0 : ImplRegion* ImplGeneralPolygonToBands (
     281                 :            :     const PolyPolygon& rPolyPoly,
     282                 :            :     const Rectangle& rPolygonBoundingBox)
     283                 :            : {
     284                 :          0 :     long nLineID = 0L;
     285                 :            : 
     286                 :            :     // initialisation and creation of Bands
     287         [ #  # ]:          0 :     ImplRegion* pImplRegion = new ImplRegion();
     288                 :          0 :     pImplRegion->CreateBandRange( rPolygonBoundingBox.Top(), rPolygonBoundingBox.Bottom() );
     289                 :            : 
     290                 :            :     // insert polygons
     291                 :          0 :     const sal_uInt16 nPolyCount = rPolyPoly.Count();
     292         [ #  # ]:          0 :     for ( sal_uInt16 nPoly = 0; nPoly < nPolyCount; nPoly++ )
     293                 :            :     {
     294                 :            :         // get reference to current polygon
     295         [ #  # ]:          0 :         const Polygon&  aPoly = rPolyPoly.GetObject( nPoly );
     296         [ #  # ]:          0 :         const sal_uInt16    nSize = aPoly.GetSize();
     297                 :            : 
     298                 :            :         // not enough points ( <= 2 )? -> nothing to do!
     299         [ #  # ]:          0 :         if ( nSize <= 2 )
     300                 :          0 :             continue;
     301                 :            : 
     302                 :            :         // band the polygon
     303         [ #  # ]:          0 :         for ( sal_uInt16 nPoint = 1; nPoint < nSize; nPoint++ )
     304 [ #  # ][ #  # ]:          0 :             pImplRegion->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
                 [ #  # ]
     305                 :            : 
     306                 :            :         // close polygon with line from first point to last point, if neccesary
     307         [ #  # ]:          0 :         const Point rLastPoint = aPoly.GetPoint(nSize-1);
     308         [ #  # ]:          0 :         const Point rFirstPoint = aPoly.GetPoint(0);
     309         [ #  # ]:          0 :         if ( rLastPoint != rFirstPoint )
     310         [ #  # ]:          0 :             pImplRegion->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
     311                 :            :     }
     312                 :            : 
     313                 :          0 :     return pImplRegion;
     314                 :            : }
     315                 :            : 
     316                 :            : 
     317                 :            : } // end of anonymous namespace
     318                 :            : 
     319                 :            : 
     320                 :            : // -----------------------------------------------------------------------
     321                 :            : 
     322                 :            : #ifdef DBG_UTIL
     323                 :            : const char* ImplDbgTestRegion( const void* pObj )
     324                 :            : {
     325                 :            :     Region*       pRegion = (Region*)pObj;
     326                 :            :     ImplRegion*   pImplRegion = pRegion->ImplGetImplRegion();
     327                 :            : 
     328                 :            :     if ( aImplNullRegion.mnRefCount )
     329                 :            :         return "Null-Region-RefCount modified";
     330                 :            :     if ( aImplNullRegion.mnRectCount )
     331                 :            :         return "Null-Region-RectCount modified";
     332                 :            :     if ( aImplNullRegion.mpPolyPoly )
     333                 :            :         return "Null-Region-PolyPoly modified";
     334                 :            :     if ( aImplEmptyRegion.mnRefCount )
     335                 :            :         return "Emptry-Region-RefCount modified";
     336                 :            :     if ( aImplEmptyRegion.mnRectCount )
     337                 :            :         return "Emptry-Region-RectCount modified";
     338                 :            :     if ( aImplEmptyRegion.mpPolyPoly )
     339                 :            :         return "Emptry-Region-PolyPoly modified";
     340                 :            : 
     341                 :            :     if ( (pImplRegion != &aImplEmptyRegion) && (pImplRegion != &aImplNullRegion) )
     342                 :            :     {
     343                 :            :         sal_uLong                   nCount = 0;
     344                 :            :         const ImplRegionBand*   pBand = pImplRegion->ImplGetFirstRegionBand();
     345                 :            :         while ( pBand )
     346                 :            :         {
     347                 :            :             if ( pBand->mnYBottom < pBand->mnYTop )
     348                 :            :                 return "YBottom < YTop";
     349                 :            :             if ( pBand->mpNextBand )
     350                 :            :             {
     351                 :            :                 if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
     352                 :            :                     return "overlapping bands in region";
     353                 :            :             }
     354                 :            :             if ( pBand->mbTouched > 1 )
     355                 :            :                 return "Band-mbTouched overwrite";
     356                 :            : 
     357                 :            :             ImplRegionBandSep* pSep = pBand->mpFirstSep;
     358                 :            :             while ( pSep )
     359                 :            :             {
     360                 :            :                 if ( pSep->mnXRight < pSep->mnXLeft )
     361                 :            :                     return "XLeft < XRight";
     362                 :            :                 if ( pSep->mpNextSep )
     363                 :            :                 {
     364                 :            :                     if ( pSep->mnXRight >= pSep->mpNextSep->mnXLeft )
     365                 :            :                         return "overlapping separations in region";
     366                 :            :                 }
     367                 :            :                 if ( pSep->mbRemoved > 1 )
     368                 :            :                     return "Sep-mbRemoved overwrite";
     369                 :            : 
     370                 :            :                 nCount++;
     371                 :            :                 pSep = pSep->mpNextSep;
     372                 :            :             }
     373                 :            : 
     374                 :            :             pBand = pBand->mpNextBand;
     375                 :            :         }
     376                 :            : 
     377                 :            :         if ( pImplRegion->mnRectCount != nCount )
     378                 :            :             return "mnRetCount is not valid";
     379                 :            :     }
     380                 :            : 
     381                 :            :     return NULL;
     382                 :            : }
     383                 :            : 
     384                 :            : #endif
     385                 :            : 
     386                 :            : // =======================================================================
     387                 :            : 
     388                 :    3533083 : inline void Region::ImplPolyPolyRegionToBandRegion()
     389                 :            : {
     390 [ +  - ][ +  + ]:    3533083 :     if( mpImplRegion->mpPolyPoly || mpImplRegion->mpB2DPolyPoly )
     391                 :         26 :         ImplPolyPolyRegionToBandRegionFunc();
     392                 :    3533083 : }
     393                 :            : 
     394                 :            : // =======================================================================
     395                 :            : 
     396                 :    1793949 : ImplRegionBase::ImplRegionBase( int nRefCount )
     397                 :            : :   mnRefCount( nRefCount )
     398                 :            : ,   mnRectCount( 0 )
     399                 :            : ,   mpPolyPoly( NULL )
     400                 :    1793949 : ,   mpB2DPolyPoly( NULL )
     401                 :    1793949 : {}
     402                 :            : 
     403                 :            : // ------------------------------------------------------------------------
     404                 :            : 
     405                 :     802882 : ImplRegion::ImplRegion()
     406                 :            : {
     407                 :     802882 :     mpFirstBand         = NULL;
     408                 :     802882 :     mpLastCheckedBand   = NULL;
     409                 :     802882 : }
     410                 :            : 
     411                 :            : // ------------------------------------------------------------------------
     412                 :            : 
     413                 :         22 : ImplRegion::ImplRegion( const PolyPolygon& rPolyPoly )
     414                 :            : {
     415                 :         22 :     mpFirstBand         = NULL;
     416                 :         22 :     mpLastCheckedBand   = NULL;
     417 [ +  - ][ +  - ]:         22 :     mpPolyPoly          = new PolyPolygon( rPolyPoly );
     418                 :         22 : }
     419                 :            : 
     420                 :            : // ------------------------------------------------------------------------
     421                 :            : 
     422                 :         43 : ImplRegion::ImplRegion( const basegfx::B2DPolyPolygon& rPolyPoly )
     423                 :            : {
     424                 :         43 :     mpFirstBand = NULL;
     425                 :         43 :     mpLastCheckedBand = NULL;
     426 [ +  - ][ +  - ]:         43 :     mpB2DPolyPoly = new basegfx::B2DPolyPolygon( rPolyPoly );
     427                 :         43 : }
     428                 :            : 
     429                 :            : // -----------------------------------------------------------------------
     430                 :            : 
     431                 :     990308 : ImplRegion::ImplRegion( const ImplRegion& rImplRegion )
     432                 :     990308 : :   ImplRegionBase()
     433                 :            : {
     434                 :     990308 :     mpFirstBand = NULL;
     435                 :     990308 :     mpLastCheckedBand = NULL;
     436                 :     990308 :     mnRectCount = rImplRegion.mnRectCount;
     437                 :            : 
     438         [ +  + ]:     990308 :     if ( rImplRegion.mpPolyPoly )
     439 [ +  - ][ +  - ]:         11 :         mpPolyPoly = new PolyPolygon( *rImplRegion.mpPolyPoly );
     440         [ +  + ]:     990297 :     else if( rImplRegion.mpB2DPolyPoly )
     441 [ +  - ][ +  - ]:         16 :         mpB2DPolyPoly = new basegfx::B2DPolyPolygon( *rImplRegion.mpB2DPolyPoly );
     442                 :            : 
     443                 :            :     // insert band(s) into the list
     444                 :            :     ImplRegionBand* pNewBand;
     445                 :     990308 :     ImplRegionBand* pPrevBand = 0;
     446                 :     990308 :     ImplRegionBand* pBand = rImplRegion.mpFirstBand;
     447         [ +  + ]:    2000319 :     while ( pBand )
     448                 :            :     {
     449 [ +  - ][ +  - ]:    1010011 :         pNewBand = new ImplRegionBand( *pBand );
     450                 :            : 
     451                 :            :         // first element? -> set as first into the list
     452         [ +  + ]:    1010011 :         if ( pBand == rImplRegion.mpFirstBand )
     453                 :     990281 :             mpFirstBand = pNewBand;
     454                 :            :         else
     455                 :      19730 :             pPrevBand->mpNextBand = pNewBand;
     456                 :            : 
     457                 :    1010011 :         pPrevBand = pNewBand;
     458                 :    1010011 :         pBand = pBand->mpNextBand;
     459                 :            :     }
     460                 :     990308 : }
     461                 :            : 
     462                 :            : // -----------------------------------------------------------------------
     463                 :            : 
     464                 :    1788841 : ImplRegion::~ImplRegion()
     465                 :            : {
     466                 :            :     DBG_ASSERT( (this != &aImplEmptyRegion) && (this != &aImplNullRegion),
     467                 :            :                 "ImplRegion::~ImplRegion() - Empty oder NULL-Region" );
     468                 :            : 
     469                 :    1788841 :     ImplRegionBand* pBand = mpFirstBand;
     470         [ +  + ]:    3443423 :     while ( pBand )
     471                 :            :     {
     472                 :    1654582 :         ImplRegionBand* pTempBand = pBand->mpNextBand;
     473 [ +  - ][ +  - ]:    1654582 :         delete pBand;
     474                 :    1654582 :         pBand = pTempBand;
     475                 :            :     }
     476         [ -  + ]:    3577682 : }
     477                 :            : 
     478                 :            : // -----------------------------------------------------------------------
     479                 :            : 
     480                 :    1789535 : ImplRegionBase::~ImplRegionBase()
     481                 :            : {
     482         [ +  + ]:    1789535 :     delete mpPolyPoly;
     483         [ +  + ]:    1789535 :     delete mpB2DPolyPoly;
     484         [ -  + ]:    1789535 : }
     485                 :            : 
     486                 :            : // -----------------------------------------------------------------------
     487                 :            : //
     488                 :            : // create complete range of bands in single steps
     489                 :            : 
     490                 :          0 : void ImplRegion::CreateBandRange( long nYTop, long nYBottom )
     491                 :            : {
     492                 :            :     // add top band
     493         [ #  # ]:          0 :     mpFirstBand = new ImplRegionBand( nYTop-1, nYTop-1 );
     494                 :            : 
     495                 :            :     // begin first search from the first element
     496                 :          0 :     mpLastCheckedBand = mpFirstBand;
     497                 :            : 
     498                 :          0 :     ImplRegionBand* pBand = mpFirstBand;
     499         [ #  # ]:          0 :     for ( int i = nYTop; i <= nYBottom+1; i++ )
     500                 :            :     {
     501                 :            :         // create new band
     502         [ #  # ]:          0 :         ImplRegionBand* pNewBand = new ImplRegionBand( i, i );
     503                 :          0 :         pBand->mpNextBand = pNewBand;
     504         [ #  # ]:          0 :         if ( pBand != mpFirstBand )
     505                 :          0 :             pNewBand->mpPrevBand = pBand;
     506                 :            : 
     507                 :          0 :         pBand = pBand->mpNextBand;
     508                 :            :     }
     509                 :          0 : }
     510                 :            : 
     511                 :            : // -----------------------------------------------------------------------
     512                 :            : 
     513                 :          0 : sal_Bool ImplRegion::InsertLine( const Point& rStartPt, const Point& rEndPt,
     514                 :            :                              long nLineId )
     515                 :            : {
     516                 :            :     long nX, nY;
     517                 :            : 
     518                 :            :     // lines consisting of a single point do not interest here
     519         [ #  # ]:          0 :     if ( rStartPt == rEndPt )
     520                 :          0 :         return sal_True;
     521                 :            : 
     522         [ #  # ]:          0 :     LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
     523         [ #  # ]:          0 :     if ( rStartPt.X() == rEndPt.X() )
     524                 :            :     {
     525                 :            :         // vertical line
     526                 :          0 :         const long nEndY = rEndPt.Y();
     527                 :            : 
     528                 :          0 :         nX = rStartPt.X();
     529                 :          0 :         nY = rStartPt.Y();
     530                 :            : 
     531         [ #  # ]:          0 :         if( nEndY > nY )
     532                 :            :         {
     533         [ #  # ]:          0 :             for ( ; nY <= nEndY; nY++ )
     534                 :            :             {
     535                 :          0 :                 Point aNewPoint( nX, nY );
     536                 :            :                 InsertPoint( aNewPoint, nLineId,
     537                 :          0 :                              (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
     538         [ #  # ]:          0 :                              eLineType );
           [ #  #  #  # ]
     539                 :            :             }
     540                 :            :         }
     541                 :            :         else
     542                 :            :         {
     543         [ #  # ]:          0 :             for ( ; nY >= nEndY; nY-- )
     544                 :            :             {
     545                 :          0 :                 Point aNewPoint( nX, nY );
     546                 :            :                 InsertPoint( aNewPoint, nLineId,
     547                 :          0 :                              (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
     548         [ #  # ]:          0 :                              eLineType );
           [ #  #  #  # ]
     549                 :            :             }
     550                 :            :         }
     551                 :            :     }
     552         [ #  # ]:          0 :     else if ( rStartPt.Y() != rEndPt.Y() )
     553                 :            :     {
     554                 :          0 :         const long  nDX = labs( rEndPt.X() - rStartPt.X() );
     555                 :          0 :         const long  nDY = labs( rEndPt.Y() - rStartPt.Y() );
     556                 :          0 :         const long  nStartX = rStartPt.X();
     557                 :          0 :         const long  nStartY = rStartPt.Y();
     558                 :          0 :         const long  nEndX = rEndPt.X();
     559                 :          0 :         const long  nEndY = rEndPt.Y();
     560         [ #  # ]:          0 :         const long  nXInc = ( nStartX < nEndX ) ? 1L : -1L;
     561         [ #  # ]:          0 :         const long  nYInc = ( nStartY < nEndY ) ? 1L : -1L;
     562                 :            : 
     563         [ #  # ]:          0 :         if ( nDX >= nDY )
     564                 :            :         {
     565                 :          0 :             const long  nDYX = ( nDY - nDX ) << 1;
     566                 :          0 :             const long  nDY2 = nDY << 1;
     567                 :          0 :             long        nD = nDY2 - nDX;
     568                 :            : 
     569         [ #  # ]:          0 :             for ( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
     570                 :            :             {
     571         [ #  # ]:          0 :                 InsertPoint( Point( nX, nY ), nLineId, nStartX == nX, eLineType );
     572                 :            : 
     573         [ #  # ]:          0 :                 if ( nD < 0L )
     574                 :          0 :                     nD += nDY2;
     575                 :            :                 else
     576                 :          0 :                     nD += nDYX, nY += nYInc;
     577                 :            :             }
     578                 :            :         }
     579                 :            :         else
     580                 :            :         {
     581                 :          0 :             const long  nDYX = ( nDX - nDY ) << 1;
     582                 :          0 :             const long  nDY2 = nDX << 1;
     583                 :          0 :             long        nD = nDY2 - nDY;
     584                 :            : 
     585         [ #  # ]:          0 :             for ( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
     586                 :            :             {
     587         [ #  # ]:          0 :                 InsertPoint( Point( nX, nY ), nLineId, nStartY == nY, eLineType );
     588                 :            : 
     589         [ #  # ]:          0 :                 if ( nD < 0L )
     590                 :          0 :                     nD += nDY2;
     591                 :            :                 else
     592                 :          0 :                     nD += nDYX, nX += nXInc;
     593                 :            :             }
     594                 :            :         }
     595                 :            : 
     596                 :            :         // last point
     597         [ #  # ]:          0 :         InsertPoint( Point( nEndX, nEndY ), nLineId, sal_True, eLineType );
     598                 :            :     }
     599                 :            : 
     600                 :          0 :     return sal_True;
     601                 :            : }
     602                 :            : 
     603                 :            : // -----------------------------------------------------------------------
     604                 :            : //
     605                 :            : // search for appropriate place for the new point
     606                 :            : 
     607                 :          0 : sal_Bool ImplRegion::InsertPoint( const Point &rPoint, long nLineID,
     608                 :            :                               sal_Bool bEndPoint, LineType eLineType )
     609                 :            : {
     610                 :            :     DBG_ASSERT( mpFirstBand != NULL, "ImplRegion::InsertPoint - no bands available!" );
     611                 :            : 
     612         [ #  # ]:          0 :     if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
     613                 :            :     {
     614                 :          0 :         mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
     615                 :          0 :         return sal_True;
     616                 :            :     }
     617                 :            : 
     618         [ #  # ]:          0 :     if ( rPoint.Y() > mpLastCheckedBand->mnYTop )
     619                 :            :     {
     620                 :            :         // Search ascending
     621         [ #  # ]:          0 :         while ( mpLastCheckedBand )
     622                 :            :         {
     623                 :            :             // Insert point if possible
     624         [ #  # ]:          0 :             if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
     625                 :            :             {
     626                 :          0 :                 mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
     627                 :          0 :                 return sal_True;
     628                 :            :             }
     629                 :            : 
     630                 :          0 :             mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
     631                 :            :         }
     632                 :            : 
     633                 :            :         OSL_FAIL( "ImplRegion::InsertPoint reached the end of the list!" );
     634                 :            :     }
     635                 :            :     else
     636                 :            :     {
     637                 :            :         // Search descending
     638         [ #  # ]:          0 :         while ( mpLastCheckedBand )
     639                 :            :         {
     640                 :            :             // Insert point if possible
     641         [ #  # ]:          0 :             if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
     642                 :            :             {
     643                 :          0 :                 mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
     644                 :          0 :                 return sal_True;
     645                 :            :             }
     646                 :            : 
     647                 :          0 :             mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
     648                 :            :         }
     649                 :            : 
     650                 :            :         OSL_FAIL( "ImplRegion::InsertPoint reached the beginning of the list!" );
     651                 :            :     }
     652                 :            : 
     653                 :            :     OSL_FAIL( "ImplRegion::InsertPoint point not inserted!" );
     654                 :            : 
     655                 :            :     // reinitialize pointer (should never be reached!)
     656                 :          0 :     mpLastCheckedBand = mpFirstBand;
     657                 :            : 
     658                 :          0 :     return sal_False;
     659                 :            : }
     660                 :            : 
     661                 :            : // -----------------------------------------------------------------------
     662                 :            : //
     663                 :            : // search for appropriate places for the new bands
     664                 :            : 
     665                 :    1132292 : void ImplRegion::InsertBands( long nTop, long nBottom )
     666                 :            : {
     667                 :            :     // region empty? -> set rectagle as first entry!
     668         [ +  + ]:    1132292 :     if ( !mpFirstBand )
     669                 :            :     {
     670                 :            :         // add band with boundaries of the rectangle
     671         [ +  - ]:      83872 :         mpFirstBand = new ImplRegionBand( nTop, nBottom );
     672                 :    1132292 :         return;
     673                 :            :     }
     674                 :            : 
     675                 :            :     // find/insert bands for the boundaries of the rectangle
     676                 :    1048420 :     sal_Bool bTopBoundaryInserted = sal_False;
     677                 :    1048420 :     sal_Bool bTop2BoundaryInserted = sal_False;
     678                 :    1048420 :     sal_Bool bBottomBoundaryInserted = sal_False;
     679                 :            : 
     680                 :            :     // special case: top boundary is above the first band
     681                 :            :     ImplRegionBand* pNewBand;
     682         [ +  + ]:    1048420 :     if ( nTop < mpFirstBand->mnYTop )
     683                 :            :     {
     684                 :            :         // create new band above the first in the list
     685         [ +  - ]:     365973 :         pNewBand = new ImplRegionBand( nTop, mpFirstBand->mnYTop );
     686         [ +  + ]:     365973 :         if ( nBottom < mpFirstBand->mnYTop )
     687                 :      16614 :             pNewBand->mnYBottom = nBottom;
     688                 :            : 
     689                 :            :         // insert band into the list
     690                 :     365973 :         pNewBand->mpNextBand = mpFirstBand;
     691                 :     365973 :         mpFirstBand = pNewBand;
     692                 :            : 
     693                 :     365973 :         bTopBoundaryInserted = sal_True;
     694                 :            :     }
     695                 :            : 
     696                 :            :     // insert band(s) into the list
     697                 :    1048420 :     ImplRegionBand* pBand = mpFirstBand;
     698         [ +  + ]:    3837344 :     while ( pBand )
     699                 :            :     {
     700                 :            :         // Insert Bands if possible
     701         [ +  + ]:    3479911 :         if ( !bTopBoundaryInserted )
     702                 :    1449172 :             bTopBoundaryInserted = InsertSingleBand( pBand, nTop - 1 );
     703                 :            : 
     704         [ +  + ]:    3479911 :         if ( !bTop2BoundaryInserted )
     705                 :    1655234 :             bTop2BoundaryInserted = InsertSingleBand( pBand, nTop );
     706                 :            : 
     707 [ +  + ][ +  + ]:    3479911 :         if ( !bBottomBoundaryInserted && (nTop != nBottom) )
     708                 :    3120943 :             bBottomBoundaryInserted = InsertSingleBand( pBand, nBottom );
     709                 :            : 
     710                 :            :         // both boundaries inserted? -> nothing more to do
     711 [ +  + ][ +  + ]:    3479911 :         if ( bTopBoundaryInserted && bTop2BoundaryInserted && bBottomBoundaryInserted )
                 [ +  + ]
     712                 :     690987 :             break;
     713                 :            : 
     714                 :            :         // insert bands between two bands if neccessary
     715         [ +  + ]:    2788924 :         if ( pBand->mpNextBand )
     716                 :            :         {
     717         [ +  + ]:    2431491 :             if ( (pBand->mnYBottom + 1) < pBand->mpNextBand->mnYTop )
     718                 :            :             {
     719                 :            :                 // copy band with list and set new boundary
     720                 :            :                 pNewBand = new ImplRegionBand( pBand->mnYBottom+1,
     721         [ +  - ]:      29506 :                                                pBand->mpNextBand->mnYTop-1 );
     722                 :            : 
     723                 :            :                 // insert band into the list
     724                 :      29506 :                 pNewBand->mpNextBand = pBand->mpNextBand;
     725                 :      29506 :                 pBand->mpNextBand = pNewBand;
     726                 :            :             }
     727                 :            :         }
     728                 :            : 
     729                 :    2788924 :         pBand = pBand->mpNextBand;
     730                 :            :     }
     731                 :            : }
     732                 :            : 
     733                 :            : // -----------------------------------------------------------------------
     734                 :            : //
     735                 :            : // create new band and insert it into the list
     736                 :            : 
     737                 :    6225349 : sal_Bool ImplRegion::InsertSingleBand( ImplRegionBand* pBand,
     738                 :            :                                    long nYBandPosition )
     739                 :            : {
     740                 :            :     // boundary already included in band with height 1? -> nothing to do!
     741 [ +  + ][ +  + ]:    6225349 :     if ( (pBand->mnYTop == pBand->mnYBottom) &&
     742                 :            :          (nYBandPosition == pBand->mnYTop) )
     743                 :       8186 :         return sal_True;
     744                 :            : 
     745                 :            :     // insert single height band on top?
     746                 :            :     ImplRegionBand* pNewBand;
     747         [ +  + ]:    6217163 :     if ( nYBandPosition == pBand->mnYTop )
     748                 :            :     {
     749                 :            :         // copy band with list and set new boundary
     750         [ +  - ]:     930973 :         pNewBand = new ImplRegionBand( *pBand );
     751                 :     930973 :         pNewBand->mnYTop = nYBandPosition+1;
     752                 :            : 
     753                 :            :         // insert band into the list
     754                 :     930973 :         pNewBand->mpNextBand = pBand->mpNextBand;
     755                 :     930973 :         pBand->mnYBottom = nYBandPosition;
     756                 :     930973 :         pBand->mpNextBand = pNewBand;
     757                 :            : 
     758                 :     930973 :         return sal_True;
     759                 :            :     }
     760                 :            : 
     761                 :            :     // top of new rectangle within the current band? -> insert new band and copy data
     762 [ +  + ][ +  + ]:    5286190 :     if ( (nYBandPosition > pBand->mnYTop) &&
     763                 :            :          (nYBandPosition < pBand->mnYBottom) )
     764                 :            :     {
     765                 :            :         // copy band with list and set new boundary
     766         [ +  - ]:     444469 :         pNewBand = new ImplRegionBand( *pBand );
     767                 :     444469 :         pNewBand->mnYTop = nYBandPosition;
     768                 :            : 
     769                 :            :         // insert band into the list
     770                 :     444469 :         pNewBand->mpNextBand = pBand->mpNextBand;
     771                 :     444469 :         pBand->mnYBottom = nYBandPosition;
     772                 :     444469 :         pBand->mpNextBand = pNewBand;
     773                 :            : 
     774                 :            :         // copy band with list and set new boundary
     775         [ +  - ]:     444469 :         pNewBand = new ImplRegionBand( *pBand );
     776                 :     444469 :         pNewBand->mnYTop = nYBandPosition;
     777                 :            : 
     778                 :            :         // insert band into the list
     779                 :     444469 :         pBand->mpNextBand->mnYTop = nYBandPosition+1;
     780                 :            : 
     781                 :     444469 :         pNewBand->mpNextBand = pBand->mpNextBand;
     782                 :     444469 :         pBand->mnYBottom = nYBandPosition - 1;
     783                 :     444469 :         pBand->mpNextBand = pNewBand;
     784                 :            : 
     785                 :     444469 :         return sal_True;
     786                 :            :     }
     787                 :            : 
     788                 :            :     // create new band behind the current in the list
     789         [ +  + ]:    4841721 :     if ( !pBand->mpNextBand )
     790                 :            :     {
     791         [ +  + ]:    2035545 :         if ( nYBandPosition == pBand->mnYBottom )
     792                 :            :         {
     793                 :            :             // copy band with list and set new boundary
     794         [ +  - ]:     319534 :             pNewBand = new ImplRegionBand( *pBand );
     795                 :     319534 :             pNewBand->mnYTop = pBand->mnYBottom;
     796                 :     319534 :             pNewBand->mnYBottom = nYBandPosition;
     797                 :            : 
     798                 :     319534 :             pBand->mnYBottom = nYBandPosition-1;
     799                 :            : 
     800                 :            :             // append band to the list
     801                 :     319534 :             pBand->mpNextBand = pNewBand;
     802                 :     319534 :             return sal_True;
     803                 :            :         }
     804                 :            : 
     805         [ +  + ]:    1716011 :         if ( nYBandPosition > pBand->mnYBottom )
     806                 :            :         {
     807                 :            :             // create new band
     808         [ +  - ]:     707663 :             pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
     809                 :            : 
     810                 :            :             // append band to the list
     811                 :     707663 :             pBand->mpNextBand = pNewBand;
     812                 :     707663 :             return sal_True;
     813                 :            :         }
     814                 :            :     }
     815                 :            : 
     816                 :    6225349 :     return sal_False;
     817                 :            : }
     818                 :            : 
     819                 :            : // ------------------------------------------------------------------------
     820                 :            : 
     821                 :         34 : void ImplRegion::InsertBand (ImplRegionBand* pPreviousBand, ImplRegionBand* pBandToInsert)
     822                 :            : {
     823                 :            :     OSL_ASSERT(pBandToInsert!=NULL);
     824                 :            : 
     825         [ +  + ]:         34 :     if (pPreviousBand == NULL)
     826                 :            :     {
     827                 :            :         // Insert band before all others.
     828         [ -  + ]:         26 :         if (mpFirstBand != NULL)
     829                 :          0 :             mpFirstBand->mpPrevBand = pBandToInsert;
     830                 :         26 :         pBandToInsert->mpNextBand = mpFirstBand;
     831                 :         26 :         mpFirstBand = pBandToInsert;
     832                 :            :     }
     833                 :            :     else
     834                 :            :     {
     835                 :            :         // Insert band directly after pPreviousBand.
     836                 :          8 :         pBandToInsert->mpNextBand = pPreviousBand->mpNextBand;
     837                 :          8 :         pPreviousBand->mpNextBand = pBandToInsert;
     838                 :          8 :         pBandToInsert->mpPrevBand = pPreviousBand;
     839                 :            :     }
     840                 :         34 : }
     841                 :            : 
     842                 :            : // ------------------------------------------------------------------------
     843                 :            : 
     844                 :     165698 : void ImplRegion::Union( long nLeft, long nTop, long nRight, long nBottom )
     845                 :            : {
     846                 :            :     DBG_ASSERT( nLeft <= nRight, "ImplRegion::Union() - nLeft > nRight" );
     847                 :            :     DBG_ASSERT( nTop <= nBottom, "ImplRegion::Union() - nTop > nBottom" );
     848                 :            : 
     849                 :            :     // process union
     850                 :     165698 :     ImplRegionBand* pBand = mpFirstBand;
     851         [ +  + ]:     547106 :     while ( pBand )
     852                 :            :     {
     853         [ +  + ]:     397751 :         if ( pBand->mnYTop >= nTop )
     854                 :            :         {
     855         [ +  + ]:     336088 :             if ( pBand->mnYBottom <= nBottom )
     856                 :     319745 :                 pBand->Union( nLeft, nRight );
     857                 :            :             else
     858                 :            :             {
     859                 :            : #ifdef DBG_UTIL
     860                 :            :                 long nCurY = pBand->mnYBottom;
     861                 :            :                 pBand = pBand->mpNextBand;
     862                 :            :                 while ( pBand )
     863                 :            :                 {
     864                 :            :                     if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
     865                 :            :                     {
     866                 :            :                         OSL_FAIL( "ImplRegion::Union() - Bands not sorted!" );
     867                 :            :                     }
     868                 :            :                     pBand = pBand->mpNextBand;
     869                 :            :                 }
     870                 :            : #endif
     871                 :      16343 :                 break;
     872                 :            :             }
     873                 :            :         }
     874                 :            : 
     875                 :     381408 :         pBand = pBand->mpNextBand;
     876                 :            :     }
     877                 :     165698 : }
     878                 :            : 
     879                 :            : // -----------------------------------------------------------------------
     880                 :            : 
     881                 :    1324487 : void ImplRegion::Exclude( long nLeft, long nTop, long nRight, long nBottom )
     882                 :            : {
     883                 :            :     DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
     884                 :            :     DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
     885                 :            : 
     886                 :            :     // process exclude
     887                 :    1324487 :     ImplRegionBand* pBand = mpFirstBand;
     888         [ +  + ]:    6525849 :     while ( pBand )
     889                 :            :     {
     890         [ +  + ]:    5641357 :         if ( pBand->mnYTop >= nTop )
     891                 :            :         {
     892         [ +  + ]:    4808464 :             if ( pBand->mnYBottom <= nBottom )
     893                 :    4368469 :                 pBand->Exclude( nLeft, nRight );
     894                 :            :             else
     895                 :            :             {
     896                 :            : #ifdef DBG_UTIL
     897                 :            :                 long nCurY = pBand->mnYBottom;
     898                 :            :                 pBand = pBand->mpNextBand;
     899                 :            :                 while ( pBand )
     900                 :            :                 {
     901                 :            :                     if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
     902                 :            :                     {
     903                 :            :                         OSL_FAIL( "ImplRegion::Exclude() - Bands not sorted!" );
     904                 :            :                     }
     905                 :            :                     pBand = pBand->mpNextBand;
     906                 :            :                 }
     907                 :            : #endif
     908                 :     439995 :                 break;
     909                 :            :             }
     910                 :            :         }
     911                 :            : 
     912                 :    5201362 :         pBand = pBand->mpNextBand;
     913                 :            :     }
     914                 :    1324487 : }
     915                 :            : 
     916                 :            : // -----------------------------------------------------------------------
     917                 :            : 
     918                 :          0 : void ImplRegion::XOr( long nLeft, long nTop, long nRight, long nBottom )
     919                 :            : {
     920                 :            :     DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
     921                 :            :     DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
     922                 :            : 
     923                 :            :     // process xor
     924                 :          0 :     ImplRegionBand* pBand = mpFirstBand;
     925         [ #  # ]:          0 :     while ( pBand )
     926                 :            :     {
     927         [ #  # ]:          0 :         if ( pBand->mnYTop >= nTop )
     928                 :            :         {
     929         [ #  # ]:          0 :             if ( pBand->mnYBottom <= nBottom )
     930                 :          0 :                 pBand->XOr( nLeft, nRight );
     931                 :            :             else
     932                 :            :             {
     933                 :            : #ifdef DBG_UTIL
     934                 :            :                 long nCurY = pBand->mnYBottom;
     935                 :            :                 pBand = pBand->mpNextBand;
     936                 :            :                 while ( pBand )
     937                 :            :                 {
     938                 :            :                     if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
     939                 :            :                     {
     940                 :            :                         OSL_FAIL( "ImplRegion::XOr() - Bands not sorted!" );
     941                 :            :                     }
     942                 :            :                     pBand = pBand->mpNextBand;
     943                 :            :                 }
     944                 :            : #endif
     945                 :          0 :                 break;
     946                 :            :             }
     947                 :            :         }
     948                 :            : 
     949                 :          0 :         pBand = pBand->mpNextBand;
     950                 :            :     }
     951                 :          0 : }
     952                 :            : 
     953                 :            : // -----------------------------------------------------------------------
     954                 :            : //
     955                 :            : // remove empty bands
     956                 :            : 
     957                 :    1128458 : sal_Bool ImplRegion::OptimizeBandList()
     958                 :            : {
     959                 :            :     DBG_ASSERT( (this != &aImplNullRegion) && (this != &aImplEmptyRegion),
     960                 :            :                 "ImplRegion::OptimizeBandList() - Empty oder NULL-Region" );
     961                 :            : 
     962                 :    1128458 :     mnRectCount = 0;
     963                 :            : 
     964                 :    1128458 :     ImplRegionBand* pPrevBand = 0;
     965                 :    1128458 :     ImplRegionBand* pBand = mpFirstBand;
     966         [ +  + ]:    4765334 :     while ( pBand )
     967                 :            :     {
     968                 :            :         const sal_Bool bBTEqual = pBand->mpNextBand &&
     969 [ +  + ][ +  + ]:    3636876 :                               (pBand->mnYBottom == pBand->mpNextBand->mnYTop);
     970                 :            : 
     971                 :            :         // no separation? -> remove!
     972 [ +  + ][ +  + ]:    3636876 :         if ( pBand->IsEmpty() || (bBTEqual && (pBand->mnYBottom == pBand->mnYTop)) )
         [ -  + ][ +  + ]
     973                 :            :         {
     974                 :            :             // save pointer
     975                 :    1538552 :             ImplRegionBand* pOldBand = pBand;
     976                 :            : 
     977                 :            :             // previous element of the list
     978         [ +  + ]:    1538552 :             if ( pBand == mpFirstBand )
     979                 :    1128975 :                 mpFirstBand = pBand->mpNextBand;
     980                 :            :             else
     981                 :     409577 :                 pPrevBand->mpNextBand = pBand->mpNextBand;
     982                 :            : 
     983                 :    1538552 :             pBand = pBand->mpNextBand;
     984         [ +  - ]:    1538552 :             delete pOldBand;
     985                 :            :         }
     986                 :            :         else
     987                 :            :         {
     988                 :            :             // fixup
     989         [ +  + ]:    2098324 :             if ( bBTEqual )
     990                 :       3721 :                 pBand->mnYBottom = pBand->mpNextBand->mnYTop-1;
     991                 :            : 
     992                 :            :             // this and next band with equal separations? -> combine!
     993         [ +  + ]:    3583017 :             if ( pBand->mpNextBand &&
           [ +  +  +  + ]
                 [ +  + ]
     994                 :            :                  ((pBand->mnYBottom+1) == pBand->mpNextBand->mnYTop) &&
     995                 :    1484693 :                  (*pBand == *pBand->mpNextBand) )
     996                 :            :             {
     997                 :            :                 // expand current height
     998                 :    1047207 :                 pBand->mnYBottom = pBand->mpNextBand->mnYBottom;
     999                 :            : 
    1000                 :            :                 // remove next band from list
    1001                 :    1047207 :                 ImplRegionBand* pDeletedBand = pBand->mpNextBand;
    1002                 :    1047207 :                 pBand->mpNextBand = pDeletedBand->mpNextBand;
    1003         [ +  - ]:    1047207 :                 delete pDeletedBand;
    1004                 :            : 
    1005                 :            :                 // check band again!
    1006                 :            :             }
    1007                 :            :             else
    1008                 :            :             {
    1009                 :            :                 // count rectangles within band
    1010                 :    1051117 :                 ImplRegionBandSep* pSep = pBand->mpFirstSep;
    1011         [ +  + ]:    2179301 :                 while ( pSep )
    1012                 :            :                 {
    1013                 :    1128184 :                     mnRectCount++;
    1014                 :    1128184 :                     pSep = pSep->mpNextSep;
    1015                 :            :                 }
    1016                 :            : 
    1017                 :    1051117 :                 pPrevBand = pBand;
    1018                 :    1051117 :                 pBand = pBand->mpNextBand;
    1019                 :            :             }
    1020                 :            :         }
    1021                 :            :     }
    1022                 :            : 
    1023                 :            : #ifdef DBG_UTIL
    1024                 :            :     pBand = mpFirstBand;
    1025                 :            :     while ( pBand )
    1026                 :            :     {
    1027                 :            :         DBG_ASSERT( pBand->mpFirstSep != NULL,
    1028                 :            :                     "Exiting ImplRegion::OptimizeBandList(): empty band in region!" );
    1029                 :            : 
    1030                 :            :         if ( pBand->mnYBottom < pBand->mnYTop )
    1031                 :            :             OSL_FAIL( "ImplRegion::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
    1032                 :            : 
    1033                 :            :         if ( pBand->mpNextBand )
    1034                 :            :         {
    1035                 :            :             if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
    1036                 :            :                 OSL_FAIL( "ImplRegion::OptimizeBandList(): overlapping bands in region!" );
    1037                 :            :         }
    1038                 :            : 
    1039                 :            :         pBand = pBand->mpNextBand;
    1040                 :            :     }
    1041                 :            : #endif
    1042                 :            : 
    1043                 :    1128458 :     return (mnRectCount != 0);
    1044                 :            : }
    1045                 :            : 
    1046                 :            : // =======================================================================
    1047                 :            : 
    1048                 :     990308 : void Region::ImplCopyData()
    1049                 :            : {
    1050                 :     990308 :     mpImplRegion->mnRefCount--;
    1051         [ +  - ]:     990308 :     mpImplRegion = new ImplRegion( *mpImplRegion );
    1052                 :     990308 : }
    1053                 :            : 
    1054                 :            : // =======================================================================
    1055                 :            : 
    1056                 :    1480075 : Region::Region()
    1057                 :            : {
    1058                 :            :     DBG_CTOR( Region, ImplDbgTestRegion );
    1059                 :            : 
    1060                 :    1480075 :     mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1061                 :    1480075 : }
    1062                 :            : 
    1063                 :            : // -----------------------------------------------------------------------
    1064                 :            : 
    1065                 :     965386 : Region::Region( RegionType eType )
    1066                 :            : {
    1067                 :            :     DBG_CTOR( Region, ImplDbgTestRegion );
    1068                 :            :     DBG_ASSERT( (eType == REGION_NULL) || (eType == REGION_EMPTY),
    1069                 :            :                 "Region( RegionType ) - RegionType != EMPTY/NULL" );
    1070                 :            : 
    1071         [ +  + ]:     965386 :     if ( eType == REGION_NULL )
    1072                 :     917157 :         mpImplRegion = (ImplRegion*)(&aImplNullRegion);
    1073                 :            :     else
    1074                 :      48229 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1075                 :     965386 : }
    1076                 :            : 
    1077                 :            : // -----------------------------------------------------------------------
    1078                 :            : 
    1079                 :     415602 : Region::Region( const Rectangle& rRect )
    1080                 :            : {
    1081                 :            :     DBG_CTOR( Region, ImplDbgTestRegion );
    1082                 :            : 
    1083                 :     415602 :     ImplCreateRectRegion( rRect );
    1084                 :     415602 : }
    1085                 :            : 
    1086                 :            : // -----------------------------------------------------------------------
    1087                 :            : 
    1088                 :          0 : Region::Region( const Polygon& rPolygon )
    1089                 :            : {
    1090                 :            :     DBG_CTOR( Region, ImplDbgTestRegion );
    1091                 :            :     DBG_CHKOBJ( &rPolygon, Polygon, NULL );
    1092                 :            : 
    1093         [ #  # ]:          0 :     ImplCreatePolyPolyRegion( rPolygon );
    1094                 :          0 : }
    1095                 :            : 
    1096                 :            : // -----------------------------------------------------------------------
    1097                 :            : 
    1098                 :        111 : Region::Region( const PolyPolygon& rPolyPoly )
    1099                 :            : {
    1100                 :            :     DBG_CTOR( Region, ImplDbgTestRegion );
    1101                 :            :     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
    1102                 :            : 
    1103                 :        111 :     ImplCreatePolyPolyRegion( rPolyPoly );
    1104                 :        111 : }
    1105                 :            : 
    1106                 :            : // -----------------------------------------------------------------------
    1107                 :            : 
    1108                 :         43 : Region::Region( const basegfx::B2DPolyPolygon& rPolyPoly )
    1109                 :            : {
    1110                 :            :     DBG_CTOR( Region, ImplDbgTestRegion );
    1111                 :            :     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
    1112                 :            : 
    1113         [ +  - ]:         43 :     mpImplRegion = new ImplRegion( rPolyPoly );
    1114                 :         43 : }
    1115                 :            : 
    1116                 :            : // -----------------------------------------------------------------------
    1117                 :            : 
    1118                 :    2085336 : Region::Region( const Region& rRegion )
    1119                 :            : {
    1120                 :            :     DBG_CTOR( Region, ImplDbgTestRegion );
    1121                 :            :     DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
    1122                 :            :     DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
    1123                 :            : 
    1124                 :            :     // copy pointer to instance of implementation
    1125                 :    2085336 :     mpImplRegion = rRegion.mpImplRegion;
    1126         [ +  + ]:    2085336 :     if ( mpImplRegion->mnRefCount )
    1127                 :    1711212 :         mpImplRegion->mnRefCount++;
    1128                 :    2085336 : }
    1129                 :            : 
    1130                 :            : // -----------------------------------------------------------------------
    1131                 :            : 
    1132                 :    4914236 : Region::~Region()
    1133                 :            : {
    1134                 :            :     DBG_DTOR( Region, ImplDbgTestRegion );
    1135                 :            : 
    1136                 :            :     // statische Object haben RefCount von 0
    1137         [ +  + ]:    4914236 :     if ( mpImplRegion->mnRefCount )
    1138                 :            :     {
    1139         [ +  + ]:    2994269 :         if ( mpImplRegion->mnRefCount > 1 )
    1140                 :    1881433 :             mpImplRegion->mnRefCount--;
    1141                 :            :         else
    1142         [ +  - ]:    1112836 :             delete mpImplRegion;
    1143                 :            :     }
    1144                 :    4914236 : }
    1145                 :            : 
    1146                 :            : // -----------------------------------------------------------------------
    1147                 :            : 
    1148                 :     583800 : void Region::ImplCreateRectRegion( const Rectangle& rRect )
    1149                 :            : {
    1150         [ +  + ]:     583800 :     if ( rRect.IsEmpty() )
    1151                 :      43772 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1152                 :            :     else
    1153                 :            :     {
    1154                 :            :         // get justified rectangle
    1155                 :     540028 :         long nTop       = Min( rRect.Top(), rRect.Bottom() );
    1156                 :     540028 :         long nBottom    = Max( rRect.Top(), rRect.Bottom() );
    1157                 :     540028 :         long nLeft      = Min( rRect.Left(), rRect.Right() );
    1158                 :     540028 :         long nRight     = Max( rRect.Left(), rRect.Right() );
    1159                 :            : 
    1160                 :            :         // create instance of implementation class
    1161         [ +  - ]:     540028 :         mpImplRegion = new ImplRegion();
    1162                 :            : 
    1163                 :            :         // add band with boundaries of the rectangle
    1164         [ +  - ]:     540028 :         mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
    1165                 :            : 
    1166                 :            :         // Set left and right boundaries of the band
    1167                 :     540028 :         mpImplRegion->mpFirstBand->Union( nLeft, nRight );
    1168                 :     540028 :         mpImplRegion->mnRectCount = 1;
    1169                 :            :     }
    1170                 :     583800 : }
    1171                 :            : 
    1172                 :            : // -----------------------------------------------------------------------
    1173                 :            : 
    1174                 :        111 : void Region::ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly )
    1175                 :            : {
    1176                 :        111 :     const sal_uInt16 nPolyCount = rPolyPoly.Count();
    1177         [ +  - ]:        111 :     if ( nPolyCount )
    1178                 :            :     {
    1179                 :            :         // polypolygon empty? -> empty region
    1180         [ +  - ]:        111 :         const Rectangle aRect( rPolyPoly.GetBoundRect() );
    1181                 :            : 
    1182 [ +  - ][ +  - ]:        111 :         if ( !aRect.IsEmpty() )
    1183                 :            :         {
    1184                 :            :             // width OR height == 1 ? => Rectangular region
    1185 [ +  - ][ +  - ]:        333 :             if ( (aRect.GetWidth() == 1)
         [ +  - ][ +  + ]
                 [ +  + ]
    1186         [ +  - ]:        111 :                 || (aRect.GetHeight() == 1)
    1187         [ +  - ]:        111 :                 || rPolyPoly.IsRect() )
    1188                 :            :             {
    1189         [ +  - ]:         89 :                 ImplCreateRectRegion( aRect );
    1190                 :            :             }
    1191                 :            :             else
    1192 [ +  - ][ +  - ]:         22 :                 mpImplRegion = new ImplRegion( rPolyPoly );
    1193                 :            :         }
    1194                 :            :         else
    1195                 :        111 :             mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1196                 :            :     }
    1197                 :            :     else
    1198                 :          0 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1199                 :        111 : }
    1200                 :            : 
    1201                 :            : // -----------------------------------------------------------------------
    1202                 :            : 
    1203                 :         26 : void Region::ImplPolyPolyRegionToBandRegionFunc()
    1204                 :            : {
    1205                 :            :     // ensure to subdivide when bezier segemnts are used, it's going to
    1206                 :            :     // be expanded to rectangles
    1207         [ +  - ]:         26 :     PolyPolygon aPolyPoly;
    1208 [ +  - ][ +  - ]:         26 :     GetPolyPolygon().AdaptiveSubdivide(aPolyPoly);
                 [ +  - ]
    1209                 :            : 
    1210         [ +  + ]:         26 :     if ( mpImplRegion->mnRefCount > 1 )
    1211                 :         10 :         mpImplRegion->mnRefCount--;
    1212                 :            :     else
    1213 [ +  - ][ +  - ]:         16 :         delete mpImplRegion;
    1214                 :            : 
    1215 [ +  - ][ +  - ]:         26 :     if ( aPolyPoly.Count() )
    1216                 :            :     {
    1217                 :            :         // polypolygon empty? -> empty region
    1218         [ +  - ]:         26 :         const Rectangle aRect( aPolyPoly.GetBoundRect() );
    1219                 :            : 
    1220 [ +  - ][ +  - ]:         26 :         if ( !aRect.IsEmpty() )
    1221                 :            :         {
    1222 [ +  - ][ +  - ]:         26 :             if (ImplIsPolygonRectilinear(aPolyPoly))
    1223                 :            :             {
    1224                 :            :                 // For rectilinear polygons there is an optimized band conversion.
    1225         [ +  - ]:         26 :                 mpImplRegion = ImplRectilinearPolygonToBands(aPolyPoly);
    1226                 :            :             }
    1227                 :            :             else
    1228                 :            :             {
    1229         [ #  # ]:          0 :                 mpImplRegion = ImplGeneralPolygonToBands(aPolyPoly, aRect);
    1230                 :            :             }
    1231                 :            : 
    1232                 :            :             // Convert points into seps.
    1233                 :         26 :             ImplRegionBand* pRegionBand = mpImplRegion->mpFirstBand;
    1234         [ +  + ]:         60 :             while ( pRegionBand )
    1235                 :            :             {
    1236                 :            :                 // generate separations from the lines and process union
    1237         [ +  - ]:         34 :                 pRegionBand->ProcessPoints();
    1238                 :         34 :                 pRegionBand = pRegionBand->mpNextBand;
    1239                 :            :             }
    1240                 :            : 
    1241                 :            :             // Optimize list of bands.  Adjacent bands with identical lists
    1242                 :            :             // of seps are joined.
    1243 [ +  - ][ -  + ]:         26 :             if ( !mpImplRegion->OptimizeBandList() )
    1244                 :            :             {
    1245 [ #  # ][ #  # ]:          0 :                 delete mpImplRegion;
    1246                 :          0 :                 mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1247                 :            :             }
    1248                 :            :         }
    1249                 :            :         else
    1250                 :         26 :             mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1251                 :            :     }
    1252                 :            :     else
    1253         [ +  - ]:         26 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1254                 :         26 : }
    1255                 :            : 
    1256                 :            : // -----------------------------------------------------------------------
    1257                 :            : 
    1258                 :     603771 : void Region::Move( long nHorzMove, long nVertMove )
    1259                 :            : {
    1260                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1261                 :            : 
    1262                 :            :     // no region data? -> nothing to do
    1263 [ +  + ][ +  + ]:     603771 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1264                 :     603771 :         return;
    1265                 :            : 
    1266                 :            :     // no own instance data? -> make own copy!
    1267         [ +  + ]:     459057 :     if ( mpImplRegion->mnRefCount > 1 )
    1268                 :     459004 :         ImplCopyData();
    1269                 :            : 
    1270         [ +  + ]:     459057 :     if ( mpImplRegion->mpPolyPoly )
    1271                 :         11 :         mpImplRegion->mpPolyPoly->Move( nHorzMove, nVertMove );
    1272         [ +  + ]:     459046 :     else if( mpImplRegion->mpB2DPolyPoly )
    1273                 :            :     {
    1274         [ +  - ]:         16 :         mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
    1275                 :            :     }
    1276                 :            :     else
    1277                 :            :     {
    1278                 :     459030 :         ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
    1279         [ +  + ]:     927659 :         while ( pBand )
    1280                 :            :         {
    1281                 :            :             // process the vertical move
    1282         [ +  + ]:     468629 :             if ( nVertMove != 0)
    1283                 :            :             {
    1284                 :     467116 :                 pBand->mnYTop = pBand->mnYTop + nVertMove;
    1285                 :     467116 :                 pBand->mnYBottom = pBand->mnYBottom + nVertMove;
    1286                 :            :             }
    1287                 :            : 
    1288                 :            :             // process the horizontal move
    1289         [ +  + ]:     468629 :             if ( nHorzMove != 0)
    1290                 :      89006 :                 pBand->MoveX( nHorzMove );
    1291                 :            : 
    1292                 :     468629 :             pBand = pBand->mpNextBand;
    1293                 :            :         }
    1294                 :            :     }
    1295                 :            : }
    1296                 :            : 
    1297                 :            : // -----------------------------------------------------------------------
    1298                 :            : 
    1299                 :          0 : void Region::Scale( double fScaleX, double fScaleY )
    1300                 :            : {
    1301                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1302                 :            : 
    1303                 :            :     // no region data? -> nothing to do
    1304 [ #  # ][ #  # ]:          0 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1305                 :          0 :         return;
    1306                 :            : 
    1307                 :            :     // no own instance data? -> make own copy!
    1308         [ #  # ]:          0 :     if ( mpImplRegion->mnRefCount > 1 )
    1309                 :          0 :         ImplCopyData();
    1310                 :            : 
    1311         [ #  # ]:          0 :     if ( mpImplRegion->mpPolyPoly )
    1312                 :          0 :         mpImplRegion->mpPolyPoly->Scale( fScaleX, fScaleY );
    1313         [ #  # ]:          0 :     else if( mpImplRegion->mpB2DPolyPoly )
    1314                 :            :     {
    1315         [ #  # ]:          0 :         mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
    1316                 :            :     }
    1317                 :            :     else
    1318                 :            :     {
    1319                 :          0 :         ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
    1320         [ #  # ]:          0 :         while ( pBand )
    1321                 :            :         {
    1322                 :            :             // process the vertical move
    1323         [ #  # ]:          0 :             if ( fScaleY != 0.0 )
    1324                 :            :             {
    1325                 :          0 :                 pBand->mnYTop = FRound( pBand->mnYTop * fScaleY );
    1326                 :          0 :                 pBand->mnYBottom = FRound( pBand->mnYBottom * fScaleY );
    1327                 :            :             }
    1328                 :            : 
    1329                 :            :             // process the horizontal move
    1330         [ #  # ]:          0 :             if ( fScaleX != 0.0 )
    1331                 :          0 :                 pBand->ScaleX( fScaleX );
    1332                 :            : 
    1333                 :          0 :             pBand = pBand->mpNextBand;
    1334                 :            :         }
    1335                 :            :     }
    1336                 :            : }
    1337                 :            : 
    1338                 :            : // -----------------------------------------------------------------------
    1339                 :            : 
    1340                 :       5416 : void Region::Union( const Rectangle& rRect )
    1341                 :            : {
    1342                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1343                 :            : 
    1344                 :            :     // is rectangle empty? -> nothing to do
    1345         [ +  + ]:       5416 :     if ( rRect.IsEmpty() )
    1346                 :       1456 :         return;
    1347                 :            : 
    1348         [ -  + ]:       3960 :     if( HasPolyPolygon() )
    1349                 :            :     {
    1350                 :            :         // get this B2DPolyPolygon
    1351         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
    1352 [ #  # ][ #  # ]:          0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
                 [ #  # ]
    1353                 :            : 
    1354 [ #  # ][ #  # ]:          0 :         if( aThisPolyPoly.count() == 0 )
    1355                 :            :         {
    1356         [ #  # ]:          0 :             *this = rRect;
    1357                 :            :             return;
    1358                 :            :         }
    1359                 :            : 
    1360                 :            :         // get the other B2DPolyPolygon
    1361 [ #  # ][ #  # ]:          0 :         basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
    1362         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
    1363                 :            : 
    1364         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
    1365 [ #  # ][ #  # ]:          0 :         *this = Region( aClip );
                 [ #  # ]
    1366                 :            : 
    1367 [ #  # ][ #  # ]:          0 :         return;
         [ #  # ][ #  # ]
    1368                 :            :     }
    1369                 :            : 
    1370                 :       3960 :     ImplPolyPolyRegionToBandRegion();
    1371                 :            : 
    1372                 :            :     // no instance data? -> create!
    1373 [ -  + ][ +  + ]:       3960 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1374         [ +  - ]:       1457 :         mpImplRegion = new ImplRegion();
    1375                 :            : 
    1376                 :            :     // no own instance data? -> make own copy!
    1377         [ -  + ]:       3960 :     if ( mpImplRegion->mnRefCount > 1 )
    1378                 :          0 :         ImplCopyData();
    1379                 :            : 
    1380                 :            :     // get justified rectangle
    1381                 :       3960 :     long nLeft      = Min( rRect.Left(), rRect.Right() );
    1382                 :       3960 :     long nTop       = Min( rRect.Top(), rRect.Bottom() );
    1383                 :       3960 :     long nRight     = Max( rRect.Left(), rRect.Right() );
    1384                 :       3960 :     long nBottom    = Max( rRect.Top(), rRect.Bottom() );
    1385                 :            : 
    1386                 :            :     // insert bands if the boundaries are not allready in the list
    1387                 :       3960 :     mpImplRegion->InsertBands( nTop, nBottom );
    1388                 :            : 
    1389                 :            :     // process union
    1390                 :       3960 :     mpImplRegion->Union( nLeft, nTop, nRight, nBottom );
    1391                 :            : 
    1392                 :            :     // cleanup
    1393         [ -  + ]:       3960 :     if ( !mpImplRegion->OptimizeBandList() )
    1394                 :            :     {
    1395         [ #  # ]:          0 :         delete mpImplRegion;
    1396                 :       5416 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1397                 :            :     }
    1398                 :            : }
    1399                 :            : 
    1400                 :            : // -----------------------------------------------------------------------
    1401                 :            : 
    1402                 :     362335 : void Region::Intersect( const Rectangle& rRect )
    1403                 :            : {
    1404                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1405                 :            : 
    1406                 :            :     // is rectangle empty? -> nothing to do
    1407         [ +  + ]:     362335 :     if ( rRect.IsEmpty() )
    1408                 :            :     {
    1409                 :            :         // statische Object haben RefCount von 0
    1410         [ +  + ]:         79 :         if ( mpImplRegion->mnRefCount )
    1411                 :            :         {
    1412         [ +  - ]:          8 :             if ( mpImplRegion->mnRefCount > 1 )
    1413                 :          8 :                 mpImplRegion->mnRefCount--;
    1414                 :            :             else
    1415         [ #  # ]:          0 :                 delete mpImplRegion;
    1416                 :            :         }
    1417                 :         79 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1418                 :         79 :         return;
    1419                 :            :     }
    1420                 :            : 
    1421                 :            :     // #103137# Avoid banding for special cases
    1422         [ -  + ]:     362256 :     if ( mpImplRegion->mpPolyPoly )
    1423                 :            :     {
    1424                 :            :         // #127431# make ImplRegion unique, if not already.
    1425         [ #  # ]:          0 :         if( mpImplRegion->mnRefCount > 1 )
    1426                 :            :         {
    1427                 :          0 :             mpImplRegion->mnRefCount--;
    1428         [ #  # ]:          0 :             mpImplRegion = new ImplRegion( *mpImplRegion->mpPolyPoly );
    1429                 :            :         }
    1430                 :            : 
    1431                 :            :         // use the PolyPolygon::Clip method for rectangles, this is
    1432                 :            :         // fairly simple (does not even use GPC) and saves us from
    1433                 :            :         // unnecessary banding
    1434                 :          0 :         mpImplRegion->mpPolyPoly->Clip( rRect );
    1435                 :            : 
    1436                 :          0 :         return;
    1437                 :            :     }
    1438         [ -  + ]:     362256 :     else if( mpImplRegion->mpB2DPolyPoly )
    1439                 :            :     {
    1440                 :            :         // #127431# make ImplRegion unique, if not already.
    1441         [ #  # ]:          0 :         if( mpImplRegion->mnRefCount > 1 )
    1442                 :            :         {
    1443                 :          0 :             mpImplRegion->mnRefCount--;
    1444         [ #  # ]:          0 :             mpImplRegion = new ImplRegion( *mpImplRegion->mpB2DPolyPoly );
    1445                 :            :         }
    1446                 :            : 
    1447                 :            :         *mpImplRegion->mpB2DPolyPoly =
    1448                 :            :         basegfx::tools::clipPolyPolygonOnRange( *mpImplRegion->mpB2DPolyPoly,
    1449                 :          0 :                                                 basegfx::B2DRange( rRect.Left(), rRect.Top(),
    1450                 :          0 :                                                                    rRect.Right(), rRect.Bottom() ),
    1451 [ #  # ][ #  # ]:          0 :                                                 true, false );
                 [ #  # ]
    1452                 :          0 :         return;
    1453                 :            :     }
    1454                 :            :     else
    1455                 :     362256 :         ImplPolyPolyRegionToBandRegion();
    1456                 :            : 
    1457                 :            :     // is region empty? -> nothing to do!
    1458         [ +  + ]:     362256 :     if ( mpImplRegion == &aImplEmptyRegion )
    1459                 :      35640 :         return;
    1460                 :            : 
    1461                 :            :     // get justified rectangle
    1462                 :     326616 :     long nLeft      = Min( rRect.Left(), rRect.Right() );
    1463                 :     326616 :     long nTop       = Min( rRect.Top(), rRect.Bottom() );
    1464                 :     326616 :     long nRight     = Max( rRect.Left(), rRect.Right() );
    1465                 :     326616 :     long nBottom    = Max( rRect.Top(), rRect.Bottom() );
    1466                 :            : 
    1467                 :            :     // is own region NULL-region? -> copy data!
    1468         [ +  + ]:     326616 :     if ( mpImplRegion == &aImplNullRegion )
    1469                 :            :     {
    1470                 :            :         // create instance of implementation class
    1471         [ +  - ]:      39507 :         mpImplRegion = new ImplRegion();
    1472                 :            : 
    1473                 :            :         // add band with boundaries of the rectangle
    1474         [ +  - ]:      39507 :         mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
    1475                 :            : 
    1476                 :            :         // Set left and right boundaries of the band
    1477                 :      39507 :         mpImplRegion->mpFirstBand->Union( nLeft, nRight );
    1478                 :      39507 :         mpImplRegion->mnRectCount = 1;
    1479                 :            : 
    1480                 :      39507 :         return;
    1481                 :            :     }
    1482                 :            : 
    1483                 :            :     // no own instance data? -> make own copy!
    1484         [ +  + ]:     287109 :     if ( mpImplRegion->mnRefCount > 1 )
    1485                 :     268486 :         ImplCopyData();
    1486                 :            : 
    1487                 :            :     // insert bands if the boundaries are not allready in the list
    1488                 :     287109 :     mpImplRegion->InsertBands( nTop, nBottom );
    1489                 :            : 
    1490                 :            :     // process intersections
    1491                 :     287109 :     ImplRegionBand* pPrevBand = 0;
    1492                 :     287109 :     ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
    1493         [ +  + ]:    1397884 :     while ( pBand )
    1494                 :            :     {
    1495                 :            :         // band within intersection boundary? -> process. otherwise remove
    1496 [ +  + ][ +  + ]:    1110775 :         if ( (pBand->mnYTop >= nTop) &&
    1497                 :            :              (pBand->mnYBottom <= nBottom) )
    1498                 :            :         {
    1499                 :            :             // process intersection
    1500                 :     883989 :             pBand->Intersect( nLeft, nRight );
    1501                 :            : 
    1502                 :     883989 :             pPrevBand = pBand;
    1503                 :     883989 :             pBand = pBand->mpNextBand;
    1504                 :            :         }
    1505                 :            :         else
    1506                 :            :         {
    1507                 :     226786 :             ImplRegionBand* pOldBand = pBand;
    1508         [ +  + ]:     226786 :             if ( pBand == mpImplRegion->mpFirstBand )
    1509                 :     222588 :                 mpImplRegion->mpFirstBand = pBand->mpNextBand;
    1510                 :            :             else
    1511                 :       4198 :                 pPrevBand->mpNextBand = pBand->mpNextBand;
    1512                 :     226786 :             pBand = pBand->mpNextBand;
    1513         [ +  - ]:     226786 :             delete pOldBand;
    1514                 :            :         }
    1515                 :            :     }
    1516                 :            : 
    1517                 :            :     // cleanup
    1518         [ +  + ]:     287109 :     if ( !mpImplRegion->OptimizeBandList() )
    1519                 :            :     {
    1520         [ +  - ]:     111087 :         delete mpImplRegion;
    1521                 :     362335 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1522                 :            :     }
    1523                 :            : }
    1524                 :            : 
    1525                 :            : // -----------------------------------------------------------------------
    1526                 :            : 
    1527                 :     101967 : void Region::Exclude( const Rectangle& rRect )
    1528                 :            : {
    1529                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1530                 :            : 
    1531                 :            :     // is rectangle empty? -> nothing to do
    1532         [ +  + ]:     101967 :     if ( rRect.IsEmpty() )
    1533                 :      23469 :         return;
    1534                 :            : 
    1535         [ -  + ]:      78498 :     if( HasPolyPolygon() )
    1536                 :            :     {
    1537                 :            :         // get this B2DPolyPolygon
    1538         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
    1539 [ #  # ][ #  # ]:          0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
                 [ #  # ]
    1540                 :            : 
    1541 [ #  # ][ #  # ]:          0 :         if( aThisPolyPoly.count() == 0 )
    1542                 :            :             return;
    1543                 :            : 
    1544                 :            :         // get the other B2DPolyPolygon
    1545 [ #  # ][ #  # ]:          0 :         basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
    1546         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
    1547                 :            : 
    1548         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
    1549 [ #  # ][ #  # ]:          0 :         *this = Region( aClip );
                 [ #  # ]
    1550                 :            : 
    1551 [ #  # ][ #  # ]:          0 :         return;
         [ #  # ][ #  # ]
    1552                 :            :     }
    1553                 :            : 
    1554                 :      78498 :     ImplPolyPolyRegionToBandRegion();
    1555                 :            : 
    1556                 :            :     // no instance data? -> create!
    1557 [ -  + ][ +  + ]:      78498 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1558                 :       2875 :         return;
    1559                 :            : 
    1560                 :            :     // no own instance data? -> make own copy!
    1561         [ +  + ]:      75623 :     if ( mpImplRegion->mnRefCount > 1 )
    1562                 :      38765 :         ImplCopyData();
    1563                 :            : 
    1564                 :            :     // get justified rectangle
    1565                 :      75623 :     long nLeft      = Min( rRect.Left(), rRect.Right() );
    1566                 :      75623 :     long nTop       = Min( rRect.Top(), rRect.Bottom() );
    1567                 :      75623 :     long nRight     = Max( rRect.Left(), rRect.Right() );
    1568                 :      75623 :     long nBottom    = Max( rRect.Top(), rRect.Bottom() );
    1569                 :            : 
    1570                 :            :     // insert bands if the boundaries are not allready in the list
    1571                 :      75623 :     mpImplRegion->InsertBands( nTop, nBottom );
    1572                 :            : 
    1573                 :            :     // process exclude
    1574                 :      75623 :     mpImplRegion->Exclude( nLeft, nTop, nRight, nBottom );
    1575                 :            : 
    1576                 :            :     // cleanup
    1577         [ +  + ]:      75623 :     if ( !mpImplRegion->OptimizeBandList() )
    1578                 :            :     {
    1579         [ +  - ]:      16132 :         delete mpImplRegion;
    1580                 :     101967 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1581                 :            :     }
    1582                 :            : }
    1583                 :            : 
    1584                 :            : // -----------------------------------------------------------------------
    1585                 :            : 
    1586                 :          0 : void Region::XOr( const Rectangle& rRect )
    1587                 :            : {
    1588                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1589                 :            : 
    1590                 :            :     // is rectangle empty? -> nothing to do
    1591         [ #  # ]:          0 :     if ( rRect.IsEmpty() )
    1592                 :          0 :         return;
    1593                 :            : 
    1594         [ #  # ]:          0 :     if( HasPolyPolygon() )
    1595                 :            :     {
    1596                 :            :         // get this B2DPolyPolygon
    1597         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
    1598 [ #  # ][ #  # ]:          0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
                 [ #  # ]
    1599                 :            : 
    1600 [ #  # ][ #  # ]:          0 :         if( aThisPolyPoly.count() == 0 )
    1601                 :            :         {
    1602         [ #  # ]:          0 :             *this = rRect;
    1603                 :            :             return;
    1604                 :            :         }
    1605                 :            : 
    1606                 :            :         // get the other B2DPolyPolygon
    1607 [ #  # ][ #  # ]:          0 :         basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
    1608         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
    1609                 :            : 
    1610         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
    1611 [ #  # ][ #  # ]:          0 :         *this = Region( aClip );
                 [ #  # ]
    1612                 :            : 
    1613 [ #  # ][ #  # ]:          0 :         return;
         [ #  # ][ #  # ]
    1614                 :            :     }
    1615                 :            : 
    1616                 :          0 :     ImplPolyPolyRegionToBandRegion();
    1617                 :            : 
    1618                 :            :     // no instance data? -> create!
    1619 [ #  # ][ #  # ]:          0 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1620         [ #  # ]:          0 :         mpImplRegion = new ImplRegion();
    1621                 :            : 
    1622                 :            :     // no own instance data? -> make own copy!
    1623         [ #  # ]:          0 :     if ( mpImplRegion->mnRefCount > 1 )
    1624                 :          0 :         ImplCopyData();
    1625                 :            : 
    1626                 :            :     // get justified rectangle
    1627                 :          0 :     long nLeft      = Min( rRect.Left(), rRect.Right() );
    1628                 :          0 :     long nTop       = Min( rRect.Top(), rRect.Bottom() );
    1629                 :          0 :     long nRight     = Max( rRect.Left(), rRect.Right() );
    1630                 :          0 :     long nBottom    = Max( rRect.Top(), rRect.Bottom() );
    1631                 :            : 
    1632                 :            :     // insert bands if the boundaries are not allready in the list
    1633                 :          0 :     mpImplRegion->InsertBands( nTop, nBottom );
    1634                 :            : 
    1635                 :            :     // process xor
    1636                 :          0 :     mpImplRegion->XOr( nLeft, nTop, nRight, nBottom );
    1637                 :            : 
    1638                 :            :     // cleanup
    1639         [ #  # ]:          0 :     if ( !mpImplRegion->OptimizeBandList() )
    1640                 :            :     {
    1641         [ #  # ]:          0 :         delete mpImplRegion;
    1642                 :          0 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1643                 :            :     }
    1644                 :            : }
    1645                 :            : 
    1646                 :            : // -----------------------------------------------------------------------
    1647                 :         13 : void Region::ImplUnionPolyPolygon( const Region& i_rRegion )
    1648                 :            : {
    1649                 :            :     // get this B2DPolyPolygon
    1650         [ +  - ]:         13 :     basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
    1651 [ +  - ][ +  - ]:         13 :     aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
                 [ +  - ]
    1652                 :            : 
    1653 [ +  - ][ -  + ]:         13 :     if( aThisPolyPoly.count() == 0 )
    1654                 :            :     {
    1655         [ #  # ]:          0 :         *this = i_rRegion;
    1656                 :         13 :         return;
    1657                 :            :     }
    1658                 :            : 
    1659                 :            :     // get the other B2DPolyPolygon
    1660         [ +  - ]:         13 :     basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
    1661 [ +  - ][ +  - ]:         13 :     aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
                 [ +  - ]
    1662                 :            : 
    1663                 :            : 
    1664         [ +  - ]:         13 :     basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
    1665                 :            : 
    1666 [ +  - ][ +  - ]:         13 :     *this = Region( aClip );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1667                 :            : }
    1668                 :            : 
    1669                 :     151702 : void Region::Union( const Region& rRegion )
    1670                 :            : {
    1671                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1672                 :            : 
    1673 [ +  + ][ +  + ]:     151702 :     if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
                 [ +  + ]
    1674                 :            :     {
    1675                 :         13 :         ImplUnionPolyPolygon( rRegion );
    1676                 :         13 :         return;
    1677                 :            :     }
    1678                 :            : 
    1679                 :     151689 :     ImplPolyPolyRegionToBandRegion();
    1680                 :     151689 :     ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
    1681                 :            : 
    1682                 :            :     // is region empty or null? -> nothing to do
    1683 [ -  + ][ +  + ]:     151689 :     if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
    1684                 :       2131 :         return;
    1685                 :            : 
    1686                 :            :     // no instance data? -> create!
    1687 [ +  + ][ -  + ]:     149558 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1688         [ +  - ]:      82415 :         mpImplRegion = new ImplRegion();
    1689                 :            : 
    1690                 :            :     // no own instance data? -> make own copy!
    1691         [ -  + ]:     149558 :     if ( mpImplRegion->mnRefCount > 1 )
    1692                 :          0 :         ImplCopyData();
    1693                 :            : 
    1694                 :            :     // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
    1695                 :     149558 :     ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
    1696         [ +  + ]:     303877 :     while ( pBand )
    1697                 :            :     {
    1698                 :            :         // insert bands if the boundaries are not allready in the list
    1699                 :     154319 :         mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
    1700                 :            : 
    1701                 :            :         // process all elements of the list
    1702                 :     154319 :         ImplRegionBandSep* pSep = pBand->mpFirstSep;
    1703         [ +  + ]:     316057 :         while ( pSep )
    1704                 :            :         {
    1705                 :            :             mpImplRegion->Union( pSep->mnXLeft, pBand->mnYTop,
    1706                 :     161738 :                                  pSep->mnXRight, pBand->mnYBottom );
    1707                 :     161738 :             pSep = pSep->mpNextSep;
    1708                 :            :         }
    1709                 :            : 
    1710                 :     154319 :         pBand = pBand->mpNextBand;
    1711                 :            :     }
    1712                 :            : 
    1713                 :            :     // cleanup
    1714         [ -  + ]:     149558 :     if ( !mpImplRegion->OptimizeBandList() )
    1715                 :            :     {
    1716         [ #  # ]:          0 :         delete mpImplRegion;
    1717                 :     151702 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1718                 :            :     }
    1719                 :            : }
    1720                 :            : 
    1721                 :            : // -----------------------------------------------------------------------
    1722                 :         30 : void Region::ImplIntersectWithPolyPolygon( const Region& i_rRegion )
    1723                 :            : {
    1724                 :            :     // get this B2DPolyPolygon
    1725         [ +  - ]:         30 :     basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
    1726 [ +  - ][ -  + ]:         30 :     if( aThisPolyPoly.count() == 0 )
    1727                 :            :     {
    1728         [ #  # ]:          0 :         *this = i_rRegion;
    1729                 :         30 :         return;
    1730                 :            :     }
    1731                 :            : 
    1732                 :            :     // get the other B2DPolyPolygon
    1733         [ +  - ]:         30 :     basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
    1734                 :            : 
    1735         [ +  - ]:         30 :     basegfx::B2DPolyPolygon aClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aOtherPolyPoly, aThisPolyPoly, true, false );
    1736 [ +  - ][ +  - ]:         30 :     *this = Region( aClip );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1737                 :            : }
    1738                 :            : 
    1739                 :    1013662 : void Region::Intersect( const Region& rRegion )
    1740                 :            : {
    1741                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1742                 :            : 
    1743                 :            :     // same instance data? -> nothing to do!
    1744         [ +  + ]:    1013662 :     if ( mpImplRegion == rRegion.mpImplRegion )
    1745                 :       4247 :         return;
    1746                 :            : 
    1747 [ +  + ][ +  + ]:    1009415 :     if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
                 [ +  + ]
    1748                 :            :     {
    1749                 :         30 :         ImplIntersectWithPolyPolygon( rRegion );
    1750                 :         30 :         return;
    1751                 :            :     }
    1752                 :            : 
    1753                 :    1009385 :     ImplPolyPolyRegionToBandRegion();
    1754                 :    1009385 :     ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
    1755                 :            : 
    1756         [ +  + ]:    1009385 :     if ( mpImplRegion == &aImplEmptyRegion )
    1757                 :      42441 :         return;
    1758                 :            : 
    1759                 :            :     // is region null? -> nothing to do
    1760         [ -  + ]:     966944 :     if ( rRegion.mpImplRegion == &aImplNullRegion )
    1761                 :          0 :         return;
    1762                 :            : 
    1763                 :            :     // is rectangle empty? -> nothing to do
    1764         [ +  + ]:     966944 :     if ( rRegion.mpImplRegion == &aImplEmptyRegion )
    1765                 :            :     {
    1766                 :            :         // statische Object haben RefCount von 0
    1767         [ +  + ]:     172528 :         if ( mpImplRegion->mnRefCount )
    1768                 :            :         {
    1769         [ +  + ]:     154706 :             if ( mpImplRegion->mnRefCount > 1 )
    1770                 :     148693 :                 mpImplRegion->mnRefCount--;
    1771                 :            :             else
    1772         [ +  - ]:       6013 :                 delete mpImplRegion;
    1773                 :            :         }
    1774                 :     172528 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1775                 :     172528 :         return;
    1776                 :            :     }
    1777                 :            : 
    1778                 :            :     // is own region NULL-region? -> copy data!
    1779         [ +  + ]:     794416 :     if ( mpImplRegion == &aImplNullRegion)
    1780                 :            :     {
    1781                 :     161164 :         mpImplRegion = rRegion.mpImplRegion;
    1782                 :     161164 :         rRegion.mpImplRegion->mnRefCount++;
    1783                 :     161164 :         return;
    1784                 :            :     }
    1785                 :            : 
    1786                 :            :     // Wenn wir weniger Rechtecke haben, drehen wir den Intersect-Aufruf um
    1787         [ +  + ]:     633252 :     if ( mpImplRegion->mnRectCount+2 < rRegion.mpImplRegion->mnRectCount )
    1788                 :            :     {
    1789         [ +  - ]:      25793 :         Region aTempRegion = rRegion;
    1790         [ +  - ]:      25793 :         aTempRegion.Intersect( *this );
    1791 [ +  - ][ +  - ]:      25793 :         *this = aTempRegion;
    1792                 :            :     }
    1793                 :            :     else
    1794                 :            :     {
    1795                 :            :         // no own instance data? -> make own copy!
    1796         [ +  + ]:     607459 :         if ( mpImplRegion->mnRefCount > 1 )
    1797                 :     224053 :             ImplCopyData();
    1798                 :            : 
    1799                 :            :         // mark all bands as untouched
    1800                 :     607459 :         ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
    1801         [ +  + ]:    1229820 :         while ( pBand )
    1802                 :            :         {
    1803                 :     622361 :             pBand->mbTouched = sal_False;
    1804                 :     622361 :             pBand = pBand->mpNextBand;
    1805                 :            :         }
    1806                 :            : 
    1807                 :     607459 :         pBand = rRegion.mpImplRegion->mpFirstBand;
    1808         [ +  + ]:    1217271 :         while ( pBand )
    1809                 :            :         {
    1810                 :            :             // insert bands if the boundaries are not allready in the list
    1811                 :     609812 :             mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
    1812                 :            : 
    1813                 :            :             // process all elements of the list
    1814                 :     609812 :             ImplRegionBandSep* pSep = pBand->mpFirstSep;
    1815         [ +  + ]:    1247395 :             while ( pSep )
    1816                 :            :             {
    1817                 :            :                 // left boundary?
    1818         [ +  + ]:     637583 :                 if ( pSep == pBand->mpFirstSep )
    1819                 :            :                 {
    1820                 :            :                     // process intersection and do not remove untouched bands
    1821                 :            :                     mpImplRegion->Exclude( LONG_MIN+1, pBand->mnYTop,
    1822                 :     609812 :                                            pSep->mnXLeft-1, pBand->mnYBottom );
    1823                 :            :                 }
    1824                 :            : 
    1825                 :            :                 // right boundary?
    1826         [ +  + ]:     637583 :                 if ( pSep->mpNextSep == NULL )
    1827                 :            :                 {
    1828                 :            :                     // process intersection and do not remove untouched bands
    1829                 :            :                     mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
    1830                 :     609812 :                                            LONG_MAX-1, pBand->mnYBottom );
    1831                 :            :                 }
    1832                 :            :                 else
    1833                 :            :                 {
    1834                 :            :                     // process intersection and do not remove untouched bands
    1835                 :            :                     mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
    1836                 :      27771 :                                            pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
    1837                 :            :                 }
    1838                 :            : 
    1839                 :     637583 :                 pSep = pSep->mpNextSep;
    1840                 :            :             }
    1841                 :            : 
    1842                 :     609812 :             pBand = pBand->mpNextBand;
    1843                 :            :         }
    1844                 :            : 
    1845                 :            :         // remove all untouched bands if bands allready left
    1846                 :     607459 :         ImplRegionBand* pPrevBand = 0;
    1847                 :     607459 :         pBand = mpImplRegion->mpFirstBand;
    1848         [ +  + ]:    3228730 :         while ( pBand )
    1849                 :            :         {
    1850         [ +  + ]:    2621271 :             if ( !pBand->mbTouched )
    1851                 :            :             {
    1852                 :            :                 // save pointer
    1853                 :     588214 :                 ImplRegionBand* pOldBand = pBand;
    1854                 :            : 
    1855                 :            :                 // previous element of the list
    1856         [ +  + ]:     588214 :                 if ( pBand == mpImplRegion->mpFirstBand )
    1857                 :     378923 :                     mpImplRegion->mpFirstBand = pBand->mpNextBand;
    1858                 :            :                 else
    1859                 :     209291 :                     pPrevBand->mpNextBand = pBand->mpNextBand;
    1860                 :            : 
    1861                 :     588214 :                 pBand = pBand->mpNextBand;
    1862         [ +  - ]:     588214 :                 delete pOldBand;
    1863                 :            :             }
    1864                 :            :             else
    1865                 :            :             {
    1866                 :    2033057 :                 pPrevBand = pBand;
    1867                 :    2033057 :                 pBand = pBand->mpNextBand;
    1868                 :            :             }
    1869                 :            :         }
    1870                 :            : 
    1871                 :            :         // cleanup
    1872         [ +  + ]:     607459 :         if ( !mpImplRegion->OptimizeBandList() )
    1873                 :            :         {
    1874         [ +  - ]:      41365 :             delete mpImplRegion;
    1875                 :    1013662 :             mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1876                 :            :         }
    1877                 :            :     }
    1878                 :            : }
    1879                 :            : 
    1880                 :            : // -----------------------------------------------------------------------
    1881                 :          0 : void Region::ImplExcludePolyPolygon( const Region& i_rRegion )
    1882                 :            : {
    1883                 :            :     // get this B2DPolyPolygon
    1884         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
    1885 [ #  # ][ #  # ]:          0 :     if( aThisPolyPoly.count() == 0 )
    1886                 :          0 :         return;
    1887 [ #  # ][ #  # ]:          0 :     aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
                 [ #  # ]
    1888                 :            : 
    1889                 :            :     // get the other B2DPolyPolygon
    1890         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
    1891 [ #  # ][ #  # ]:          0 :     aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
                 [ #  # ]
    1892                 :            : 
    1893         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
    1894 [ #  # ][ #  # ]:          0 :     *this = Region( aClip );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1895                 :            : }
    1896                 :            : 
    1897                 :       3051 : void Region::Exclude( const Region& rRegion )
    1898                 :            : {
    1899                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1900                 :            : 
    1901 [ +  - ][ -  + ]:       3051 :     if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
                 [ -  + ]
    1902                 :            :     {
    1903                 :          0 :         ImplExcludePolyPolygon( rRegion );
    1904                 :          0 :         return;
    1905                 :            :     }
    1906                 :            : 
    1907                 :       3051 :     ImplPolyPolyRegionToBandRegion();
    1908                 :       3051 :     ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
    1909                 :            : 
    1910                 :            :     // is region empty or null? -> nothing to do
    1911 [ -  + ][ +  + ]:       3051 :     if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
    1912                 :       1591 :         return;
    1913                 :            : 
    1914                 :            :     // no instance data? -> nothing to do
    1915 [ +  - ][ -  + ]:       1460 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1916                 :          0 :         return;
    1917                 :            : 
    1918                 :            :     // no own instance data? -> make own copy!
    1919         [ -  + ]:       1460 :     if ( mpImplRegion->mnRefCount > 1 )
    1920                 :          0 :         ImplCopyData();
    1921                 :            : 
    1922                 :            :     // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
    1923                 :       1460 :     ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
    1924         [ +  + ]:       4520 :     while ( pBand )
    1925                 :            :     {
    1926                 :            :         // insert bands if the boundaries are not allready in the list
    1927                 :       1469 :         mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
    1928                 :            : 
    1929                 :            :         // process all elements of the list
    1930                 :       1469 :         ImplRegionBandSep* pSep = pBand->mpFirstSep;
    1931         [ +  + ]:       2938 :         while ( pSep )
    1932                 :            :         {
    1933                 :            :             mpImplRegion->Exclude( pSep->mnXLeft, pBand->mnYTop,
    1934                 :       1469 :                                    pSep->mnXRight, pBand->mnYBottom );
    1935                 :       1469 :             pSep = pSep->mpNextSep;
    1936                 :            :         }
    1937                 :            : 
    1938                 :            :         // Wir optimieren schon in der Schleife, da wir davon
    1939                 :            :         // ausgehen, das wir insgesammt weniger Baender ueberpruefen
    1940                 :            :         // muessen
    1941         [ -  + ]:       1469 :         if ( !mpImplRegion->OptimizeBandList() )
    1942                 :            :         {
    1943         [ #  # ]:          0 :             delete mpImplRegion;
    1944                 :          0 :             mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    1945                 :          0 :             break;
    1946                 :            :         }
    1947                 :            : 
    1948                 :       1469 :         pBand = pBand->mpNextBand;
    1949                 :            :     }
    1950                 :            : }
    1951                 :            : 
    1952                 :            : // -----------------------------------------------------------------------
    1953                 :          0 : void Region::ImplXOrPolyPolygon( const Region& i_rRegion )
    1954                 :            : {
    1955                 :            :     // get this B2DPolyPolygon
    1956         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
    1957 [ #  # ][ #  # ]:          0 :     if( aThisPolyPoly.count() == 0 )
    1958                 :            :     {
    1959         [ #  # ]:          0 :         *this = i_rRegion;
    1960                 :          0 :         return;
    1961                 :            :     }
    1962 [ #  # ][ #  # ]:          0 :     aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
                 [ #  # ]
    1963                 :            : 
    1964                 :            :     // get the other B2DPolyPolygon
    1965         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
    1966 [ #  # ][ #  # ]:          0 :     aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
                 [ #  # ]
    1967                 :            : 
    1968         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
    1969 [ #  # ][ #  # ]:          0 :     *this = Region( aClip );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1970                 :            : }
    1971                 :            : 
    1972                 :          0 : void Region::XOr( const Region& rRegion )
    1973                 :            : {
    1974                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    1975                 :            : 
    1976 [ #  # ][ #  # ]:          0 :     if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
                 [ #  # ]
    1977                 :            :     {
    1978                 :          0 :         ImplXOrPolyPolygon( rRegion );
    1979                 :          0 :         return;
    1980                 :            :     }
    1981                 :            : 
    1982                 :          0 :     ImplPolyPolyRegionToBandRegion();
    1983                 :          0 :     ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
    1984                 :            : 
    1985                 :            :     // is region empty or null? -> nothing to do
    1986 [ #  # ][ #  # ]:          0 :     if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
    1987                 :          0 :         return;
    1988                 :            : 
    1989                 :            :     // no own instance data? -> XOr = copy
    1990 [ #  # ][ #  # ]:          0 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    1991                 :            :     {
    1992                 :          0 :         *this = rRegion;
    1993                 :          0 :         return;
    1994                 :            :     }
    1995                 :            : 
    1996                 :            :     // no own instance data? -> make own copy!
    1997         [ #  # ]:          0 :     if ( mpImplRegion->mnRefCount > 1 )
    1998                 :          0 :         ImplCopyData();
    1999                 :            : 
    2000                 :            :     // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
    2001                 :          0 :     ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
    2002         [ #  # ]:          0 :     while ( pBand )
    2003                 :            :     {
    2004                 :            :         // insert bands if the boundaries are not allready in the list
    2005                 :          0 :         mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
    2006                 :            : 
    2007                 :            :         // process all elements of the list
    2008                 :          0 :         ImplRegionBandSep* pSep = pBand->mpFirstSep;
    2009         [ #  # ]:          0 :         while ( pSep )
    2010                 :            :         {
    2011                 :            :             mpImplRegion->XOr( pSep->mnXLeft, pBand->mnYTop,
    2012                 :          0 :                                pSep->mnXRight, pBand->mnYBottom );
    2013                 :          0 :             pSep = pSep->mpNextSep;
    2014                 :            :         }
    2015                 :            : 
    2016                 :          0 :         pBand = pBand->mpNextBand;
    2017                 :            :     }
    2018                 :            : 
    2019                 :            :     // cleanup
    2020         [ #  # ]:          0 :     if ( !mpImplRegion->OptimizeBandList() )
    2021                 :            :     {
    2022         [ #  # ]:          0 :         delete mpImplRegion;
    2023                 :          0 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    2024                 :            :     }
    2025                 :            : }
    2026                 :            : 
    2027                 :            : // -----------------------------------------------------------------------
    2028                 :            : 
    2029                 :     687911 : Rectangle Region::GetBoundRect() const
    2030                 :            : {
    2031                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2032                 :            : 
    2033         [ +  - ]:     687911 :     Rectangle aRect;
    2034                 :            : 
    2035                 :            :     // no internal data? -> region is empty!
    2036 [ +  + ][ +  + ]:     687911 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2037                 :       3504 :         return aRect;
    2038                 :            : 
    2039                 :            :     // PolyPolygon data im Imp structure?
    2040         [ -  + ]:     684407 :     if ( mpImplRegion->mpPolyPoly )
    2041         [ #  # ]:          0 :         return mpImplRegion->mpPolyPoly->GetBoundRect();
    2042         [ +  + ]:     684407 :     if( mpImplRegion->mpB2DPolyPoly )
    2043                 :            :     {
    2044         [ +  - ]:          8 :         const basegfx::B2DRange aRange = basegfx::tools::getRange( *mpImplRegion->mpB2DPolyPoly );
    2045 [ +  - ][ +  - ]:          8 :         aRect.SetPos( Point( (int)aRange.getMinX(), (int)aRange.getMinY() ) );
    2046 [ +  - ][ +  - ]:          8 :         aRect.SetSize( Size( (int)aRange.getWidth(), (int)aRange.getHeight() ) );
                 [ +  - ]
    2047                 :          8 :         return aRect;
    2048                 :            :     }
    2049                 :            : 
    2050                 :            :     // no band in the list? -> region is empty!
    2051         [ -  + ]:     684399 :     if ( !mpImplRegion->mpFirstBand )
    2052                 :          0 :         return aRect;
    2053                 :            : 
    2054                 :            :     // get the boundaries of the first band
    2055                 :     684399 :     long nYTop    = mpImplRegion->mpFirstBand->mnYTop;
    2056                 :     684399 :     long nYBottom = mpImplRegion->mpFirstBand->mnYBottom;
    2057         [ +  - ]:     684399 :     long nXLeft   = mpImplRegion->mpFirstBand->GetXLeftBoundary();
    2058         [ +  - ]:     684399 :     long nXRight  = mpImplRegion->mpFirstBand->GetXRightBoundary();
    2059                 :            : 
    2060                 :            :     // look in the band list (don't test first band again!)
    2061                 :     684399 :     ImplRegionBand* pBand = mpImplRegion->mpFirstBand->mpNextBand;
    2062         [ +  + ]:     692373 :     while ( pBand )
    2063                 :            :     {
    2064                 :       7974 :         nYBottom    = pBand->mnYBottom;
    2065         [ +  - ]:       7974 :         nXLeft      = Min( nXLeft, pBand->GetXLeftBoundary() );
    2066         [ +  - ]:       7974 :         nXRight     = Max( nXRight, pBand->GetXRightBoundary() );
    2067                 :            : 
    2068                 :       7974 :         pBand = pBand->mpNextBand;
    2069                 :            :     }
    2070                 :            : 
    2071                 :            :     // set rectangle
    2072         [ +  - ]:     684399 :     aRect = Rectangle( nXLeft, nYTop, nXRight, nYBottom );
    2073                 :     687911 :     return aRect;
    2074                 :            : }
    2075                 :            : 
    2076                 :            : // -----------------------------------------------------------------------
    2077                 :            : 
    2078                 :    2412436 : sal_Bool Region::HasPolyPolygon() const
    2079                 :            : {
    2080                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2081         [ -  + ]:    2412436 :     if( !mpImplRegion )
    2082                 :          0 :         return false;
    2083         [ +  + ]:    2412436 :     if( mpImplRegion->mpPolyPoly )
    2084                 :         22 :         return true;
    2085         [ +  + ]:    2412414 :     if( mpImplRegion->mpB2DPolyPoly )
    2086                 :         65 :         return true;
    2087                 :    2412436 :     return false;
    2088                 :            : }
    2089                 :            : 
    2090                 :            : // -----------------------------------------------------------------------
    2091                 :            : 
    2092                 :         26 : PolyPolygon Region::GetPolyPolygon() const
    2093                 :            : {
    2094                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2095                 :            : 
    2096                 :         26 :     PolyPolygon aRet;
    2097                 :            : 
    2098         [ -  + ]:         26 :     if( mpImplRegion->mpPolyPoly )
    2099         [ #  # ]:          0 :         aRet = *mpImplRegion->mpPolyPoly;
    2100         [ +  - ]:         26 :     else if( mpImplRegion->mpB2DPolyPoly )
    2101                 :            :     {
    2102                 :            :         // the polygon needs to be converted
    2103 [ +  - ][ +  - ]:         26 :         aRet = PolyPolygon( *mpImplRegion->mpB2DPolyPoly );
                 [ +  - ]
    2104                 :            :         // TODO: cache the converted polygon?
    2105                 :            :         // mpImplRegion->mpB2DPolyPoly = aRet;
    2106                 :            :     }
    2107                 :            : 
    2108                 :         26 :     return aRet;
    2109                 :            : }
    2110                 :            : 
    2111                 :            : // -----------------------------------------------------------------------
    2112                 :            : 
    2113                 :        174 : const basegfx::B2DPolyPolygon Region::GetB2DPolyPolygon() const
    2114                 :            : {
    2115                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2116                 :            : 
    2117                 :        174 :     basegfx::B2DPolyPolygon aRet;
    2118                 :            : 
    2119         [ +  + ]:        174 :     if( mpImplRegion->mpB2DPolyPoly )
    2120         [ +  - ]:         33 :         aRet = *mpImplRegion->mpB2DPolyPoly;
    2121         [ +  + ]:        141 :     else if( mpImplRegion->mpPolyPoly )
    2122                 :            :     {
    2123                 :            :         // the polygon needs to be converted
    2124 [ +  - ][ +  - ]:         11 :         aRet = mpImplRegion->mpPolyPoly->getB2DPolyPolygon();
                 [ +  - ]
    2125                 :            :         // TODO: cache the converted polygon?
    2126                 :            :         // mpImplRegion->mpB2DPolyPoly = aRet;
    2127                 :            :     }
    2128                 :            : 
    2129                 :        174 :     return aRet;
    2130                 :            : }
    2131                 :            : 
    2132                 :            : // -----------------------------------------------------------------------
    2133                 :            : 
    2134                 :         86 : basegfx::B2DPolyPolygon Region::ConvertToB2DPolyPolygon()
    2135                 :            : {
    2136                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2137                 :            : 
    2138                 :         86 :     basegfx::B2DPolyPolygon aRet;
    2139                 :            : 
    2140 [ +  + ][ +  - ]:         86 :     if( HasPolyPolygon() )
    2141 [ +  - ][ +  - ]:         44 :         aRet = GetB2DPolyPolygon();
                 [ +  - ]
    2142                 :            :     else
    2143                 :            :     {
    2144         [ +  - ]:         42 :         RegionHandle aHdl = BeginEnumRects();
    2145         [ +  - ]:         42 :         Rectangle aSubRect;
    2146 [ +  - ][ +  + ]:         88 :         while( GetNextEnumRect( aHdl, aSubRect ) )
    2147                 :            :         {
    2148                 :            :             basegfx::B2DPolygon aPoly( basegfx::tools::createPolygonFromRect(
    2149 [ +  - ][ +  - ]:         46 :                  basegfx::B2DRectangle( aSubRect.Left(), aSubRect.Top(), aSubRect.Right(), aSubRect.Bottom() ) ) );
    2150         [ +  - ]:         46 :             aRet.append( aPoly );
    2151         [ +  - ]:         46 :         }
    2152         [ +  - ]:         42 :         EndEnumRects( aHdl );
    2153                 :            :     }
    2154                 :            : 
    2155                 :         86 :     return aRet;
    2156                 :            : }
    2157                 :            : 
    2158                 :            : // -----------------------------------------------------------------------
    2159                 :            : 
    2160                 :     165763 : bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
    2161                 :            :                                long& rX, long& rY,
    2162                 :            :                                long& rWidth, long& rHeight ) const
    2163                 :            : {
    2164                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2165                 :            : 
    2166                 :     165763 :     ((Region*)this)->ImplPolyPolyRegionToBandRegion();
    2167                 :            : 
    2168                 :            :     // no internal data? -> region is empty!
    2169 [ -  + ][ +  + ]:     165763 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2170                 :        538 :         return false;
    2171                 :            : 
    2172                 :            :     // no band in the list? -> region is empty!
    2173         [ -  + ]:     165225 :     if ( mpImplRegion->mpFirstBand == NULL )
    2174                 :          0 :         return false;
    2175                 :            : 
    2176                 :            :     // initialise pointer for first access
    2177                 :     165225 :     ImplRegionBand*     pCurrRectBand = mpImplRegion->mpFirstBand;
    2178                 :     165225 :     ImplRegionBandSep*  pCurrRectBandSep = pCurrRectBand->mpFirstSep;
    2179                 :            : 
    2180                 :            :     DBG_ASSERT( pCurrRectBandSep != NULL, "Erstes Band wurde nicht optimiert." );
    2181         [ -  + ]:     165225 :     if ( !pCurrRectBandSep )
    2182                 :          0 :         return false;
    2183                 :            : 
    2184                 :            :     // get boundaries of current rectangle
    2185                 :     165225 :     rX      = pCurrRectBandSep->mnXLeft;
    2186                 :     165225 :     rY      = pCurrRectBand->mnYTop;
    2187                 :     165225 :     rWidth  = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
    2188                 :     165225 :     rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
    2189                 :            : 
    2190                 :            :     // save pointers
    2191                 :     165225 :     rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
    2192                 :     165225 :     rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
    2193                 :            : 
    2194                 :     165763 :     return true;
    2195                 :            : }
    2196                 :            : 
    2197                 :            : // -----------------------------------------------------------------------
    2198                 :            : 
    2199                 :     252183 : bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
    2200                 :            :                               long& rX, long& rY,
    2201                 :            :                               long& rWidth, long& rHeight ) const
    2202                 :            : {
    2203                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2204                 :            : 
    2205                 :            :     // no internal data? -> region is empty!
    2206 [ +  - ][ -  + ]:     252183 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2207                 :          0 :         return false;
    2208                 :            : 
    2209                 :            :     // get last pointers
    2210                 :     252183 :     ImplRegionBand*     pCurrRectBand = (ImplRegionBand*)rImplRegionInfo.mpVoidCurrRectBand;
    2211                 :     252183 :     ImplRegionBandSep*  pCurrRectBandSep = (ImplRegionBandSep*)rImplRegionInfo.mpVoidCurrRectBandSep;
    2212                 :            : 
    2213                 :            :     // get next separation from current band
    2214                 :     252183 :     pCurrRectBandSep = pCurrRectBandSep->mpNextSep;
    2215                 :            : 
    2216                 :            :     // no separation found? -> go to next band!
    2217         [ +  + ]:     252183 :     if ( !pCurrRectBandSep )
    2218                 :            :     {
    2219                 :            :         // get next band
    2220                 :     173642 :         pCurrRectBand = pCurrRectBand->mpNextBand;
    2221                 :            : 
    2222                 :            :         // no band found? -> not further rectangles!
    2223         [ +  + ]:     173642 :         if( !pCurrRectBand )
    2224                 :     165225 :             return false;
    2225                 :            : 
    2226                 :            :         // get first separation in current band
    2227                 :       8417 :         pCurrRectBandSep = pCurrRectBand->mpFirstSep;
    2228                 :            :     }
    2229                 :            : 
    2230                 :            :     // get boundaries of current rectangle
    2231                 :      86958 :     rX      = pCurrRectBandSep->mnXLeft;
    2232                 :      86958 :     rY      = pCurrRectBand->mnYTop;
    2233                 :      86958 :     rWidth  = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
    2234                 :      86958 :     rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
    2235                 :            : 
    2236                 :            :     // save new pointers
    2237                 :      86958 :     rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
    2238                 :      86958 :     rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
    2239                 :            : 
    2240                 :     252183 :     return true;
    2241                 :            : }
    2242                 :            : 
    2243                 :            : // -----------------------------------------------------------------------
    2244                 :            : 
    2245                 :    2505436 : RegionType Region::GetType() const
    2246                 :            : {
    2247         [ +  + ]:    2505436 :     if ( mpImplRegion == &aImplEmptyRegion )
    2248                 :     264017 :         return REGION_EMPTY;
    2249         [ +  + ]:    2241419 :     else if ( mpImplRegion == &aImplNullRegion )
    2250                 :      15642 :         return REGION_NULL;
    2251         [ +  + ]:    2225777 :     else if ( mpImplRegion->mnRectCount == 1 )
    2252                 :    1934382 :         return REGION_RECTANGLE;
    2253                 :            :     else
    2254                 :    2505436 :         return REGION_COMPLEX;
    2255                 :            : }
    2256                 :            : 
    2257                 :            : // -----------------------------------------------------------------------
    2258                 :            : 
    2259                 :          0 : sal_Bool Region::IsInside( const Point& rPoint ) const
    2260                 :            : {
    2261                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2262                 :            : 
    2263                 :            :     // PolyPolygon data im Imp structure?
    2264                 :          0 :     ((Region*)this)->ImplPolyPolyRegionToBandRegion();
    2265                 :            : 
    2266                 :            :     // no instance data? -> not inside
    2267 [ #  # ][ #  # ]:          0 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2268                 :          0 :         return sal_False;
    2269                 :            : 
    2270                 :            :     // search band list
    2271                 :          0 :     ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
    2272         [ #  # ]:          0 :     while ( pBand )
    2273                 :            :     {
    2274                 :            :         // is point within band?
    2275   [ #  #  #  # ]:          0 :         if ( (pBand->mnYTop <= rPoint.Y()) &&
                 [ #  # ]
    2276                 :          0 :              (pBand->mnYBottom >= rPoint.Y()) )
    2277                 :            :         {
    2278                 :            :             // is point within separation of the band?
    2279         [ #  # ]:          0 :             if ( pBand->IsInside( rPoint.X() ) )
    2280                 :          0 :                 return sal_True;
    2281                 :            :             else
    2282                 :          0 :                 return sal_False;
    2283                 :            :         }
    2284                 :            : 
    2285                 :          0 :         pBand = pBand->mpNextBand;
    2286                 :            :     }
    2287                 :            : 
    2288                 :          0 :     return sal_False;
    2289                 :            : }
    2290                 :            : 
    2291                 :            : // -----------------------------------------------------------------------
    2292                 :            : 
    2293                 :          0 : sal_Bool Region::IsInside( const Rectangle& rRect ) const
    2294                 :            : {
    2295                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2296                 :            : 
    2297                 :            :     // is rectangle empty? -> not inside
    2298 [ #  # ][ #  # ]:          0 :     if ( rRect.IsEmpty() )
    2299                 :          0 :         return sal_False;
    2300                 :            : 
    2301                 :            :     // no instance data? -> not inside
    2302 [ #  # ][ #  # ]:          0 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2303                 :          0 :         return sal_False;
    2304                 :            : 
    2305                 :            :     // create region from rectangle and intersect own region
    2306         [ #  # ]:          0 :     Region aRegion = rRect;
    2307         [ #  # ]:          0 :     aRegion.Exclude( *this );
    2308                 :            : 
    2309                 :            :     // rectangle is inside if exclusion is empty
    2310 [ #  # ][ #  # ]:          0 :     return aRegion.IsEmpty();
    2311                 :            : }
    2312                 :            : 
    2313                 :            : // -----------------------------------------------------------------------
    2314                 :            : 
    2315                 :       9190 : sal_Bool Region::IsOver( const Rectangle& rRect ) const
    2316                 :            : {
    2317                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2318                 :            : 
    2319 [ +  + ][ -  + ]:       9190 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2320                 :       6900 :         return sal_False;
    2321                 :            : 
    2322                 :            :     // Can we optimize this ??? - is used in StarDraw for brushes pointers
    2323                 :            :     // Why we have no IsOver for Regions ???
    2324                 :            :     // create region from rectangle and intersect own region
    2325         [ +  - ]:       2290 :     Region aRegion = rRect;
    2326         [ +  - ]:       2290 :     aRegion.Intersect( *this );
    2327                 :            : 
    2328                 :            :     // rectangle is over if include is not empty
    2329 [ +  - ][ +  - ]:       9190 :     return !aRegion.IsEmpty();
    2330                 :            : }
    2331                 :            : 
    2332                 :            : // -----------------------------------------------------------------------
    2333                 :            : 
    2334                 :     337379 : void Region::SetNull()
    2335                 :            : {
    2336                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2337                 :            : 
    2338                 :            :     // statische Object haben RefCount von 0
    2339         [ +  + ]:     337379 :     if ( mpImplRegion->mnRefCount )
    2340                 :            :     {
    2341         [ +  + ]:       9989 :         if ( mpImplRegion->mnRefCount > 1 )
    2342                 :        366 :             mpImplRegion->mnRefCount--;
    2343                 :            :         else
    2344         [ +  - ]:       9623 :             delete mpImplRegion;
    2345                 :            :     }
    2346                 :            : 
    2347                 :            :     // set new type
    2348                 :     337379 :     mpImplRegion = (ImplRegion*)(&aImplNullRegion);
    2349                 :     337379 : }
    2350                 :            : 
    2351                 :            : // -----------------------------------------------------------------------
    2352                 :            : 
    2353                 :      89173 : void Region::SetEmpty()
    2354                 :            : {
    2355                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2356                 :            : 
    2357                 :            :     // statische Object haben RefCount von 0
    2358         [ +  + ]:      89173 :     if ( mpImplRegion->mnRefCount )
    2359                 :            :     {
    2360         [ +  + ]:      89000 :         if ( mpImplRegion->mnRefCount > 1 )
    2361                 :      88980 :             mpImplRegion->mnRefCount--;
    2362                 :            :         else
    2363         [ +  - ]:         20 :             delete mpImplRegion;
    2364                 :            :     }
    2365                 :            : 
    2366                 :            :     // set new type
    2367                 :      89173 :     mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    2368                 :      89173 : }
    2369                 :            : 
    2370                 :            : // -----------------------------------------------------------------------
    2371                 :            : 
    2372                 :    2279876 : Region& Region::operator=( const Region& rRegion )
    2373                 :            : {
    2374                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2375                 :            :     DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
    2376                 :            :     DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
    2377                 :            : 
    2378                 :            :     // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
    2379                 :            :     // RefCount == 0 fuer statische Objekte
    2380         [ +  + ]:    2279876 :     if ( rRegion.mpImplRegion->mnRefCount )
    2381                 :    1653340 :         rRegion.mpImplRegion->mnRefCount++;
    2382                 :            : 
    2383                 :            :     // statische Object haben RefCount von 0
    2384         [ +  + ]:    2279876 :     if ( mpImplRegion->mnRefCount )
    2385                 :            :     {
    2386         [ +  + ]:     816193 :         if ( mpImplRegion->mnRefCount > 1 )
    2387                 :     359913 :             mpImplRegion->mnRefCount--;
    2388                 :            :         else
    2389         [ +  - ]:     456280 :             delete mpImplRegion;
    2390                 :            :     }
    2391                 :            : 
    2392                 :    2279876 :     mpImplRegion = rRegion.mpImplRegion;
    2393                 :    2279876 :     return *this;
    2394                 :            : }
    2395                 :            : 
    2396                 :            : // -----------------------------------------------------------------------
    2397                 :            : 
    2398                 :     168109 : Region& Region::operator=( const Rectangle& rRect )
    2399                 :            : {
    2400                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2401                 :            : 
    2402                 :            :     // statische Object haben RefCount von 0
    2403         [ +  + ]:     168109 :     if ( mpImplRegion->mnRefCount )
    2404                 :            :     {
    2405         [ +  + ]:      90403 :         if ( mpImplRegion->mnRefCount > 1 )
    2406                 :      54934 :             mpImplRegion->mnRefCount--;
    2407                 :            :         else
    2408         [ +  - ]:      35469 :             delete mpImplRegion;
    2409                 :            :     }
    2410                 :            : 
    2411                 :     168109 :     ImplCreateRectRegion( rRect );
    2412                 :     168109 :     return *this;
    2413                 :            : }
    2414                 :            : 
    2415                 :            : // -----------------------------------------------------------------------
    2416                 :            : 
    2417                 :      34754 : sal_Bool Region::operator==( const Region& rRegion ) const
    2418                 :            : {
    2419                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2420                 :            :     DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
    2421                 :            : 
    2422                 :            :     // reference to same object? -> equal!
    2423         [ -  + ]:      34754 :     if ( mpImplRegion == rRegion.mpImplRegion )
    2424                 :          0 :         return sal_True;
    2425                 :            : 
    2426 [ +  - ][ -  + ]:      34754 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2427                 :          0 :         return sal_False;
    2428                 :            : 
    2429 [ +  - ][ -  + ]:      34754 :     if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
    2430                 :          0 :         return sal_False;
    2431                 :            : 
    2432 [ -  + ][ #  # ]:      34754 :     if ( rRegion.mpImplRegion->mpPolyPoly && mpImplRegion->mpPolyPoly )
    2433                 :          0 :         return *rRegion.mpImplRegion->mpPolyPoly == *mpImplRegion->mpPolyPoly;
    2434                 :            :     else
    2435                 :            :     {
    2436                 :      34754 :         ((Region*)this)->ImplPolyPolyRegionToBandRegion();
    2437                 :      34754 :         ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
    2438                 :            : 
    2439                 :            :         // Eine der beiden Regions kann jetzt Empty sein
    2440         [ -  + ]:      34754 :         if ( mpImplRegion == rRegion.mpImplRegion )
    2441                 :          0 :             return sal_True;
    2442                 :            : 
    2443         [ -  + ]:      34754 :         if ( mpImplRegion == &aImplEmptyRegion )
    2444                 :          0 :             return sal_False;
    2445                 :            : 
    2446         [ -  + ]:      34754 :         if ( rRegion.mpImplRegion == &aImplEmptyRegion )
    2447                 :          0 :             return sal_False;
    2448                 :            :     }
    2449                 :            : 
    2450                 :            :     // initialise pointers
    2451                 :      34754 :     ImplRegionBand*      pOwnRectBand = mpImplRegion->mpFirstBand;
    2452                 :      34754 :     ImplRegionBandSep*   pOwnRectBandSep = pOwnRectBand->mpFirstSep;
    2453                 :      34754 :     ImplRegionBand*      pSecondRectBand = rRegion.mpImplRegion->mpFirstBand;
    2454                 :      34754 :     ImplRegionBandSep*   pSecondRectBandSep = pSecondRectBand->mpFirstSep;
    2455 [ +  + ][ +  - ]:      35696 :     while ( pOwnRectBandSep && pSecondRectBandSep )
                 [ +  + ]
    2456                 :            :     {
    2457                 :            :         // get boundaries of current rectangle
    2458                 :      34754 :         long nOwnXLeft = pOwnRectBandSep->mnXLeft;
    2459                 :      34754 :         long nSecondXLeft = pSecondRectBandSep->mnXLeft;
    2460         [ +  + ]:      34754 :         if ( nOwnXLeft != nSecondXLeft )
    2461                 :      22962 :             return sal_False;
    2462                 :            : 
    2463                 :      11792 :         long nOwnYTop = pOwnRectBand->mnYTop;
    2464                 :      11792 :         long nSecondYTop = pSecondRectBand->mnYTop;
    2465         [ +  + ]:      11792 :         if ( nOwnYTop != nSecondYTop )
    2466                 :       5764 :             return sal_False;
    2467                 :            : 
    2468                 :       6028 :         long nOwnXRight = pOwnRectBandSep->mnXRight;
    2469                 :       6028 :         long nSecondXRight = pSecondRectBandSep->mnXRight;
    2470         [ +  + ]:       6028 :         if ( nOwnXRight != nSecondXRight )
    2471                 :       1204 :             return sal_False;
    2472                 :            : 
    2473                 :       4824 :         long nOwnYBottom = pOwnRectBand->mnYBottom;
    2474                 :       4824 :         long nSecondYBottom = pSecondRectBand->mnYBottom;
    2475         [ +  + ]:       4824 :         if ( nOwnYBottom != nSecondYBottom )
    2476                 :       3882 :             return sal_False;
    2477                 :            : 
    2478                 :            :         // get next separation from current band
    2479                 :        942 :         pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
    2480                 :            : 
    2481                 :            :         // no separation found? -> go to next band!
    2482         [ +  - ]:        942 :         if ( !pOwnRectBandSep )
    2483                 :            :         {
    2484                 :            :             // get next band
    2485                 :        942 :             pOwnRectBand = pOwnRectBand->mpNextBand;
    2486                 :            : 
    2487                 :            :             // get first separation in current band
    2488         [ -  + ]:        942 :             if( pOwnRectBand )
    2489                 :          0 :                 pOwnRectBandSep = pOwnRectBand->mpFirstSep;
    2490                 :            :         }
    2491                 :            : 
    2492                 :            :         // get next separation from current band
    2493                 :        942 :         pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
    2494                 :            : 
    2495                 :            :         // no separation found? -> go to next band!
    2496         [ +  - ]:        942 :         if ( !pSecondRectBandSep )
    2497                 :            :         {
    2498                 :            :             // get next band
    2499                 :        942 :             pSecondRectBand = pSecondRectBand->mpNextBand;
    2500                 :            : 
    2501                 :            :             // get first separation in current band
    2502         [ -  + ]:        942 :             if( pSecondRectBand )
    2503                 :          0 :                 pSecondRectBandSep = pSecondRectBand->mpFirstSep;
    2504                 :            :         }
    2505                 :            : 
    2506 [ -  + ][ #  # ]:        942 :         if ( pOwnRectBandSep && !pSecondRectBandSep )
    2507                 :          0 :             return sal_False;
    2508                 :            : 
    2509 [ +  - ][ -  + ]:        942 :         if ( !pOwnRectBandSep && pSecondRectBandSep )
    2510                 :          0 :             return sal_False;
    2511                 :            :     }
    2512                 :            : 
    2513                 :      34754 :     return sal_True;
    2514                 :            : }
    2515                 :            : 
    2516                 :            : // -----------------------------------------------------------------------
    2517                 :            : 
    2518                 :            : enum StreamEntryType { STREAMENTRY_BANDHEADER, STREAMENTRY_SEPARATION, STREAMENTRY_END };
    2519                 :            : 
    2520                 :        178 : SvStream& operator>>( SvStream& rIStrm, Region& rRegion )
    2521                 :            : {
    2522                 :            :     DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
    2523                 :            : 
    2524         [ +  - ]:        178 :     VersionCompat   aCompat( rIStrm, STREAM_READ );
    2525                 :            :     sal_uInt16          nVersion;
    2526                 :            :     sal_uInt16          nTmp16;
    2527                 :            : 
    2528                 :            :     // statische Object haben RefCount von 0
    2529         [ -  + ]:        178 :     if ( rRegion.mpImplRegion->mnRefCount )
    2530                 :            :     {
    2531         [ #  # ]:          0 :         if ( rRegion.mpImplRegion->mnRefCount > 1 )
    2532                 :          0 :             rRegion.mpImplRegion->mnRefCount--;
    2533                 :            :         else
    2534 [ #  # ][ #  # ]:          0 :             delete rRegion.mpImplRegion;
    2535                 :            :     }
    2536                 :            : 
    2537                 :            :     // get version of streamed region
    2538         [ +  - ]:        178 :     rIStrm >> nVersion;
    2539                 :            : 
    2540                 :            :     // get type of region
    2541         [ +  - ]:        178 :     rIStrm >> nTmp16;
    2542                 :            : 
    2543                 :        178 :     RegionType meStreamedType = (RegionType)nTmp16;
    2544                 :            : 
    2545      [ -  -  + ]:        178 :     switch( meStreamedType )
    2546                 :            :     {
    2547                 :            :         case REGION_NULL:
    2548                 :          0 :             rRegion.mpImplRegion = (ImplRegion*)&aImplNullRegion;
    2549                 :          0 :         break;
    2550                 :            : 
    2551                 :            :         case REGION_EMPTY:
    2552                 :          0 :             rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
    2553                 :          0 :         break;
    2554                 :            : 
    2555                 :            :         default:
    2556                 :            :         {
    2557                 :            :             // create instance of implementation class
    2558 [ +  - ][ +  - ]:        178 :             rRegion.mpImplRegion = new ImplRegion();
    2559                 :            : 
    2560                 :            :             // get header from first element
    2561         [ +  - ]:        178 :             rIStrm >> nTmp16;
    2562                 :            : 
    2563                 :            :             // get all bands
    2564                 :        178 :             rRegion.mpImplRegion->mnRectCount = 0;
    2565                 :        178 :             ImplRegionBand* pCurrBand = NULL;
    2566         [ +  + ]:        534 :             while ( (StreamEntryType)nTmp16 != STREAMENTRY_END )
    2567                 :            :             {
    2568                 :            :                 // insert new band or new separation?
    2569         [ +  + ]:        356 :                 if ( (StreamEntryType)nTmp16 == STREAMENTRY_BANDHEADER )
    2570                 :            :                 {
    2571                 :            :                     //#fdo39428 SvStream no longer supports operator>>(long&)
    2572                 :            :                     sal_Int32 nYTop;
    2573                 :            :                     sal_Int32 nYBottom;
    2574                 :            : 
    2575         [ +  - ]:        178 :                     rIStrm >> nYTop;
    2576         [ +  - ]:        178 :                     rIStrm >> nYBottom;
    2577                 :            : 
    2578                 :            :                     // create band
    2579 [ +  - ][ +  - ]:        178 :                     ImplRegionBand* pNewBand = new ImplRegionBand( nYTop, nYBottom );
    2580                 :            : 
    2581                 :            :                     // first element? -> set as first into the list
    2582         [ +  - ]:        178 :                     if ( !pCurrBand )
    2583                 :        178 :                         rRegion.mpImplRegion->mpFirstBand = pNewBand;
    2584                 :            :                     else
    2585                 :          0 :                         pCurrBand->mpNextBand = pNewBand;
    2586                 :            : 
    2587                 :            :                     // save pointer for next creation
    2588                 :        178 :                     pCurrBand = pNewBand;
    2589                 :            :                 }
    2590                 :            :                 else
    2591                 :            :                 {
    2592                 :            :                     //#fdo39428 SvStream no longer supports operator>>(long&)
    2593                 :            :                     sal_Int32 nXLeft;
    2594                 :            :                     sal_Int32 nXRight;
    2595                 :            : 
    2596         [ +  - ]:        178 :                     rIStrm >> nXLeft;
    2597         [ +  - ]:        178 :                     rIStrm >> nXRight;
    2598                 :            : 
    2599                 :            :                     // add separation
    2600         [ +  - ]:        178 :                     if ( pCurrBand )
    2601                 :            :                     {
    2602         [ +  - ]:        178 :                         pCurrBand->Union( nXLeft, nXRight );
    2603                 :        178 :                         rRegion.mpImplRegion->mnRectCount++;
    2604                 :            :                     }
    2605                 :            :                 }
    2606                 :            : 
    2607         [ -  + ]:        356 :                 if( rIStrm.IsEof() )
    2608                 :            :                 {
    2609                 :            :                     OSL_FAIL( "premature end of region stream" );
    2610 [ #  # ][ #  # ]:          0 :                     delete rRegion.mpImplRegion;
    2611                 :          0 :                     rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
    2612                 :          0 :                     return rIStrm;
    2613                 :            :                 }
    2614                 :            : 
    2615                 :            :                 // get next header
    2616         [ +  - ]:        356 :                 rIStrm >> nTmp16;
    2617                 :            :             }
    2618                 :            : 
    2619         [ +  - ]:        178 :             if( aCompat.GetVersion() >= 2 )
    2620                 :            :             {
    2621                 :            :                 sal_Bool bHasPolyPolygon;
    2622                 :            : 
    2623         [ +  - ]:        178 :                 rIStrm >> bHasPolyPolygon;
    2624                 :            : 
    2625         [ -  + ]:        178 :                 if( bHasPolyPolygon )
    2626                 :            :                 {
    2627 [ #  # ][ #  # ]:          0 :                     delete rRegion.mpImplRegion->mpPolyPoly;
    2628 [ #  # ][ #  # ]:          0 :                     rRegion.mpImplRegion->mpPolyPoly = new PolyPolygon;
    2629         [ #  # ]:        178 :                     rIStrm >> *( rRegion.mpImplRegion->mpPolyPoly );
    2630                 :            :                 }
    2631                 :            :             }
    2632                 :            :         }
    2633                 :        178 :         break;
    2634                 :            :     }
    2635                 :            : 
    2636         [ +  - ]:        178 :     return rIStrm;
    2637                 :            : }
    2638                 :            : 
    2639                 :            : // -----------------------------------------------------------------------
    2640                 :            : 
    2641                 :        438 : SvStream& operator<<( SvStream& rOStrm, const Region& rRegion )
    2642                 :            : {
    2643                 :            :     DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
    2644                 :            : 
    2645                 :        438 :     sal_uInt16          nVersion = 2;
    2646         [ +  - ]:        438 :     VersionCompat   aCompat( rOStrm, STREAM_WRITE, nVersion );
    2647         [ +  - ]:        438 :     Region          aTmpRegion( rRegion );
    2648                 :            : 
    2649                 :            :     // use tmp region to avoid destruction of internal region (polypolygon) of rRegion
    2650         [ +  - ]:        438 :     aTmpRegion.ImplPolyPolyRegionToBandRegion();
    2651                 :            : 
    2652                 :            :     // put version
    2653         [ +  - ]:        438 :     rOStrm << nVersion;
    2654                 :            : 
    2655                 :            :     // put type
    2656 [ +  - ][ +  - ]:        438 :     rOStrm << (sal_uInt16)aTmpRegion.GetType();
    2657                 :            : 
    2658                 :            :     // put all bands if not null or empty
    2659 [ +  - ][ +  - ]:        438 :     if ( (aTmpRegion.mpImplRegion != &aImplEmptyRegion) && (aTmpRegion.mpImplRegion != &aImplNullRegion) )
    2660                 :            :     {
    2661                 :        438 :         ImplRegionBand* pBand = aTmpRegion.mpImplRegion->mpFirstBand;
    2662         [ +  + ]:        876 :         while ( pBand )
    2663                 :            :         {
    2664                 :            :             // put boundaries
    2665                 :            :             //#fdo39428 SvStream no longer supports operator<<(long)
    2666         [ +  - ]:        438 :             rOStrm << (sal_uInt16) STREAMENTRY_BANDHEADER;
    2667         [ +  - ]:        438 :             rOStrm << sal::static_int_cast<sal_Int32>(pBand->mnYTop);
    2668         [ +  - ]:        438 :             rOStrm << sal::static_int_cast<sal_Int32>(pBand->mnYBottom);
    2669                 :            : 
    2670                 :            :             // put separations of current band
    2671                 :        438 :             ImplRegionBandSep* pSep = pBand->mpFirstSep;
    2672         [ +  + ]:        876 :             while ( pSep )
    2673                 :            :             {
    2674                 :            :                 // put separation
    2675                 :            :                 //#fdo39428 SvStream no longer supports operator<<(long)
    2676         [ +  - ]:        438 :                 rOStrm << (sal_uInt16) STREAMENTRY_SEPARATION;
    2677         [ +  - ]:        438 :                 rOStrm << sal::static_int_cast<sal_Int32>(pSep->mnXLeft);
    2678         [ +  - ]:        438 :                 rOStrm << sal::static_int_cast<sal_Int32>(pSep->mnXRight);
    2679                 :            : 
    2680                 :            :                 // next separation from current band
    2681                 :        438 :                 pSep = pSep->mpNextSep;
    2682                 :            :             }
    2683                 :            : 
    2684                 :        438 :             pBand = pBand->mpNextBand;
    2685                 :            :         }
    2686                 :            : 
    2687                 :            :         // put endmarker
    2688         [ +  - ]:        438 :         rOStrm << (sal_uInt16) STREAMENTRY_END;
    2689                 :            : 
    2690                 :            :         // write polypolygon if available
    2691         [ +  - ]:        438 :         const sal_Bool bHasPolyPolygon = rRegion.HasPolyPolygon();
    2692         [ +  - ]:        438 :         rOStrm << bHasPolyPolygon;
    2693                 :            : 
    2694         [ -  + ]:        438 :         if( bHasPolyPolygon )
    2695                 :            :         {
    2696                 :            :             // #i105373#
    2697         [ #  # ]:          0 :             PolyPolygon aNoCurvePolyPolygon;
    2698 [ #  # ][ #  # ]:          0 :             rRegion.GetPolyPolygon().AdaptiveSubdivide(aNoCurvePolyPolygon);
                 [ #  # ]
    2699                 :            : 
    2700 [ #  # ][ #  # ]:          0 :             rOStrm << aNoCurvePolyPolygon;
    2701                 :            :         }
    2702                 :            :     }
    2703                 :            : 
    2704 [ +  - ][ +  - ]:        438 :     return rOStrm;
    2705                 :            : }
    2706                 :            : 
    2707                 :            : // -----------------------------------------------------------------------
    2708                 :            : 
    2709                 :     139271 : void Region::ImplBeginAddRect()
    2710                 :            : {
    2711                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2712                 :            : 
    2713                 :            :     // statische Object haben RefCount von 0
    2714         [ -  + ]:     139271 :     if ( mpImplRegion->mnRefCount )
    2715                 :            :     {
    2716         [ #  # ]:          0 :         if ( mpImplRegion->mnRefCount > 1 )
    2717                 :          0 :             mpImplRegion->mnRefCount--;
    2718                 :            :         else
    2719         [ #  # ]:          0 :             delete mpImplRegion;
    2720                 :            :     }
    2721                 :            : 
    2722                 :            :     // create fresh region
    2723         [ +  - ]:     139271 :     mpImplRegion = new ImplRegion();
    2724                 :     139271 : }
    2725                 :            : 
    2726                 :            : // -----------------------------------------------------------------------
    2727                 :            : 
    2728                 :     144383 : sal_Bool Region::ImplAddRect( const Rectangle& rRect )
    2729                 :            : {
    2730                 :            :     // Hier kein CheckThis, da nicht alle Daten auf Stand
    2731                 :            : 
    2732         [ -  + ]:     144383 :     if ( rRect.IsEmpty() )
    2733                 :          0 :         return sal_True;
    2734                 :            : 
    2735                 :            :     // get justified rectangle
    2736                 :            :     long nTop;
    2737                 :            :     long nBottom;
    2738                 :            :     long nLeft;
    2739                 :            :     long nRight;
    2740         [ +  - ]:     144383 :     if ( rRect.Top() <= rRect.Bottom() )
    2741                 :            :     {
    2742                 :     144383 :         nTop = rRect.Top();
    2743                 :     144383 :         nBottom = rRect.Bottom();
    2744                 :            :     }
    2745                 :            :     else
    2746                 :            :     {
    2747                 :          0 :         nTop = rRect.Bottom();
    2748                 :          0 :         nBottom = rRect.Top();
    2749                 :            :     }
    2750         [ +  - ]:     144383 :     if ( rRect.Left() <= rRect.Right() )
    2751                 :            :     {
    2752                 :     144383 :         nLeft = rRect.Left();
    2753                 :     144383 :         nRight = rRect.Right();
    2754                 :            :     }
    2755                 :            :     else
    2756                 :            :     {
    2757                 :          0 :         nLeft = rRect.Right();
    2758                 :          0 :         nRight = rRect.Left();
    2759                 :            :     }
    2760                 :            : 
    2761         [ +  + ]:     144383 :     if ( !mpImplRegion->mpLastCheckedBand )
    2762                 :            :     {
    2763                 :            :         // create new band
    2764         [ +  - ]:     139271 :         mpImplRegion->mpLastCheckedBand = new ImplRegionBand( nTop, nBottom );
    2765                 :            : 
    2766                 :            :         // set band as current
    2767                 :     139271 :         mpImplRegion->mpFirstBand = mpImplRegion->mpLastCheckedBand;
    2768                 :     139271 :         mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
    2769                 :            :     }
    2770                 :            :     else
    2771                 :            :     {
    2772                 :            :         DBG_ASSERT( nTop >= mpImplRegion->mpLastCheckedBand->mnYTop,
    2773                 :            :                     "Region::ImplAddRect() - nTopY < nLastTopY" );
    2774                 :            : 
    2775                 :            :         // new band? create it!
    2776 [ +  + ][ -  + ]:       5112 :         if ( (nTop != mpImplRegion->mpLastCheckedBand->mnYTop) ||
    2777                 :            :              (nBottom != mpImplRegion->mpLastCheckedBand->mnYBottom) )
    2778                 :            :         {
    2779                 :            :             // create new band
    2780         [ +  - ]:       4307 :             ImplRegionBand* pNewRegionBand = new ImplRegionBand( nTop, nBottom );
    2781                 :            : 
    2782                 :            :             // append band to the end
    2783                 :       4307 :             mpImplRegion->mpLastCheckedBand->mpNextBand = pNewRegionBand;
    2784                 :            : 
    2785                 :            :             // skip to the new band
    2786                 :       4307 :             mpImplRegion->mpLastCheckedBand = mpImplRegion->mpLastCheckedBand->mpNextBand;
    2787                 :            :         }
    2788                 :            : 
    2789                 :            :         // Insert Sep
    2790                 :       5112 :         mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
    2791                 :            :     }
    2792                 :            : 
    2793                 :     144383 :     return sal_True;
    2794                 :            : }
    2795                 :            : 
    2796                 :            : // -----------------------------------------------------------------------
    2797                 :            : 
    2798                 :     139271 : void Region::ImplEndAddRect()
    2799                 :            : {
    2800                 :            :     // check if we are empty
    2801         [ -  + ]:     139271 :     if ( !mpImplRegion->mpFirstBand )
    2802                 :            :     {
    2803         [ #  # ]:          0 :         delete mpImplRegion;
    2804                 :          0 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    2805                 :          0 :         return;
    2806                 :            :     }
    2807                 :            : 
    2808                 :            :     // check if we have somthing to optimize
    2809         [ +  + ]:     139271 :     if ( !mpImplRegion->mpFirstBand->mpNextBand )
    2810                 :            :     {
    2811                 :            :         // update mpImplRegion->mnRectCount, because no OptimizeBandList is called
    2812                 :     136017 :         ImplRegionBandSep* pSep = mpImplRegion->mpFirstBand->mpFirstSep;
    2813                 :     136017 :         mpImplRegion->mnRectCount = 0;
    2814         [ +  + ]:     272072 :         while( pSep )
    2815                 :            :         {
    2816                 :     136055 :             mpImplRegion->mnRectCount++;
    2817                 :     136055 :             pSep = pSep->mpNextSep;
    2818                 :            :         }
    2819                 :            : 
    2820                 :            :         // Erst hier testen, da hier die Daten wieder stimmen
    2821                 :            :         DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2822                 :     136017 :         return;
    2823                 :            :     }
    2824                 :            : 
    2825                 :            :     // have to revert list? -> do it now!
    2826         [ -  + ]:       3254 :     if ( mpImplRegion->mpFirstBand->mnYTop >
    2827                 :            :          mpImplRegion->mpFirstBand->mpNextBand->mnYTop )
    2828                 :            :     {
    2829                 :            :         ImplRegionBand * pNewFirstRegionBand;
    2830                 :            : 
    2831                 :            :         // initialize temp list with first element
    2832                 :          0 :         pNewFirstRegionBand = mpImplRegion->mpFirstBand;
    2833                 :          0 :         mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
    2834                 :          0 :         pNewFirstRegionBand->mpNextBand = NULL;
    2835                 :            : 
    2836                 :            :         // insert elements to the temp list
    2837         [ #  # ]:          0 :         while ( mpImplRegion->mpFirstBand )
    2838                 :            :         {
    2839                 :          0 :             ImplRegionBand * pSavedRegionBand = pNewFirstRegionBand;
    2840                 :          0 :             pNewFirstRegionBand = mpImplRegion->mpFirstBand;
    2841                 :          0 :             mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
    2842                 :          0 :             pNewFirstRegionBand->mpNextBand = pSavedRegionBand;
    2843                 :            :         }
    2844                 :            : 
    2845                 :            :         // set temp list as new list
    2846                 :          0 :         mpImplRegion->mpFirstBand = pNewFirstRegionBand;
    2847                 :            :     }
    2848                 :            : 
    2849                 :            :     // cleanup
    2850         [ -  + ]:       3254 :     if ( !mpImplRegion->OptimizeBandList() )
    2851                 :            :     {
    2852         [ #  # ]:          0 :         delete mpImplRegion;
    2853                 :     139271 :         mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
    2854                 :            :     }
    2855                 :            : 
    2856                 :            :     // Erst hier testen, da hier die Daten wieder stimmen
    2857                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2858                 :            : }
    2859                 :            : 
    2860                 :            : // -----------------------------------------------------------------------
    2861                 :            : 
    2862                 :     427801 : sal_uLong Region::GetRectCount() const
    2863                 :            : {
    2864                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2865                 :            : 
    2866                 :     427801 :     ((Region*)this)->ImplPolyPolyRegionToBandRegion();
    2867                 :            : 
    2868                 :            : #ifdef DBG_UTIL
    2869                 :            :     sal_uLong nCount = 0;
    2870                 :            : 
    2871                 :            :     // all bands if not null or empty
    2872                 :            :     if ( (mpImplRegion != &aImplEmptyRegion) && (mpImplRegion != &aImplNullRegion) )
    2873                 :            :     {
    2874                 :            :         ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
    2875                 :            :         while ( pBand )
    2876                 :            :         {
    2877                 :            :             ImplRegionBandSep* pSep = pBand->mpFirstSep;
    2878                 :            :             while( pSep )
    2879                 :            :             {
    2880                 :            :                 nCount++;
    2881                 :            :                 pSep = pSep->mpNextSep;
    2882                 :            :             }
    2883                 :            : 
    2884                 :            :             pBand = pBand->mpNextBand;
    2885                 :            :         }
    2886                 :            :     }
    2887                 :            : 
    2888                 :            :     DBG_ASSERT( mpImplRegion->mnRectCount == nCount, "Region: invalid mnRectCount!" );
    2889                 :            : #endif
    2890                 :            : 
    2891                 :     427801 :     return mpImplRegion->mnRectCount;
    2892                 :            : }
    2893                 :            : 
    2894                 :            : // -----------------------------------------------------------------------
    2895                 :            : 
    2896                 :      96609 : RegionHandle Region::BeginEnumRects()
    2897                 :            : {
    2898                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2899                 :            : 
    2900                 :      96609 :     ImplPolyPolyRegionToBandRegion();
    2901                 :            : 
    2902                 :            :     // no internal data? -> region is empty!
    2903 [ -  + ][ +  - ]:      96609 :     if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
    2904                 :          0 :         return 0;
    2905                 :            : 
    2906                 :            :     // no band in the list? -> region is empty!
    2907         [ -  + ]:      96609 :     if ( mpImplRegion->mpFirstBand == NULL )
    2908                 :            :     {
    2909                 :            :         DBG_ASSERT( mpImplRegion->mpFirstBand, "Region::BeginEnumRects() First Band is Empty!" );
    2910                 :          0 :         return 0;
    2911                 :            :     }
    2912                 :            : 
    2913                 :      96609 :     ImplRegionHandle* pData = new ImplRegionHandle;
    2914         [ +  - ]:      96609 :     pData->mpRegion = new Region( *this );
    2915                 :      96609 :     pData->mbFirst  = sal_True;
    2916                 :            : 
    2917                 :            :     // save pointers
    2918                 :      96609 :     pData->mpCurrRectBand = pData->mpRegion->mpImplRegion->mpFirstBand;
    2919                 :      96609 :     pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
    2920                 :            : 
    2921                 :      96609 :     return (RegionHandle)pData;
    2922                 :            : }
    2923                 :            : 
    2924                 :            : // -----------------------------------------------------------------------
    2925                 :            : 
    2926                 :     405262 : sal_Bool Region::GetEnumRects( RegionHandle pVoidData, Rectangle& rRect )
    2927                 :            : {
    2928                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2929                 :            : 
    2930                 :     405262 :     ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
    2931         [ -  + ]:     405262 :     if ( !pData )
    2932                 :          0 :         return sal_False;
    2933                 :            : 
    2934         [ +  + ]:     405262 :     if ( pData->mbFirst )
    2935                 :      96609 :         pData->mbFirst = sal_False;
    2936                 :            :     else
    2937                 :            :     {
    2938                 :            :         // get next separation from current band
    2939                 :     308653 :         pData->mpCurrRectBandSep = pData->mpCurrRectBandSep->mpNextSep;
    2940                 :            : 
    2941                 :            :         // no separation found? -> go to next band!
    2942         [ +  + ]:     308653 :         if ( !pData->mpCurrRectBandSep )
    2943                 :            :         {
    2944                 :            :             // get next band
    2945                 :     105372 :             pData->mpCurrRectBand = pData->mpCurrRectBand->mpNextBand;
    2946                 :            : 
    2947                 :            :             // no band found? -> not further rectangles!
    2948         [ +  + ]:     105372 :             if ( !pData->mpCurrRectBand )
    2949                 :      96609 :                 return sal_False;
    2950                 :            : 
    2951                 :            :             // get first separation in current band
    2952                 :       8763 :             pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
    2953                 :            :         }
    2954                 :            :     }
    2955                 :            : 
    2956                 :            :     // get boundaries of current rectangle
    2957                 :     308653 :     rRect.Top()     = pData->mpCurrRectBand->mnYTop;
    2958                 :     308653 :     rRect.Bottom()  = pData->mpCurrRectBand->mnYBottom;
    2959                 :     308653 :     rRect.Left()    = pData->mpCurrRectBandSep->mnXLeft;
    2960                 :     308653 :     rRect.Right()   = pData->mpCurrRectBandSep->mnXRight;
    2961                 :     405262 :     return sal_True;
    2962                 :            : }
    2963                 :            : 
    2964                 :            : // -----------------------------------------------------------------------
    2965                 :            : 
    2966                 :      96609 : void Region::EndEnumRects( RegionHandle pVoidData )
    2967                 :            : {
    2968                 :            :     DBG_CHKTHIS( Region, ImplDbgTestRegion );
    2969                 :            : 
    2970                 :      96609 :     ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
    2971         [ -  + ]:      96609 :     if ( !pData )
    2972                 :      96609 :         return;
    2973                 :            : 
    2974                 :            :     // cleanup
    2975         [ +  - ]:      96609 :     delete pData->mpRegion;
    2976                 :      96609 :     delete pData;
    2977                 :            : }
    2978                 :            : 
    2979                 :            : // -----------------------------------------------------------------------
    2980                 :            : 
    2981                 :          0 : static inline bool ImplPolygonRectTest( const Polygon& rPoly, Rectangle* pRectOut = NULL )
    2982                 :            : {
    2983                 :          0 :     bool bIsRect = false;
    2984                 :          0 :     const Point* pPoints = rPoly.GetConstPointAry();
    2985                 :          0 :     sal_uInt16 nPoints = rPoly.GetSize();
    2986 [ #  # ][ #  # ]:          0 :     if( nPoints == 4 || (nPoints == 5 && pPoints[0] == pPoints[4]) )
         [ #  # ][ #  # ]
    2987                 :            :     {
    2988                 :          0 :         long nX1 = pPoints[0].X(), nX2 = pPoints[2].X(),
    2989                 :          0 :         nY1 = pPoints[0].Y(), nY2 = pPoints[2].Y();
    2990   [ #  #  #  #  :          0 :         if( ( (pPoints[1].X() == nX1 && pPoints[3].X() == nX2) &&
          #  #  #  #  #  
             #  #  #  #  
              # ][ #  # ]
                 [ #  # ]
    2991                 :          0 :             (pPoints[1].Y() == nY2 && pPoints[3].Y() == nY1) )
    2992                 :            :         ||
    2993                 :          0 :         ( (pPoints[1].X() == nX2 && pPoints[3].X() == nX1) &&
    2994                 :          0 :         (pPoints[1].Y() == nY1 && pPoints[3].Y() == nY2) ) )
    2995                 :            :         {
    2996                 :          0 :             bIsRect = true;
    2997         [ #  # ]:          0 :             if( pRectOut )
    2998                 :            :             {
    2999                 :            :                 long nSwap;
    3000         [ #  # ]:          0 :                 if( nX2 < nX1 )
    3001                 :            :                 {
    3002                 :          0 :                     nSwap = nX2;
    3003                 :          0 :                     nX2 = nX1;
    3004                 :          0 :                     nX1 = nSwap;
    3005                 :            :                 }
    3006         [ #  # ]:          0 :                 if( nY2 < nY1 )
    3007                 :            :                 {
    3008                 :          0 :                     nSwap = nY2;
    3009                 :          0 :                     nY2 = nY1;
    3010                 :          0 :                     nY1 = nSwap;
    3011                 :            :                 }
    3012         [ #  # ]:          0 :                 if( nX2 != nX1 )
    3013                 :          0 :                     nX2--;
    3014         [ #  # ]:          0 :                 if( nY2 != nY1 )
    3015                 :          0 :                     nY2--;
    3016                 :          0 :                 pRectOut->Left()    = nX1;
    3017                 :          0 :                 pRectOut->Right()   = nX2;
    3018                 :          0 :                 pRectOut->Top()     = nY1;
    3019                 :          0 :                 pRectOut->Bottom()  = nY2;
    3020                 :            :             }
    3021                 :            :         }
    3022                 :            :     }
    3023                 :          0 :     return bIsRect;
    3024                 :            : }
    3025                 :            : 
    3026                 :          0 : Region Region::GetRegionFromPolyPolygon( const PolyPolygon& rPolyPoly )
    3027                 :            : {
    3028                 :            :     //return Region( rPolyPoly );
    3029                 :            : 
    3030                 :            :     // check if it's worth extracting the XOr'ing the Rectangles
    3031                 :            :     // empiricism shows that break even between XOr'ing rectangles separately
    3032                 :            :     // and ImplPolyPolyRegionToBandRegion is at half rectangles/half polygons
    3033                 :          0 :     int nPolygonRects = 0, nPolygonPolygons = 0;
    3034         [ #  # ]:          0 :     int nPolygons = rPolyPoly.Count();
    3035                 :            : 
    3036         [ #  # ]:          0 :     for( sal_uInt16 i = 0; i < nPolygons; i++ )
    3037                 :            :     {
    3038         [ #  # ]:          0 :         const Polygon& rPoly = rPolyPoly[i];
    3039 [ #  # ][ #  # ]:          0 :         if( ImplPolygonRectTest( rPoly ) )
    3040                 :          0 :             nPolygonRects++;
    3041                 :            :         else
    3042                 :          0 :             nPolygonPolygons++;
    3043                 :            :     }
    3044         [ #  # ]:          0 :     if( nPolygonPolygons > nPolygonRects )
    3045         [ #  # ]:          0 :         return Region( rPolyPoly );
    3046                 :            : 
    3047         [ #  # ]:          0 :     Region aResult;
    3048         [ #  # ]:          0 :     Rectangle aRect;
    3049         [ #  # ]:          0 :     for( sal_uInt16 i = 0; i < nPolygons; i++ )
    3050                 :            :     {
    3051         [ #  # ]:          0 :         const Polygon& rPoly = rPolyPoly[i];
    3052 [ #  # ][ #  # ]:          0 :         if( ImplPolygonRectTest( rPoly, &aRect ) )
    3053         [ #  # ]:          0 :             aResult.XOr( aRect );
    3054                 :            :         else
    3055 [ #  # ][ #  # ]:          0 :             aResult.XOr( Region(rPoly) );
                 [ #  # ]
    3056                 :            :     }
    3057 [ #  # ][ #  # ]:          0 :     return aResult;
    3058 [ +  - ][ +  - ]:       1041 : }
    3059                 :            : 
    3060                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10