LCOV - code coverage report
Current view: top level - vcl/source/gdi - region.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 436 713 61.2 %
Date: 2014-11-03 Functions: 36 43 83.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10