LCOV - code coverage report
Current view: top level - vcl/source/gdi - region.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 436 723 60.3 %
Date: 2015-06-13 12:38:46 Functions: 36 44 81.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <limits.h>
      21             : #include <tools/vcompat.hxx>
      22             : #include <tools/stream.hxx>
      23             : #include <tools/helpers.hxx>
      24             : #include <osl/diagnose.h>
      25             : #include <vcl/region.hxx>
      26             : #include <regionband.hxx>
      27             : 
      28             : #include <basegfx/matrix/b2dhommatrix.hxx>
      29             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      30             : #include <basegfx/polygon/b2dpolygontools.hxx>
      31             : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      32             : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
      33             : #include <basegfx/range/b2drange.hxx>
      34             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      35             : 
      36             : namespace
      37             : {
      38             :     /** Return <TRUE/> when the given polygon is rectiliner and oriented so that
      39             :         all sides are either horizontal or vertical.
      40             :     */
      41          25 :     bool ImplIsPolygonRectilinear (const tools::PolyPolygon& rPolyPoly)
      42             :     {
      43             :         // Iterate over all polygons.
      44          25 :         const sal_uInt16 nPolyCount = rPolyPoly.Count();
      45          52 :         for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
      46             :         {
      47          29 :             const Polygon&  aPoly = rPolyPoly.GetObject(nPoly);
      48             : 
      49             :             // Iterate over all edges of the current polygon.
      50          29 :             const sal_uInt16 nSize = aPoly.GetSize();
      51             : 
      52          29 :             if (nSize < 2)
      53           0 :                 continue;
      54          29 :             Point aPoint (aPoly.GetPoint(0));
      55          29 :             const Point aLastPoint (aPoint);
      56         137 :             for (sal_uInt16 nPoint = 1; nPoint < nSize; ++nPoint)
      57             :             {
      58         110 :                 const Point aNextPoint (aPoly.GetPoint(nPoint));
      59             :                 // When there is at least one edge that is neither vertical nor
      60             :                 // horizontal then the entire polygon is not rectilinear (and
      61             :                 // oriented along primary axes.)
      62         110 :                 if (aPoint.X() != aNextPoint.X() && aPoint.Y() != aNextPoint.Y())
      63           2 :                     return false;
      64             : 
      65         108 :                 aPoint = aNextPoint;
      66             :             }
      67             :             // Compare closing edge.
      68          27 :             if (aLastPoint.X() != aPoint.X() && aLastPoint.Y() != aPoint.Y())
      69           0 :                 return false;
      70             :         }
      71          23 :         return true;
      72             :     }
      73             : 
      74             :     /** Convert a rectilinear polygon (that is oriented along the primary axes)
      75             :         to a list of bands.  For this special form of polygon we can use an
      76             :         optimization that prevents the creation of one band per y value.
      77             :         However, it still is possible that some temporary bands are created that
      78             :         later can be optimized away.
      79             :         @param rPolyPolygon
      80             :             A set of zero, one, or more polygons, nested or not, that are
      81             :             converted into a list of bands.
      82             :         @return
      83             :             A new RegionBand object is returned that contains the bands that
      84             :             represent the given poly-polygon.
      85             :     */
      86          23 :     RegionBand* ImplRectilinearPolygonToBands(const tools::PolyPolygon& rPolyPoly)
      87             :     {
      88             :         OSL_ASSERT(ImplIsPolygonRectilinear (rPolyPoly));
      89             : 
      90             :         // Create a new RegionBand object as container of the bands.
      91          23 :         RegionBand* pRegionBand = new RegionBand();
      92          23 :         long nLineId = 0L;
      93             : 
      94             :         // Iterate over all polygons.
      95          23 :         const sal_uInt16 nPolyCount = rPolyPoly.Count();
      96          50 :         for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
      97             :         {
      98          27 :             const Polygon&  aPoly = rPolyPoly.GetObject(nPoly);
      99             : 
     100             :             // Iterate over all edges of the current polygon.
     101          27 :             const sal_uInt16 nSize = aPoly.GetSize();
     102          27 :             if (nSize < 2)
     103           0 :                 continue;
     104             :             // Avoid fetching every point twice (each point is the start point
     105             :             // of one and the end point of another edge.)
     106          27 :             Point aStart (aPoly.GetPoint(0));
     107          27 :             Point aEnd;
     108         162 :             for (sal_uInt16 nPoint = 1; nPoint <= nSize; ++nPoint, aStart=aEnd)
     109             :             {
     110             :                 // We take the implicit closing edge into account by mapping
     111             :                 // index nSize to 0.
     112         135 :                 aEnd = aPoly.GetPoint(nPoint%nSize);
     113         135 :                 if (aStart.Y() == aEnd.Y())
     114             :                 {
     115             :                     // Horizontal lines are ignored.
     116          81 :                     continue;
     117             :                 }
     118             : 
     119             :                 // At this point the line has to be vertical.
     120             :                 OSL_ASSERT(aStart.X() == aEnd.X());
     121             : 
     122             :                 // Sort y-coordinates to simplify the algorithm and store the
     123             :                 // direction separately.  The direction is calculated as it is
     124             :                 // in other places (but seems to be the wrong way.)
     125          54 :                 const long nTop (::std::min(aStart.Y(), aEnd.Y()));
     126          54 :                 const long nBottom (::std::max(aStart.Y(), aEnd.Y()));
     127          54 :                 const LineType eLineType (aStart.Y() > aEnd.Y() ? LINE_DESCENDING : LINE_ASCENDING);
     128             : 
     129             :                 // Make sure that the current line is covered by bands.
     130          54 :                 pRegionBand->ImplAddMissingBands(nTop,nBottom);
     131             : 
     132             :                 // Find top-most band that may contain nTop.
     133          54 :                 ImplRegionBand* pBand = pRegionBand->ImplGetFirstRegionBand();
     134         114 :                 while (pBand!=NULL && pBand->mnYBottom < nTop)
     135           6 :                     pBand = pBand->mpNextBand;
     136          54 :                 ImplRegionBand* pTopBand = pBand;
     137             :                 // If necessary split the band at nTop so that nTop is contained
     138             :                 // in the lower band.
     139          54 :                 if (pBand!=NULL
     140             :                        // Prevent the current band from becoming 0 pixel high
     141          54 :                     && pBand->mnYTop<nTop
     142             :                        // this allows the lowest pixel of the band to be split off
     143           2 :                     && pBand->mnYBottom>=nTop
     144             :                        // do not split a band that is just one pixel high
     145           2 :                     && pBand->mnYTop<pBand->mnYBottom)
     146             :                 {
     147             :                     // Split the top band.
     148           2 :                     pTopBand = pBand->SplitBand(nTop);
     149             :                 }
     150             : 
     151             :                 // Advance to band that may contain nBottom.
     152         118 :                 while (pBand!=NULL && pBand->mnYBottom < nBottom)
     153          10 :                     pBand = pBand->mpNextBand;
     154             :                 // The lowest band may have to be split at nBottom so that
     155             :                 // nBottom itself remains in the upper band.
     156          54 :                 if (pBand!=NULL
     157             :                        // allow the current band becoming 1 pixel high
     158          54 :                     && pBand->mnYTop<=nBottom
     159             :                        // prevent splitting off a band that is 0 pixel high
     160          54 :                     && pBand->mnYBottom>nBottom
     161             :                        // do not split a band that is just one pixel high
     162           0 :                     && pBand->mnYTop<pBand->mnYBottom)
     163             :                 {
     164             :                     // Split the bottom band.
     165           0 :                     pBand->SplitBand(nBottom+1);
     166             :                 }
     167             : 
     168             :                 // Note that we remember the top band (in pTopBand) but not the
     169             :                 // bottom band.  The later can be determined by comparing y
     170             :                 // coordinates.
     171             : 
     172             :                 // Add the x-value as point to all bands in the nTop->nBottom range.
     173         116 :                 for (pBand=pTopBand; pBand!=NULL&&pBand->mnYTop<=nBottom; pBand=pBand->mpNextBand)
     174          62 :                     pBand->InsertPoint(aStart.X(), nLineId++, true, eLineType);
     175             :             }
     176             :         }
     177             : 
     178          23 :         return pRegionBand;
     179             :     }
     180             : 
     181             :     /** Convert a general polygon (one for which ImplIsPolygonRectilinear()
     182             :         returns <FALSE/>) to bands.
     183             :     */
     184           2 :     RegionBand* ImplGeneralPolygonToBands(const tools::PolyPolygon& rPolyPoly, const Rectangle& rPolygonBoundingBox)
     185             :     {
     186           2 :         long nLineID = 0L;
     187             : 
     188             :         // initialisation and creation of Bands
     189           2 :         RegionBand* pRegionBand = new RegionBand();
     190           2 :         pRegionBand->CreateBandRange(rPolygonBoundingBox.Top(), rPolygonBoundingBox.Bottom());
     191             : 
     192             :         // insert polygons
     193           2 :         const sal_uInt16 nPolyCount = rPolyPoly.Count();
     194             : 
     195           4 :         for ( sal_uInt16 nPoly = 0; nPoly < nPolyCount; nPoly++ )
     196             :         {
     197             :             // get reference to current polygon
     198           2 :             const Polygon&  aPoly = rPolyPoly.GetObject( nPoly );
     199           2 :             const sal_uInt16    nSize = aPoly.GetSize();
     200             : 
     201             :             // not enough points ( <= 2 )? -> nothing to do!
     202           2 :             if ( nSize <= 2 )
     203           0 :                 continue;
     204             : 
     205             :             // band the polygon
     206         394 :             for ( sal_uInt16 nPoint = 1; nPoint < nSize; nPoint++ )
     207             :             {
     208         392 :                 pRegionBand->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
     209             :             }
     210             : 
     211             :             // close polygon with line from first point to last point, if necessary
     212           2 :             const Point rLastPoint = aPoly.GetPoint(nSize-1);
     213           2 :             const Point rFirstPoint = aPoly.GetPoint(0);
     214             : 
     215           2 :             if ( rLastPoint != rFirstPoint )
     216             :             {
     217           0 :                 pRegionBand->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
     218             :             }
     219             :         }
     220             : 
     221           2 :         return pRegionBand;
     222             :     }
     223             : } // end of anonymous namespace
     224             : 
     225             : namespace vcl {
     226             : 
     227     6146378 : bool vcl::Region::IsEmpty() const
     228             : {
     229     6146378 :     return !mbIsNull && !mpB2DPolyPolygon.get() && !mpPolyPolygon.get() && !mpRegionBand.get();
     230             : }
     231             : 
     232             : 
     233          25 : RegionBand* ImplCreateRegionBandFromPolyPolygon(const tools::PolyPolygon& rPolyPolygon)
     234             : {
     235          25 :     RegionBand* pRetval = 0;
     236             : 
     237          25 :     if(rPolyPolygon.Count())
     238             :     {
     239             :         // ensure to subdivide when bezier segemnts are used, it's going to
     240             :         // be expanded to rectangles
     241          25 :         tools::PolyPolygon aPolyPolygon;
     242             : 
     243          25 :         rPolyPolygon.AdaptiveSubdivide(aPolyPolygon);
     244             : 
     245          25 :         if(aPolyPolygon.Count())
     246             :         {
     247          25 :             const Rectangle aRect(aPolyPolygon.GetBoundRect());
     248             : 
     249          25 :             if(!aRect.IsEmpty())
     250             :             {
     251          25 :                 if(ImplIsPolygonRectilinear(aPolyPolygon))
     252             :                 {
     253             :                     // For rectilinear polygons there is an optimized band conversion.
     254          23 :                     pRetval = ImplRectilinearPolygonToBands(aPolyPolygon);
     255             :                 }
     256             :                 else
     257             :                 {
     258           2 :                     pRetval = ImplGeneralPolygonToBands(aPolyPolygon, aRect);
     259             :                 }
     260             : 
     261             :                 // Convert points into seps.
     262          25 :                 if(pRetval)
     263             :                 {
     264          25 :                     pRetval->processPoints();
     265             : 
     266             :                     // Optimize list of bands.  Adjacent bands with identical lists
     267             :                     // of seps are joined.
     268          25 :                     if(!pRetval->OptimizeBandList())
     269             :                     {
     270           0 :                         delete pRetval;
     271           0 :                         pRetval = 0;
     272             :                     }
     273             :                 }
     274             :             }
     275          25 :         }
     276             :     }
     277             : 
     278          25 :     return pRetval;
     279             : }
     280             : 
     281          99 : tools::PolyPolygon vcl::Region::ImplCreatePolyPolygonFromRegionBand() const
     282             : {
     283          99 :     tools::PolyPolygon aRetval;
     284             : 
     285          99 :     if(getRegionBand())
     286             :     {
     287          99 :         RectangleVector aRectangles;
     288          99 :         GetRegionRectangles(aRectangles);
     289             : 
     290         198 :         for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
     291             :         {
     292          99 :             aRetval.Insert(Polygon(*aRectIter));
     293          99 :         }
     294             :     }
     295             :     else
     296             :     {
     297             :         OSL_ENSURE(false, "Called with no local RegionBand (!)");
     298             :     }
     299             : 
     300          99 :     return aRetval;
     301             : }
     302             : 
     303          99 : basegfx::B2DPolyPolygon vcl::Region::ImplCreateB2DPolyPolygonFromRegionBand() const
     304             : {
     305          99 :     tools::PolyPolygon aPoly(ImplCreatePolyPolygonFromRegionBand());
     306             : 
     307          99 :     return aPoly.getB2DPolyPolygon();
     308             : }
     309             : 
     310     4116856 : Region::Region(bool bIsNull)
     311             : :   mpB2DPolyPolygon(),
     312             :     mpPolyPolygon(),
     313             :     mpRegionBand(),
     314     4116856 :     mbIsNull(bIsNull)
     315             : {
     316     4116856 : }
     317             : 
     318      546357 : Region::Region(const Rectangle& rRect)
     319             : :   mpB2DPolyPolygon(),
     320             :     mpPolyPolygon(),
     321             :     mpRegionBand(),
     322      546357 :     mbIsNull(false)
     323             : {
     324      546357 :     mpRegionBand.reset(rRect.IsEmpty() ? 0 : new RegionBand(rRect));
     325      546357 : }
     326             : 
     327           0 : Region::Region(const Polygon& rPolygon)
     328             : :   mpB2DPolyPolygon(),
     329             :     mpPolyPolygon(),
     330             :     mpRegionBand(),
     331           0 :     mbIsNull(false)
     332             : {
     333             : 
     334           0 :     if(rPolygon.GetSize())
     335             :     {
     336           0 :         ImplCreatePolyPolyRegion(rPolygon);
     337             :     }
     338           0 : }
     339             : 
     340          54 : Region::Region(const tools::PolyPolygon& rPolyPoly)
     341             : :   mpB2DPolyPolygon(),
     342             :     mpPolyPolygon(),
     343             :     mpRegionBand(),
     344          54 :     mbIsNull(false)
     345             : {
     346             : 
     347          54 :     if(rPolyPoly.Count())
     348             :     {
     349          19 :         ImplCreatePolyPolyRegion(rPolyPoly);
     350             :     }
     351          54 : }
     352             : 
     353         147 : Region::Region(const basegfx::B2DPolyPolygon& rPolyPoly)
     354             : :   mpB2DPolyPolygon(),
     355             :     mpPolyPolygon(),
     356             :     mpRegionBand(),
     357         147 :     mbIsNull(false)
     358             : {
     359             : 
     360         147 :     if(rPolyPoly.count())
     361             :     {
     362         147 :         ImplCreatePolyPolyRegion(rPolyPoly);
     363             :     }
     364         147 : }
     365             : 
     366     1776911 : Region::Region(const vcl::Region& rRegion)
     367             : :   mpB2DPolyPolygon(rRegion.mpB2DPolyPolygon),
     368             :     mpPolyPolygon(rRegion.mpPolyPolygon),
     369             :     mpRegionBand(rRegion.mpRegionBand),
     370     1776911 :     mbIsNull(rRegion.mbIsNull)
     371             : {
     372     1776911 : }
     373             : 
     374     6423982 : Region::~Region()
     375             : {
     376     6423982 : }
     377             : 
     378          19 : void vcl::Region::ImplCreatePolyPolyRegion( const tools::PolyPolygon& rPolyPoly )
     379             : {
     380          19 :     const sal_uInt16 nPolyCount = rPolyPoly.Count();
     381             : 
     382          19 :     if(nPolyCount)
     383             :     {
     384             :         // polypolygon empty? -> empty region
     385          19 :         const Rectangle aRect(rPolyPoly.GetBoundRect());
     386             : 
     387          19 :         if(!aRect.IsEmpty())
     388             :         {
     389             :             // width OR height == 1 ? => Rectangular region
     390          19 :             if((1 == aRect.GetWidth()) || (1 == aRect.GetHeight()) || rPolyPoly.IsRect())
     391             :             {
     392          18 :                 mpRegionBand.reset(new RegionBand(aRect));
     393             :             }
     394             :             else
     395             :             {
     396           1 :                 mpPolyPolygon.reset(new tools::PolyPolygon(rPolyPoly));
     397             :             }
     398             : 
     399          19 :             mbIsNull = false;
     400             :         }
     401             :     }
     402          19 : }
     403             : 
     404         147 : void vcl::Region::ImplCreatePolyPolyRegion( const basegfx::B2DPolyPolygon& rPolyPoly )
     405             : {
     406         147 :     if(rPolyPoly.count() && !rPolyPoly.getB2DRange().isEmpty())
     407             :     {
     408         147 :         mpB2DPolyPolygon.reset(new basegfx::B2DPolyPolygon(rPolyPoly));
     409         147 :         mbIsNull = false;
     410             :     }
     411         147 : }
     412             : 
     413      540549 : void vcl::Region::Move( long nHorzMove, long nVertMove )
     414             : {
     415      540549 :     if(IsNull() || IsEmpty())
     416             :     {
     417             :         // empty or null need no move
     418       89436 :         return;
     419             :     }
     420             : 
     421      451113 :     if(!nHorzMove && !nVertMove)
     422             :     {
     423             :         // no move defined
     424         165 :         return;
     425             :     }
     426             : 
     427      450948 :     if(getB2DPolyPolygon())
     428             :     {
     429           4 :         basegfx::B2DPolyPolygon aPoly(*getB2DPolyPolygon());
     430             : 
     431           4 :         aPoly.transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
     432           4 :         mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
     433           4 :         mpPolyPolygon.reset();
     434           4 :         mpRegionBand.reset();
     435             :     }
     436      450944 :     else if(getPolyPolygon())
     437             :     {
     438           0 :         tools::PolyPolygon aPoly(*getPolyPolygon());
     439             : 
     440           0 :         aPoly.Move(nHorzMove, nVertMove);
     441           0 :         mpB2DPolyPolygon.reset();
     442           0 :         mpPolyPolygon.reset(aPoly.Count() ? new tools::PolyPolygon(aPoly) : 0);
     443           0 :         mpRegionBand.reset();
     444             :     }
     445      450944 :     else if(getRegionBand())
     446             :     {
     447      450944 :         RegionBand* pNew = new RegionBand(*getRegionBand());
     448             : 
     449      450944 :         pNew->Move(nHorzMove, nVertMove);
     450      450944 :         mpB2DPolyPolygon.reset();
     451      450944 :         mpPolyPolygon.reset();
     452      450944 :         mpRegionBand.reset(pNew);
     453             :     }
     454             :     else
     455             :     {
     456             :         OSL_ENSURE(false, "Region::Move error: impossible combination (!)");
     457             :     }
     458             : }
     459             : 
     460          42 : void vcl::Region::Scale( double fScaleX, double fScaleY )
     461             : {
     462          42 :     if(IsNull() || IsEmpty())
     463             :     {
     464             :         // empty or null need no scale
     465           0 :         return;
     466             :     }
     467             : 
     468          42 :     if(basegfx::fTools::equalZero(fScaleX) && basegfx::fTools::equalZero(fScaleY))
     469             :     {
     470             :         // no scale defined
     471           0 :         return;
     472             :     }
     473             : 
     474          42 :     if(getB2DPolyPolygon())
     475             :     {
     476          42 :         basegfx::B2DPolyPolygon aPoly(*getB2DPolyPolygon());
     477             : 
     478          42 :         aPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
     479          42 :         mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
     480          42 :         mpPolyPolygon.reset();
     481          42 :         mpRegionBand.reset();
     482             :     }
     483           0 :     else if(getPolyPolygon())
     484             :     {
     485           0 :         tools::PolyPolygon aPoly(*getPolyPolygon());
     486             : 
     487           0 :         aPoly.Scale(fScaleX, fScaleY);
     488           0 :         mpB2DPolyPolygon.reset();
     489           0 :         mpPolyPolygon.reset(aPoly.Count() ? new tools::PolyPolygon(aPoly) : 0);
     490           0 :         mpRegionBand.reset();
     491             :     }
     492           0 :     else if(getRegionBand())
     493             :     {
     494           0 :         RegionBand* pNew = new RegionBand(*getRegionBand());
     495             : 
     496           0 :         pNew->Scale(fScaleX, fScaleY);
     497           0 :         mpB2DPolyPolygon.reset();
     498           0 :         mpPolyPolygon.reset();
     499           0 :         mpRegionBand.reset(pNew);
     500             :     }
     501             :     else
     502             :     {
     503             :         OSL_ENSURE(false, "Region::Scale error: impossible combination (!)");
     504             :     }
     505             : }
     506             : 
     507      140054 : bool vcl::Region::Union( const Rectangle& rRect )
     508             : {
     509      140054 :     if(rRect.IsEmpty())
     510             :     {
     511             :         // empty rectangle will not expand the existing union, nothing to do
     512         708 :         return true;
     513             :     }
     514             : 
     515      139346 :     if(IsEmpty())
     516             :     {
     517             :         // no local data, the union will be equal to source. Create using rectangle
     518      134184 :         *this = rRect;
     519      134184 :         return true;
     520             :     }
     521             : 
     522        5162 :     if(HasPolyPolygonOrB2DPolyPolygon())
     523             :     {
     524             :         // get this B2DPolyPolygon, solve on polygon base
     525           0 :         basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
     526             : 
     527           0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
     528             : 
     529           0 :         if(!aThisPolyPoly.count())
     530             :         {
     531             :             // no local polygon, use the rectangle as new region
     532           0 :             *this = rRect;
     533             :         }
     534             :         else
     535             :         {
     536             :             // get the other B2DPolyPolygon and use logical Or-Operation
     537             :             const basegfx::B2DPolygon aRectPoly(
     538             :                 basegfx::tools::createPolygonFromRect(
     539             :                     basegfx::B2DRectangle(
     540           0 :                         rRect.Left(),
     541           0 :                         rRect.Top(),
     542           0 :                         rRect.Right(),
     543           0 :                         rRect.Bottom())));
     544             :             const basegfx::B2DPolyPolygon aClip(
     545             :                 basegfx::tools::solvePolygonOperationOr(
     546             :                     aThisPolyPoly,
     547           0 :                     basegfx::B2DPolyPolygon(aRectPoly)));
     548           0 :             *this = vcl::Region(aClip);
     549             :         }
     550             : 
     551           0 :         return true;
     552             :     }
     553             : 
     554             :     // only region band mode possibility left here or null/empty
     555        5162 :     const RegionBand* pCurrent = getRegionBand();
     556             : 
     557        5162 :     if(!pCurrent)
     558             :     {
     559             :         // no region band, create using the rectangle
     560           0 :         *this = rRect;
     561           0 :         return true;
     562             :     }
     563             : 
     564        5162 :     RegionBand* pNew = new RegionBand(*pCurrent);
     565             : 
     566             :     // get justified rectangle
     567        5162 :     const long nLeft(std::min(rRect.Left(), rRect.Right()));
     568        5162 :     const long nTop(std::min(rRect.Top(), rRect.Bottom()));
     569        5162 :     const long nRight(std::max(rRect.Left(), rRect.Right()));
     570        5162 :     const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
     571             : 
     572             :     // insert bands if the boundaries are not already in the list
     573        5162 :     pNew->InsertBands(nTop, nBottom);
     574             : 
     575             :     // process union
     576        5162 :     pNew->Union(nLeft, nTop, nRight, nBottom);
     577             : 
     578             :     // cleanup
     579        5162 :     if(!pNew->OptimizeBandList())
     580             :     {
     581           0 :         delete pNew;
     582           0 :         pNew = 0;
     583             :     }
     584             : 
     585        5162 :     mpRegionBand.reset(pNew);
     586        5162 :     return true;
     587             : }
     588             : 
     589      265283 : bool vcl::Region::Intersect( const Rectangle& rRect )
     590             : {
     591      265283 :     if ( rRect.IsEmpty() )
     592             :     {
     593             :         // empty rectangle will create empty region
     594          23 :         SetEmpty();
     595          23 :         return true;
     596             :     }
     597             : 
     598      265260 :     if(IsNull())
     599             :     {
     600             :         // null region (everything) intersect with rect will give rect
     601       26437 :         *this = rRect;
     602       26437 :         return true;
     603             :     }
     604             : 
     605      238823 :     if(IsEmpty())
     606             :     {
     607             :         // no content, cannot get more empty
     608           0 :         return true;
     609             :     }
     610             : 
     611      238823 :     if(HasPolyPolygonOrB2DPolyPolygon())
     612             :     {
     613             :         // if polygon data prefer double precision, the other will be lost (if buffered)
     614          23 :         if(getB2DPolyPolygon())
     615             :         {
     616             :             const basegfx::B2DPolyPolygon aPoly(
     617             :                 basegfx::tools::clipPolyPolygonOnRange(
     618          22 :                     *getB2DPolyPolygon(),
     619             :                     basegfx::B2DRange(
     620          22 :                         rRect.Left(),
     621          22 :                         rRect.Top(),
     622          22 :                         rRect.Right() + 1,
     623          22 :                         rRect.Bottom() + 1),
     624             :                     true,
     625         110 :                     false));
     626             : 
     627          22 :             mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
     628          22 :             mpPolyPolygon.reset();
     629          22 :             mpRegionBand.reset();
     630             :         }
     631             :         else // if(getPolyPolygon())
     632             :         {
     633           1 :             tools::PolyPolygon aPoly(*getPolyPolygon());
     634             : 
     635             :             // use the PolyPolygon::Clip method for rectangles, this is
     636             :             // fairly simple (does not even use GPC) and saves us from
     637             :             // unnecessary banding
     638           1 :             aPoly.Clip(rRect);
     639             : 
     640           1 :             mpB2DPolyPolygon.reset();
     641           1 :             mpPolyPolygon.reset(aPoly.Count() ? new tools::PolyPolygon(aPoly) : 0);
     642           1 :             mpRegionBand.reset();
     643             :         }
     644             : 
     645          23 :         return true;
     646             :     }
     647             : 
     648             :     // only region band mode possibility left here or null/empty
     649      238800 :     const RegionBand* pCurrent = getRegionBand();
     650             : 
     651      238800 :     if(!pCurrent)
     652             :     {
     653             :         // region is empty -> nothing to do!
     654           0 :         return true;
     655             :     }
     656             : 
     657      238800 :     RegionBand* pNew = new RegionBand(*pCurrent);
     658             : 
     659             :     // get justified rectangle
     660      238800 :     const long nLeft(std::min(rRect.Left(), rRect.Right()));
     661      238800 :     const long nTop(std::min(rRect.Top(), rRect.Bottom()));
     662      238800 :     const long nRight(std::max(rRect.Left(), rRect.Right()));
     663      238800 :     const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
     664             : 
     665             :     // insert bands if the boundaries are not already in the list
     666      238800 :     pNew->InsertBands(nTop, nBottom);
     667             : 
     668             :     // process intersect
     669      238800 :     pNew->Intersect(nLeft, nTop, nRight, nBottom);
     670             : 
     671             :     // cleanup
     672      238800 :     if(!pNew->OptimizeBandList())
     673             :     {
     674       79940 :         delete pNew;
     675       79940 :         pNew = 0;
     676             :     }
     677             : 
     678      238800 :     mpRegionBand.reset(pNew);
     679      238800 :     return true;
     680             : }
     681             : 
     682      322952 : bool vcl::Region::Exclude( const Rectangle& rRect )
     683             : {
     684      322952 :     if ( rRect.IsEmpty() )
     685             :     {
     686             :         // excluding nothing will do no change
     687       70177 :         return true;
     688             :     }
     689             : 
     690      252775 :     if(IsEmpty())
     691             :     {
     692             :         // cannot exclude from empty, done
     693       18429 :         return true;
     694             :     }
     695             : 
     696      234346 :     if(IsNull())
     697             :     {
     698             :         // error; cannot exclude from null region since this is not representable
     699             :         // in the data
     700             :         OSL_ENSURE(false, "Region::Exclude error: Cannot exclude from null region (!)");
     701           0 :         return true;
     702             :     }
     703             : 
     704      234346 :     if( HasPolyPolygonOrB2DPolyPolygon() )
     705             :     {
     706             :         // get this B2DPolyPolygon
     707           0 :         basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
     708             : 
     709           0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
     710             : 
     711           0 :         if(!aThisPolyPoly.count())
     712             :         {
     713             :             // when local polygon is empty, nothing can be excluded
     714           0 :             return true;
     715             :         }
     716             : 
     717             :         // get the other B2DPolyPolygon
     718             :         const basegfx::B2DPolygon aRectPoly(
     719             :             basegfx::tools::createPolygonFromRect(
     720           0 :                 basegfx::B2DRectangle(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom())));
     721           0 :         const basegfx::B2DPolyPolygon aOtherPolyPoly(aRectPoly);
     722           0 :         const basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff(aThisPolyPoly, aOtherPolyPoly);
     723             : 
     724           0 :         *this = vcl::Region(aClip);
     725             : 
     726           0 :         return true;
     727             :     }
     728             : 
     729             :     // only region band mode possibility left here or null/empty
     730      234346 :     const RegionBand* pCurrent = getRegionBand();
     731             : 
     732      234346 :     if(!pCurrent)
     733             :     {
     734             :         // empty? -> done!
     735           0 :         return true;
     736             :     }
     737             : 
     738      234346 :     RegionBand* pNew = new RegionBand(*pCurrent);
     739             : 
     740             :     // get justified rectangle
     741      234346 :     const long nLeft(std::min(rRect.Left(), rRect.Right()));
     742      234346 :     const long nTop(std::min(rRect.Top(), rRect.Bottom()));
     743      234346 :     const long nRight(std::max(rRect.Left(), rRect.Right()));
     744      234346 :     const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
     745             : 
     746             :     // insert bands if the boundaries are not already in the list
     747      234346 :     pNew->InsertBands(nTop, nBottom);
     748             : 
     749             :     // process exclude
     750      234346 :     pNew->Exclude(nLeft, nTop, nRight, nBottom);
     751             : 
     752             :     // cleanup
     753      234346 :     if(!pNew->OptimizeBandList())
     754             :     {
     755       53422 :         delete pNew;
     756       53422 :         pNew = 0;
     757             :     }
     758             : 
     759      234346 :     mpRegionBand.reset(pNew);
     760      234346 :     return true;
     761             : }
     762             : 
     763           0 : bool vcl::Region::XOr( const Rectangle& rRect )
     764             : {
     765           0 :     if ( rRect.IsEmpty() )
     766             :     {
     767             :         // empty rectangle will not change local content
     768           0 :         return true;
     769             :     }
     770             : 
     771           0 :     if(IsEmpty())
     772             :     {
     773             :         // rRect will be the xored-form (local off, rect on)
     774           0 :         *this = rRect;
     775           0 :         return true;
     776             :     }
     777             : 
     778           0 :     if(IsNull())
     779             :     {
     780             :         // error; cannot exclude from null region since this is not representable
     781             :         // in the data
     782             :         OSL_ENSURE(false, "Region::XOr error: Cannot XOr with null region (!)");
     783           0 :         return true;
     784             :     }
     785             : 
     786           0 :     if( HasPolyPolygonOrB2DPolyPolygon() )
     787             :     {
     788             :         // get this B2DPolyPolygon
     789           0 :         basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
     790             : 
     791           0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
     792             : 
     793           0 :         if(!aThisPolyPoly.count())
     794             :         {
     795             :             // no local content, XOr will be equal to rectangle
     796           0 :             *this = rRect;
     797           0 :             return true;
     798             :         }
     799             : 
     800             :         // get the other B2DPolyPolygon
     801             :         const basegfx::B2DPolygon aRectPoly(
     802             :             basegfx::tools::createPolygonFromRect(
     803           0 :                 basegfx::B2DRectangle(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom())));
     804           0 :         const basegfx::B2DPolyPolygon aOtherPolyPoly(aRectPoly);
     805           0 :         const basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor(aThisPolyPoly, aOtherPolyPoly);
     806             : 
     807           0 :         *this = vcl::Region(aClip);
     808             : 
     809           0 :         return true;
     810             :     }
     811             : 
     812             :     // only region band mode possibility left here or null/empty
     813           0 :     const RegionBand* pCurrent = getRegionBand();
     814             : 
     815           0 :     if(!pCurrent)
     816             :     {
     817             :         // rRect will be the xored-form (local off, rect on)
     818           0 :         *this = rRect;
     819           0 :         return true;
     820             :     }
     821             : 
     822             :     // only region band mode possibility left here or null/empty
     823           0 :     RegionBand* pNew = new RegionBand(*getRegionBand());
     824             : 
     825             :     // get justified rectangle
     826           0 :     const long nLeft(std::min(rRect.Left(), rRect.Right()));
     827           0 :     const long nTop(std::min(rRect.Top(), rRect.Bottom()));
     828           0 :     const long nRight(std::max(rRect.Left(), rRect.Right()));
     829           0 :     const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
     830             : 
     831             :     // insert bands if the boundaries are not already in the list
     832           0 :     pNew->InsertBands(nTop, nBottom);
     833             : 
     834             :     // process xor
     835           0 :     pNew->XOr(nLeft, nTop, nRight, nBottom);
     836             : 
     837             :     // cleanup
     838           0 :     if(!pNew->OptimizeBandList())
     839             :     {
     840           0 :         delete pNew;
     841           0 :         pNew = 0;
     842             :     }
     843             : 
     844           0 :     mpRegionBand.reset(pNew);
     845           0 :     return true;
     846             : }
     847             : 
     848      195820 : bool vcl::Region::Union( const vcl::Region& rRegion )
     849             : {
     850      195820 :     if(rRegion.IsEmpty())
     851             :     {
     852             :         // no extension at all
     853        2907 :         return true;
     854             :     }
     855             : 
     856      192913 :     if(rRegion.IsNull())
     857             :     {
     858             :         // extending with null region -> null region
     859           0 :         *this = vcl::Region(true);
     860           0 :         return true;
     861             :     }
     862             : 
     863      192913 :     if(IsEmpty())
     864             :     {
     865             :         // local is empty, union will give source region
     866      121506 :         *this = rRegion;
     867      121506 :         return true;
     868             :     }
     869             : 
     870       71407 :     if(IsNull())
     871             :     {
     872             :         // already fully expanded (is null region), cannot be extended
     873           0 :         return true;
     874             :     }
     875             : 
     876       71407 :     if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
     877             :     {
     878             :         // get this B2DPolyPolygon
     879           0 :         basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
     880             : 
     881           0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
     882             : 
     883           0 :         if(!aThisPolyPoly.count())
     884             :         {
     885             :             // when no local content, union will be equal to rRegion
     886           0 :             *this = rRegion;
     887           0 :             return true;
     888             :         }
     889             : 
     890             :         // get the other B2DPolyPolygon
     891           0 :         basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
     892           0 :         aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation(aOtherPolyPoly);
     893             : 
     894             :         // use logical OR operation
     895           0 :         basegfx::B2DPolyPolygon aClip(basegfx::tools::solvePolygonOperationOr(aThisPolyPoly, aOtherPolyPoly));
     896             : 
     897           0 :         *this = vcl::Region( aClip );
     898           0 :         return true;
     899             :     }
     900             : 
     901             :     // only region band mode possibility left here or null/empty
     902       71407 :     const RegionBand* pCurrent = getRegionBand();
     903             : 
     904       71407 :     if(!pCurrent)
     905             :     {
     906             :         // local is empty, union will give source region
     907           0 :         *this = rRegion;
     908           0 :         return true;
     909             :     }
     910             : 
     911       71407 :     const RegionBand* pSource = rRegion.getRegionBand();
     912             : 
     913       71407 :     if(!pSource)
     914             :     {
     915             :         // no extension at all
     916           0 :         return true;
     917             :     }
     918             : 
     919             :     // prepare source and target
     920       71407 :     RegionBand* pNew = new RegionBand(*pCurrent);
     921             : 
     922             :     // union with source
     923       71407 :     pNew->Union(*pSource);
     924             : 
     925             :     // cleanup
     926       71407 :     if(!pNew->OptimizeBandList())
     927             :     {
     928           0 :         delete pNew;
     929           0 :         pNew = 0;
     930             :     }
     931             : 
     932       71407 :     mpRegionBand.reset(pNew);
     933       71407 :     return true;
     934             : }
     935             : 
     936     1236782 : bool vcl::Region::Intersect( const vcl::Region& rRegion )
     937             : {
     938             :     // same instance data? -> nothing to do!
     939     1236782 :     if(getB2DPolyPolygon() && getB2DPolyPolygon() == rRegion.getB2DPolyPolygon())
     940             :     {
     941           0 :         return true;
     942             :     }
     943             : 
     944     1236782 :     if(getPolyPolygon() && getPolyPolygon() == rRegion.getPolyPolygon())
     945             :     {
     946           0 :         return true;
     947             :     }
     948             : 
     949     1236782 :     if(getRegionBand() && getRegionBand() == rRegion.getRegionBand())
     950             :     {
     951           0 :         return true;
     952             :     }
     953             : 
     954     1236782 :     if(rRegion.IsNull())
     955             :     {
     956             :         // source region is null-region, intersect will not change local region
     957           0 :         return true;
     958             :     }
     959             : 
     960     1236782 :     if(IsNull())
     961             :     {
     962             :         // when local region is null-region, intersect will be equal to source
     963      125943 :         *this = rRegion;
     964      125943 :         return true;
     965             :     }
     966             : 
     967     1110839 :     if(rRegion.IsEmpty())
     968             :     {
     969             :         // source region is empty, intersection will always be empty
     970      121654 :         SetEmpty();
     971      121654 :         return true;
     972             :     }
     973             : 
     974      989185 :     if(IsEmpty())
     975             :     {
     976             :         // local region is empty, cannot get more empty than that. Nothing to do
     977      103909 :         return true;
     978             :     }
     979             : 
     980      885276 :     if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
     981             :     {
     982             :         // get this B2DPolyPolygon
     983           0 :         basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
     984             : 
     985           0 :         if(!aThisPolyPoly.count())
     986             :         {
     987             :             // local region is empty, cannot get more empty than that. Nothing to do
     988           0 :             return true;
     989             :         }
     990             : 
     991             :         // get the other B2DPolyPolygon
     992           0 :         basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
     993             : 
     994           0 :         if(!aOtherPolyPoly.count())
     995             :         {
     996             :             // source region is empty, intersection will always be empty
     997           0 :             SetEmpty();
     998           0 :             return true;
     999             :         }
    1000             : 
    1001             :         const basegfx::B2DPolyPolygon aClip(
    1002             :             basegfx::tools::clipPolyPolygonOnPolyPolygon(
    1003             :                 aOtherPolyPoly,
    1004             :                 aThisPolyPoly,
    1005             :                 true,
    1006           0 :                 false));
    1007           0 :         *this = vcl::Region( aClip );
    1008           0 :         return true;
    1009             :     }
    1010             : 
    1011             :     // only region band mode possibility left here or null/empty
    1012      885276 :     const RegionBand* pCurrent = getRegionBand();
    1013             : 
    1014      885276 :     if(!pCurrent)
    1015             :     {
    1016             :         // local region is empty, cannot get more empty than that. Nothing to do
    1017           0 :         return true;
    1018             :     }
    1019             : 
    1020      885276 :     const RegionBand* pSource = rRegion.getRegionBand();
    1021             : 
    1022      885276 :     if(!pSource)
    1023             :     {
    1024             :         // source region is empty, intersection will always be empty
    1025           0 :         SetEmpty();
    1026           0 :         return true;
    1027             :     }
    1028             : 
    1029             :     // both RegionBands exist and are not empty
    1030      885276 :     if(pCurrent->getRectangleCount() + 2 < pSource->getRectangleCount())
    1031             :     {
    1032             :         // when we have less rectangles, turn around the call
    1033        6255 :         vcl::Region aTempRegion = rRegion;
    1034        6255 :         aTempRegion.Intersect( *this );
    1035        6255 :         *this = aTempRegion;
    1036             :     }
    1037             :     else
    1038             :     {
    1039             :         // prepare new regionBand
    1040      879021 :         RegionBand* pNew = new RegionBand(*pCurrent);
    1041             : 
    1042             :         // intersect with source
    1043      879021 :         pNew->Intersect(*pSource);
    1044             : 
    1045             :         // cleanup
    1046      879021 :         if(!pNew->OptimizeBandList())
    1047             :         {
    1048       70814 :             delete pNew;
    1049       70814 :             pNew = 0;
    1050             :         }
    1051             : 
    1052      879021 :         mpRegionBand.reset(pNew);
    1053             :     }
    1054             : 
    1055      885276 :     return true;
    1056             : }
    1057             : 
    1058        9578 : bool vcl::Region::Exclude( const vcl::Region& rRegion )
    1059             : {
    1060        9578 :     if ( rRegion.IsEmpty() )
    1061             :     {
    1062             :         // excluding nothing will do no change
    1063        5430 :         return true;
    1064             :     }
    1065             : 
    1066        4148 :     if ( rRegion.IsNull() )
    1067             :     {
    1068             :         // excluding everything will create empty region
    1069           0 :         SetEmpty();
    1070           0 :         return true;
    1071             :     }
    1072             : 
    1073        4148 :     if(IsEmpty())
    1074             :     {
    1075             :         // cannot exclude from empty, done
    1076           0 :         return true;
    1077             :     }
    1078             : 
    1079        4148 :     if(IsNull())
    1080             :     {
    1081             :         // error; cannot exclude from null region since this is not representable
    1082             :         // in the data
    1083             :         OSL_ENSURE(false, "Region::Exclude error: Cannot exclude from null region (!)");
    1084           0 :         return true;
    1085             :     }
    1086             : 
    1087        4148 :     if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
    1088             :     {
    1089             :         // get this B2DPolyPolygon
    1090           0 :         basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
    1091             : 
    1092           0 :         if(!aThisPolyPoly.count())
    1093             :         {
    1094             :             // cannot exclude from empty, done
    1095           0 :             return true;
    1096             :         }
    1097             : 
    1098           0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
    1099             : 
    1100             :         // get the other B2DPolyPolygon
    1101           0 :         basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
    1102           0 :         aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
    1103             : 
    1104           0 :         basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
    1105           0 :         *this = vcl::Region( aClip );
    1106           0 :         return true;
    1107             :     }
    1108             : 
    1109             :     // only region band mode possibility left here or null/empty
    1110        4148 :     const RegionBand* pCurrent = getRegionBand();
    1111             : 
    1112        4148 :     if(!pCurrent)
    1113             :     {
    1114             :         // cannot exclude from empty, done
    1115           0 :         return true;
    1116             :     }
    1117             : 
    1118        4148 :     const RegionBand* pSource = rRegion.getRegionBand();
    1119             : 
    1120        4148 :     if(!pSource)
    1121             :     {
    1122             :         // excluding nothing will do no change
    1123           0 :         return true;
    1124             :     }
    1125             : 
    1126             :     // prepare source and target
    1127        4148 :     RegionBand* pNew = new RegionBand(*pCurrent);
    1128             : 
    1129             :     // union with source
    1130        4148 :     const bool bSuccess(pNew->Exclude(*pSource));
    1131             : 
    1132             :     // cleanup
    1133        4148 :     if(!bSuccess)
    1134             :     {
    1135         148 :         delete pNew;
    1136         148 :         pNew = 0;
    1137             :     }
    1138             : 
    1139        4148 :     mpRegionBand.reset(pNew);
    1140        4148 :     return true;
    1141             : }
    1142             : 
    1143           0 : bool vcl::Region::XOr( const vcl::Region& rRegion )
    1144             : {
    1145           0 :     if ( rRegion.IsEmpty() )
    1146             :     {
    1147             :         // empty region will not change local content
    1148           0 :         return true;
    1149             :     }
    1150             : 
    1151           0 :     if ( rRegion.IsNull() )
    1152             :     {
    1153             :         // error; cannot exclude null region from local since this is not representable
    1154             :         // in the data
    1155             :         OSL_ENSURE(false, "Region::XOr error: Cannot XOr with null region (!)");
    1156           0 :         return true;
    1157             :     }
    1158             : 
    1159           0 :     if(IsEmpty())
    1160             :     {
    1161             :         // rRect will be the xored-form (local off, rect on)
    1162           0 :         *this = rRegion;
    1163           0 :         return true;
    1164             :     }
    1165             : 
    1166           0 :     if(IsNull())
    1167             :     {
    1168             :         // error: cannot exclude from null region since this is not representable
    1169             :         // in the data
    1170             :         OSL_ENSURE(false, "Region::XOr error: Cannot XOr with null region (!)");
    1171           0 :         return false;
    1172             :     }
    1173             : 
    1174           0 :     if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
    1175             :     {
    1176             :         // get this B2DPolyPolygon
    1177           0 :         basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
    1178             : 
    1179           0 :         if(!aThisPolyPoly.count())
    1180             :         {
    1181             :             // rRect will be the xored-form (local off, rect on)
    1182           0 :             *this = rRegion;
    1183           0 :             return true;
    1184             :         }
    1185             : 
    1186           0 :         aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
    1187             : 
    1188             :         // get the other B2DPolyPolygon
    1189           0 :         basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
    1190           0 :         aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
    1191             : 
    1192           0 :         basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
    1193           0 :         *this = vcl::Region( aClip );
    1194           0 :         return true;
    1195             :     }
    1196             : 
    1197             :     // only region band mode possibility left here or null/empty
    1198           0 :     const RegionBand* pCurrent = getRegionBand();
    1199             : 
    1200           0 :     if(!pCurrent)
    1201             :     {
    1202             :         // rRect will be the xored-form (local off, rect on)
    1203           0 :         *this = rRegion;
    1204           0 :         return true;
    1205             :     }
    1206             : 
    1207           0 :     const RegionBand* pSource = rRegion.getRegionBand();
    1208             : 
    1209           0 :     if(!pSource)
    1210             :     {
    1211             :         // empty region will not change local content
    1212           0 :         return true;
    1213             :     }
    1214             : 
    1215             :     // prepare source and target
    1216           0 :     RegionBand* pNew = new RegionBand(*pCurrent);
    1217             : 
    1218             :     // union with source
    1219           0 :     pNew->XOr(*pSource);
    1220             : 
    1221             :     // cleanup
    1222           0 :     if(!pNew->OptimizeBandList())
    1223             :     {
    1224           0 :         delete pNew;
    1225           0 :         pNew = 0;
    1226             :     }
    1227             : 
    1228           0 :     mpRegionBand.reset(pNew);
    1229             : 
    1230           0 :     return true;
    1231             : }
    1232             : 
    1233      328825 : Rectangle vcl::Region::GetBoundRect() const
    1234             : {
    1235      328825 :     if(IsEmpty())
    1236             :     {
    1237             :         // no internal data? -> region is empty!
    1238        5970 :         return Rectangle();
    1239             :     }
    1240             : 
    1241      322855 :     if(IsNull())
    1242             :     {
    1243             :         // error; null region has no BoundRect
    1244             :         // OSL_ENSURE(false, "Region::GetBoundRect error: null region has unlimitied bound rect, not representable (!)");
    1245       10303 :         return Rectangle();
    1246             :     }
    1247             : 
    1248             :     // prefer double precision source
    1249      312552 :     if(getB2DPolyPolygon())
    1250             :     {
    1251           8 :         const basegfx::B2DRange aRange(basegfx::tools::getRange(*getB2DPolyPolygon()));
    1252             : 
    1253           8 :         if(aRange.isEmpty())
    1254             :         {
    1255             :             // emulate PolyPolygon::GetBoundRect() when empty polygon
    1256           0 :             return Rectangle();
    1257             :         }
    1258             :         else
    1259             :         {
    1260             :             // #i122149# corrected rounding, no need for ceil() and floor() here
    1261             :             return Rectangle(
    1262          16 :                 basegfx::fround(aRange.getMinX()), basegfx::fround(aRange.getMinY()),
    1263          24 :                 basegfx::fround(aRange.getMaxX()), basegfx::fround(aRange.getMaxY()));
    1264             :         }
    1265             :     }
    1266             : 
    1267      312544 :     if(getPolyPolygon())
    1268             :     {
    1269           0 :         return getPolyPolygon()->GetBoundRect();
    1270             :     }
    1271             : 
    1272      312544 :     if(getRegionBand())
    1273             :     {
    1274      312544 :         return getRegionBand()->GetBoundRect();
    1275             :     }
    1276             : 
    1277           0 :     return Rectangle();
    1278             : }
    1279             : 
    1280          43 : const tools::PolyPolygon vcl::Region::GetAsPolyPolygon() const
    1281             : {
    1282          43 :     if(getPolyPolygon())
    1283             :     {
    1284           0 :         return *getPolyPolygon();
    1285             :     }
    1286             : 
    1287          43 :     if(getB2DPolyPolygon())
    1288             :     {
    1289             :         // the polygon needs to be converted, buffer the down converion
    1290          43 :         const tools::PolyPolygon aPolyPolgon(*getB2DPolyPolygon());
    1291          43 :         const_cast< vcl::Region* >(this)->mpPolyPolygon.reset(new tools::PolyPolygon(aPolyPolgon));
    1292             : 
    1293          43 :         return *getPolyPolygon();
    1294             :     }
    1295             : 
    1296           0 :     if(getRegionBand())
    1297             :     {
    1298             :         // the BandRegion needs to be converted, buffer the converion
    1299           0 :         const tools::PolyPolygon aPolyPolgon(ImplCreatePolyPolygonFromRegionBand());
    1300           0 :         const_cast< vcl::Region* >(this)->mpPolyPolygon.reset(new tools::PolyPolygon(aPolyPolgon));
    1301             : 
    1302           0 :         return *getPolyPolygon();
    1303             :     }
    1304             : 
    1305           0 :     return tools::PolyPolygon();
    1306             : }
    1307             : 
    1308         191 : const basegfx::B2DPolyPolygon vcl::Region::GetAsB2DPolyPolygon() const
    1309             : {
    1310         191 :     if(getB2DPolyPolygon())
    1311             :     {
    1312          50 :         return *getB2DPolyPolygon();
    1313             :     }
    1314             : 
    1315         141 :     if(getPolyPolygon())
    1316             :     {
    1317             :         // the polygon needs to be converted, buffer the up conversion. This will be preferred from now.
    1318          42 :         const basegfx::B2DPolyPolygon aB2DPolyPolygon(getPolyPolygon()->getB2DPolyPolygon());
    1319          42 :         const_cast< vcl::Region* >(this)->mpB2DPolyPolygon.reset(new basegfx::B2DPolyPolygon(aB2DPolyPolygon));
    1320             : 
    1321          42 :         return *getB2DPolyPolygon();
    1322             :     }
    1323             : 
    1324          99 :     if(getRegionBand())
    1325             :     {
    1326             :         // the BandRegion needs to be converted, buffer the converion
    1327          99 :         const basegfx::B2DPolyPolygon aB2DPolyPolygon(ImplCreateB2DPolyPolygonFromRegionBand());
    1328          99 :         const_cast< vcl::Region* >(this)->mpB2DPolyPolygon.reset(new basegfx::B2DPolyPolygon(aB2DPolyPolygon));
    1329             : 
    1330          99 :         return *getB2DPolyPolygon();
    1331             :     }
    1332             : 
    1333           0 :     return basegfx::B2DPolyPolygon();
    1334             : }
    1335             : 
    1336      702868 : const RegionBand* vcl::Region::GetAsRegionBand() const
    1337             : {
    1338      702868 :     if(!getRegionBand())
    1339             :     {
    1340        1431 :         if(getB2DPolyPolygon())
    1341             :         {
    1342             :             // convert B2DPolyPolygon to RegionBand, buffer it and return it
    1343          23 :             const_cast< vcl::Region* >(this)->mpRegionBand.reset(ImplCreateRegionBandFromPolyPolygon(tools::PolyPolygon(*getB2DPolyPolygon())));
    1344             :         }
    1345        1408 :         else if(getPolyPolygon())
    1346             :         {
    1347             :             // convert B2DPolyPolygon to RegionBand, buffer it and return it
    1348           2 :             const_cast< vcl::Region* >(this)->mpRegionBand.reset(ImplCreateRegionBandFromPolyPolygon(*getPolyPolygon()));
    1349             :         }
    1350             :     }
    1351             : 
    1352      702868 :     return getRegionBand();
    1353             : }
    1354             : 
    1355           0 : bool vcl::Region::IsInside( const Point& rPoint ) const
    1356             : {
    1357           0 :     if(IsEmpty())
    1358             :     {
    1359             :         // no point can be in empty region
    1360           0 :         return false;
    1361             :     }
    1362             : 
    1363           0 :     if(IsNull())
    1364             :     {
    1365             :         // all points are inside null-region
    1366           0 :         return true;
    1367             :     }
    1368             : 
    1369             :     // Too expensive (?)
    1370             :     //if(mpImplRegion->getRegionPolyPoly())
    1371             :     //{
    1372             :     //  return mpImplRegion->getRegionPolyPoly()->IsInside( rPoint );
    1373             :     //}
    1374             : 
    1375             :     // ensure RegionBand existence
    1376           0 :     const RegionBand* pRegionBand = GetAsRegionBand();
    1377             : 
    1378           0 :     if(pRegionBand)
    1379             :     {
    1380           0 :         return pRegionBand->IsInside(rPoint);
    1381             :     }
    1382             : 
    1383           0 :     return false;
    1384             : }
    1385             : 
    1386           0 : bool vcl::Region::IsInside( const Rectangle& rRect ) const
    1387             : {
    1388           0 :     if(IsEmpty())
    1389             :     {
    1390             :         // no rectangle can be in empty region
    1391           0 :         return false;
    1392             :     }
    1393             : 
    1394           0 :     if(IsNull())
    1395             :     {
    1396             :         // rectangle always inside null-region
    1397           0 :         return true;
    1398             :     }
    1399             : 
    1400           0 :     if ( rRect.IsEmpty() )
    1401             :     {
    1402             :         // is rectangle empty? -> not inside
    1403           0 :         return false;
    1404             :     }
    1405             : 
    1406             :     // create region from rectangle and intersect own region
    1407           0 :     vcl::Region aRegion(rRect);
    1408           0 :     aRegion.Exclude(*this);
    1409             : 
    1410             :     // rectangle is inside if exclusion is empty
    1411           0 :     return aRegion.IsEmpty();
    1412             : }
    1413             : 
    1414       13641 : bool vcl::Region::IsOver( const Rectangle& rRect ) const
    1415             : {
    1416       13641 :     if(IsEmpty())
    1417             :     {
    1418             :         // nothing can be over something empty
    1419        8447 :         return false;
    1420             :     }
    1421             : 
    1422        5194 :     if(IsNull())
    1423             :     {
    1424             :         // everything is over null region
    1425           0 :         return true;
    1426             :     }
    1427             : 
    1428             :     // Can we optimize this ??? - is used in StarDraw for brushes pointers
    1429             :     // Why we have no IsOver for Regions ???
    1430             :     // create region from rectangle and intersect own region
    1431        5194 :     vcl::Region aRegion(rRect);
    1432        5194 :     aRegion.Intersect( *this );
    1433             : 
    1434             :     // rectangle is over if include is not empty
    1435        5194 :     return !aRegion.IsEmpty();
    1436             : }
    1437             : 
    1438           0 : bool vcl::Region::IsRectangle() const
    1439             : {
    1440           0 :     if( IsEmpty() || IsNull() )
    1441           0 :         return false;
    1442             : 
    1443           0 :     if( getB2DPolyPolygon() )
    1444           0 :         return basegfx::tools::isRectangle( *getB2DPolyPolygon() );
    1445             : 
    1446           0 :     if( getPolyPolygon() )
    1447           0 :         return getPolyPolygon()->IsRect();
    1448             : 
    1449           0 :     if( getRegionBand() )
    1450           0 :         return (getRegionBand()->getRectangleCount() == 1);
    1451             : 
    1452           0 :     return false;
    1453             : }
    1454             : 
    1455      523507 : void vcl::Region::SetNull()
    1456             : {
    1457             :     // reset all content
    1458      523507 :     mpB2DPolyPolygon.reset();
    1459      523507 :     mpPolyPolygon.reset();
    1460      523507 :     mpRegionBand.reset();
    1461      523507 :     mbIsNull = true;
    1462      523507 : }
    1463             : 
    1464      271976 : void vcl::Region::SetEmpty()
    1465             : {
    1466             :     // reset all content
    1467      271976 :     mpB2DPolyPolygon.reset();
    1468      271976 :     mpPolyPolygon.reset();
    1469      271976 :     mpRegionBand.reset();
    1470      271976 :     mbIsNull = false;
    1471      271976 : }
    1472             : 
    1473     2893307 : Region& vcl::Region::operator=( const vcl::Region& rRegion )
    1474             : {
    1475             :     // reset all content
    1476     2893307 :     mpB2DPolyPolygon = rRegion.mpB2DPolyPolygon;
    1477     2893307 :     mpPolyPolygon = rRegion.mpPolyPolygon;
    1478     2893307 :     mpRegionBand = rRegion.mpRegionBand;
    1479     2893307 :     mbIsNull = rRegion.mbIsNull;
    1480             : 
    1481     2893307 :     return *this;
    1482             : }
    1483             : 
    1484      479345 : Region& vcl::Region::operator=( const Rectangle& rRect )
    1485             : {
    1486      479345 :     mpB2DPolyPolygon.reset();
    1487      479345 :     mpPolyPolygon.reset();
    1488      479345 :     mpRegionBand.reset(rRect.IsEmpty() ? 0 : new RegionBand(rRect));
    1489      479345 :     mbIsNull = false;
    1490             : 
    1491      479345 :     return *this;
    1492             : }
    1493             : 
    1494       26789 : bool vcl::Region::operator==( const vcl::Region& rRegion ) const
    1495             : {
    1496       26789 :     if(IsNull() && rRegion.IsNull())
    1497             :     {
    1498             :         // both are null region
    1499           0 :         return true;
    1500             :     }
    1501             : 
    1502       26789 :     if(IsEmpty() && rRegion.IsEmpty())
    1503             :     {
    1504             :         // both are empty
    1505           0 :         return true;
    1506             :     }
    1507             : 
    1508       26789 :     if(getB2DPolyPolygon() && getB2DPolyPolygon() == rRegion.getB2DPolyPolygon())
    1509             :     {
    1510             :         // same instance data? -> equal
    1511           0 :         return true;
    1512             :     }
    1513             : 
    1514       26789 :     if(getPolyPolygon() && getPolyPolygon() == rRegion.getPolyPolygon())
    1515             :     {
    1516             :         // same instance data? -> equal
    1517           0 :         return true;
    1518             :     }
    1519             : 
    1520       26789 :     if(getRegionBand() && getRegionBand() == rRegion.getRegionBand())
    1521             :     {
    1522             :         // same instance data? -> equal
    1523           0 :         return true;
    1524             :     }
    1525             : 
    1526       26789 :     if(IsNull() || IsEmpty())
    1527             :     {
    1528           0 :         return false;
    1529             :     }
    1530             : 
    1531       26789 :     if(rRegion.IsNull() || rRegion.IsEmpty())
    1532             :     {
    1533           0 :         return false;
    1534             :     }
    1535             : 
    1536       26789 :     if(rRegion.getB2DPolyPolygon() || getB2DPolyPolygon())
    1537             :     {
    1538             :         // one of both has a B2DPolyPolygon based region, ensure both have it
    1539             :         // by evtl. conversion
    1540           0 :         GetAsB2DPolyPolygon();
    1541           0 :         rRegion.GetAsB2DPolyPolygon();
    1542             : 
    1543           0 :         return *rRegion.getB2DPolyPolygon() == *getB2DPolyPolygon();
    1544             :     }
    1545             : 
    1546       26789 :     if(rRegion.getPolyPolygon() || getPolyPolygon())
    1547             :     {
    1548             :         // one of both has a B2DPolyPolygon based region, ensure both have it
    1549             :         // by evtl. conversion
    1550           0 :         GetAsPolyPolygon();
    1551           0 :         rRegion.GetAsPolyPolygon();
    1552             : 
    1553           0 :         return *rRegion.getPolyPolygon() == *getPolyPolygon();
    1554             :     }
    1555             : 
    1556             :     // both are not empty or null (see above) and if content supported polygon
    1557             :     // data the comparison is already done. Only both on RegionBand base can be left,
    1558             :     // but better check
    1559       26789 :     if(rRegion.getRegionBand() && getRegionBand())
    1560             :     {
    1561       26789 :         return *rRegion.getRegionBand() == *getRegionBand();
    1562             :     }
    1563             : 
    1564             :     // should not happen, but better deny equality
    1565           0 :     return false;
    1566             : }
    1567             : 
    1568        1014 : SvStream& ReadRegion(SvStream& rIStrm, vcl::Region& rRegion)
    1569             : {
    1570        1014 :     VersionCompat aCompat(rIStrm, StreamMode::READ);
    1571        1014 :     sal_uInt16 nVersion(0);
    1572        1014 :     sal_uInt16 nTmp16(0);
    1573             : 
    1574             :     // clear region to be loaded
    1575        1014 :     rRegion.SetEmpty();
    1576             : 
    1577             :     // get version of streamed region
    1578        1014 :     rIStrm.ReadUInt16( nVersion );
    1579             : 
    1580             :     // get type of region
    1581        1014 :     rIStrm.ReadUInt16( nTmp16 );
    1582             : 
    1583             :     enum RegionType { REGION_NULL, REGION_EMPTY, REGION_RECTANGLE, REGION_COMPLEX };
    1584        1014 :     RegionType meStreamedType = (RegionType)nTmp16;
    1585             : 
    1586        1014 :     switch(meStreamedType)
    1587             :     {
    1588             :         case REGION_NULL:
    1589             :         {
    1590           0 :             rRegion.SetNull();
    1591           0 :             break;
    1592             :         }
    1593             : 
    1594             :         case REGION_EMPTY:
    1595             :         {
    1596           0 :             rRegion.SetEmpty();
    1597           0 :             break;
    1598             :         }
    1599             : 
    1600             :         default:
    1601             :         {
    1602        1014 :             RegionBand* pNewRegionBand = new RegionBand();
    1603        1014 :             pNewRegionBand->load(rIStrm);
    1604        1014 :             rRegion.mpRegionBand.reset(pNewRegionBand);
    1605             : 
    1606        1014 :             if(aCompat.GetVersion() >= 2)
    1607             :             {
    1608        1014 :                 bool bHasPolyPolygon(false);
    1609             : 
    1610        1014 :                 rIStrm.ReadCharAsBool( bHasPolyPolygon );
    1611             : 
    1612        1014 :                 if(bHasPolyPolygon)
    1613             :                 {
    1614          43 :                     tools::PolyPolygon* pNewPoly = new tools::PolyPolygon();
    1615          43 :                     ReadPolyPolygon( rIStrm, *pNewPoly );
    1616          43 :                     rRegion.mpPolyPolygon.reset(pNewPoly);
    1617             :                 }
    1618             :             }
    1619             : 
    1620        1014 :             break;
    1621             :         }
    1622             :     }
    1623             : 
    1624        1014 :     return rIStrm;
    1625             : }
    1626             : 
    1627        1587 : SvStream& WriteRegion( SvStream& rOStrm, const vcl::Region& rRegion )
    1628             : {
    1629        1587 :     const sal_uInt16 nVersion(2);
    1630        1587 :     VersionCompat aCompat(rOStrm, StreamMode::WRITE, nVersion);
    1631             : 
    1632             :     // put version
    1633        1587 :     rOStrm.WriteUInt16( nVersion );
    1634             : 
    1635             :     // put type
    1636             :     enum RegionType { REGION_NULL, REGION_EMPTY, REGION_RECTANGLE, REGION_COMPLEX };
    1637        1587 :     RegionType aRegionType(REGION_COMPLEX);
    1638        1587 :     bool bEmpty(rRegion.IsEmpty());
    1639             : 
    1640        1587 :     if(!bEmpty && rRegion.getB2DPolyPolygon() && 0 == rRegion.getB2DPolyPolygon()->count())
    1641             :     {
    1642             :         OSL_ENSURE(false, "Region with empty B2DPolyPolygon, should not be created (!)");
    1643           0 :         bEmpty = true;
    1644             :     }
    1645             : 
    1646        1587 :     if(!bEmpty && rRegion.getPolyPolygon() && 0 == rRegion.getPolyPolygon()->Count())
    1647             :     {
    1648             :         OSL_ENSURE(false, "Region with empty PolyPolygon, should not be created (!)");
    1649           0 :         bEmpty = true;
    1650             :     }
    1651             : 
    1652        1587 :     if(bEmpty)
    1653             :     {
    1654         237 :         aRegionType = REGION_EMPTY;
    1655             :     }
    1656        1350 :     else if(rRegion.IsNull())
    1657             :     {
    1658           0 :         aRegionType = REGION_NULL;
    1659             :     }
    1660        1350 :     else if(rRegion.getRegionBand() && rRegion.getRegionBand()->isSingleRectangle())
    1661             :     {
    1662        1307 :         aRegionType = REGION_RECTANGLE;
    1663             :     }
    1664             : 
    1665        1587 :     rOStrm.WriteUInt16( aRegionType );
    1666             : 
    1667             :     // get RegionBand
    1668        1587 :     const RegionBand* pRegionBand = rRegion.getRegionBand();
    1669             : 
    1670        1587 :     if(pRegionBand)
    1671             :     {
    1672        1307 :         pRegionBand->save(rOStrm);
    1673             :     }
    1674             :     else
    1675             :     {
    1676             :         // for compatibility, write an empty RegionBand (will only write
    1677             :         // the end marker STREAMENTRY_END, but this *is* needed)
    1678         280 :         const RegionBand aRegionBand;
    1679             : 
    1680         280 :         aRegionBand.save(rOStrm);
    1681             :     }
    1682             : 
    1683             :     // write polypolygon if available
    1684        1587 :     const bool bHasPolyPolygon(rRegion.HasPolyPolygonOrB2DPolyPolygon());
    1685        1587 :     rOStrm.WriteBool( bHasPolyPolygon );
    1686             : 
    1687        1587 :     if(bHasPolyPolygon)
    1688             :     {
    1689             :         // #i105373#
    1690          43 :         tools::PolyPolygon aNoCurvePolyPolygon;
    1691          43 :         rRegion.GetAsPolyPolygon().AdaptiveSubdivide(aNoCurvePolyPolygon);
    1692             : 
    1693          43 :         WritePolyPolygon( rOStrm, aNoCurvePolyPolygon );
    1694             :     }
    1695             : 
    1696        1587 :     return rOStrm;
    1697             : }
    1698             : 
    1699      702868 : void vcl::Region::GetRegionRectangles(RectangleVector& rTarget) const
    1700             : {
    1701             :     // clear returnvalues
    1702      702868 :     rTarget.clear();
    1703             : 
    1704             :     // ensure RegionBand existence
    1705      702868 :     const RegionBand* pRegionBand = GetAsRegionBand();
    1706             : 
    1707      702868 :     if(pRegionBand)
    1708             :     {
    1709      701462 :         pRegionBand->GetRegionRectangles(rTarget);
    1710             :     }
    1711      702868 : }
    1712             : 
    1713           0 : static inline bool ImplPolygonRectTest( const Polygon& rPoly, Rectangle* pRectOut = NULL )
    1714             : {
    1715           0 :     bool bIsRect = false;
    1716           0 :     const Point* pPoints = rPoly.GetConstPointAry();
    1717           0 :     sal_uInt16 nPoints = rPoly.GetSize();
    1718             : 
    1719           0 :     if( nPoints == 4 || (nPoints == 5 && pPoints[0] == pPoints[4]) )
    1720             :     {
    1721           0 :         long nX1 = pPoints[0].X(), nX2 = pPoints[2].X(), nY1 = pPoints[0].Y(), nY2 = pPoints[2].Y();
    1722             : 
    1723           0 :         if( ( (pPoints[1].X() == nX1 && pPoints[3].X() == nX2) && (pPoints[1].Y() == nY2 && pPoints[3].Y() == nY1) )
    1724           0 :          || ( (pPoints[1].X() == nX2 && pPoints[3].X() == nX1) && (pPoints[1].Y() == nY1 && pPoints[3].Y() == nY2) ) )
    1725             :         {
    1726           0 :             bIsRect = true;
    1727             : 
    1728           0 :             if( pRectOut )
    1729             :             {
    1730             :                 long nSwap;
    1731             : 
    1732           0 :                 if( nX2 < nX1 )
    1733             :                 {
    1734           0 :                     nSwap = nX2;
    1735           0 :                     nX2 = nX1;
    1736           0 :                     nX1 = nSwap;
    1737             :                 }
    1738             : 
    1739           0 :                 if( nY2 < nY1 )
    1740             :                 {
    1741           0 :                     nSwap = nY2;
    1742           0 :                     nY2 = nY1;
    1743           0 :                     nY1 = nSwap;
    1744             :                 }
    1745             : 
    1746           0 :                 if( nX2 != nX1 )
    1747             :                 {
    1748           0 :                     nX2--;
    1749             :                 }
    1750             : 
    1751           0 :                 if( nY2 != nY1 )
    1752             :                 {
    1753           0 :                     nY2--;
    1754             :                 }
    1755             : 
    1756           0 :                 pRectOut->Left()    = nX1;
    1757           0 :                 pRectOut->Right()   = nX2;
    1758           0 :                 pRectOut->Top()     = nY1;
    1759           0 :                 pRectOut->Bottom()  = nY2;
    1760             :             }
    1761             :         }
    1762             :     }
    1763             : 
    1764           0 :     return bIsRect;
    1765             : }
    1766             : 
    1767           0 : vcl::Region vcl::Region::GetRegionFromPolyPolygon( const tools::PolyPolygon& rPolyPoly )
    1768             : {
    1769             :     //return vcl::Region( rPolyPoly );
    1770             : 
    1771             :     // check if it's worth extracting the XOr'ing the Rectangles
    1772             :     // empiricism shows that break even between XOr'ing rectangles separately
    1773             :     // and ImplCreateRegionBandFromPolyPolygon is at half rectangles/half polygons
    1774           0 :     int nPolygonRects = 0, nPolygonPolygons = 0;
    1775           0 :     int nPolygons = rPolyPoly.Count();
    1776             : 
    1777           0 :     for( int i = 0; i < nPolygons; i++ )
    1778             :     {
    1779           0 :         const Polygon& rPoly = rPolyPoly[i];
    1780             : 
    1781           0 :         if( ImplPolygonRectTest( rPoly ) )
    1782             :         {
    1783           0 :             nPolygonRects++;
    1784             :         }
    1785             :         else
    1786             :         {
    1787           0 :             nPolygonPolygons++;
    1788             :         }
    1789             :     }
    1790             : 
    1791           0 :     if( nPolygonPolygons > nPolygonRects )
    1792             :     {
    1793           0 :         return vcl::Region( rPolyPoly );
    1794             :     }
    1795             : 
    1796           0 :     vcl::Region aResult;
    1797           0 :     Rectangle aRect;
    1798             : 
    1799           0 :     for( int i = 0; i < nPolygons; i++ )
    1800             :     {
    1801           0 :         const Polygon& rPoly = rPolyPoly[i];
    1802             : 
    1803           0 :         if( ImplPolygonRectTest( rPoly, &aRect ) )
    1804             :         {
    1805           0 :             aResult.XOr( aRect );
    1806             :         }
    1807             :         else
    1808             :         {
    1809           0 :             aResult.XOr( vcl::Region(rPoly) );
    1810             :         }
    1811             :     }
    1812             : 
    1813           0 :     return aResult;
    1814             : }
    1815             : 
    1816             : } /* namespace vcl */
    1817             : 
    1818             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11