incubator-ooo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a..@apache.org
Subject svn commit: r1401294 [3/4] - in /incubator/ooo/trunk/main: canvas/source/vcl/ cppcanvas/source/mtfrenderer/ drawinglayer/source/primitive2d/ filter/source/graphicfilter/eps/ sd/source/ui/slidesorter/view/ svx/source/sdr/overlay/ svx/source/sdr/properti...
Date Tue, 23 Oct 2012 13:46:30 GMT
Modified: incubator/ooo/trunk/main/vcl/source/gdi/region.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/vcl/source/gdi/region.cxx?rev=1401294&r1=1401293&r2=1401294&view=diff
==============================================================================
--- incubator/ooo/trunk/main/vcl/source/gdi/region.cxx (original)
+++ incubator/ooo/trunk/main/vcl/source/gdi/region.cxx Tue Oct 23 13:46:28 2012
@@ -19,23 +19,14 @@
  * 
  *************************************************************/
 
-
-
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_vcl.hxx"
 
 #include <limits.h>
-
 #include <tools/vcompat.hxx>
 #include <tools/stream.hxx>
-#include <tools/debug.hxx>
-
 #include <vcl/region.hxx>
-#include <vcl/regband.hxx>
-#include <vcl/salbtype.hxx>
-
-#include <region.h>
-
+#include <regionband.hxx>
 #include <basegfx/matrix/b2dhommatrix.hxx>
 #include <basegfx/polygon/b2dpolypolygontools.hxx>
 #include <basegfx/polygon/b2dpolygontools.hxx>
@@ -44,2078 +35,1237 @@
 #include <basegfx/range/b2drange.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 
-// =======================================================================
-//
-// ImplRegionBand
-//
-// Die Klassen RegionBand/ImplRegionBand speichert Regionen in Form von
-// Rechtecken ab. Die Region ist in Y-Richtung in Baendern unterteilt, die
-// wiederum ein oder mehrere Rechtecke mit der Hoehe des Bandes enthalten.
-//
-// Leere Baender werden entfernt.
-//
-// Polygone und PolyPolygone werden ebenfalls in Rechtecke zerlegt und in
-// der Baendern abgelegt. Hierzu werden alle Punkte der einzelnen Polygone
-// mit dem Bresenham-Algorithmus berechnet und in die Baender eingetragen.
-// Nach der vollstaendigen Berechung aller Kanten werden die entsprechenden
-// Rechntecke berechnet
-
-// =======================================================================
-
-static ImplRegionBase aImplNullRegion( 0 );
-static ImplRegionBase aImplEmptyRegion( 0 );
-
-// =======================================================================
+//////////////////////////////////////////////////////////////////////////////
 
 DBG_NAME( Region )
 DBG_NAMEEX( Polygon )
 DBG_NAMEEX( PolyPolygon )
 
-namespace {
+//////////////////////////////////////////////////////////////////////////////
 
-/** Return <TRUE/> when the given polygon is rectiliner and oriented so that
-    all sides are either horizontal or vertical.
-*/
-bool ImplIsPolygonRectilinear (const PolyPolygon& rPolyPoly)
+namespace 
 {
-    // Iterate over all polygons.
-	const sal_uInt16 nPolyCount = rPolyPoly.Count();
-    for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
+    /** Return <TRUE/> when the given polygon is rectiliner and oriented so that
+        all sides are either horizontal or vertical.
+    */
+    bool ImplIsPolygonRectilinear (const PolyPolygon& rPolyPoly)
     {
-        const Polygon&	aPoly = rPolyPoly.GetObject(nPoly);
+        // Iterate over all polygons.
+        const sal_uInt16 nPolyCount = rPolyPoly.Count();
+        for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
+        {
+            const Polygon&	aPoly = rPolyPoly.GetObject(nPoly);
 
-        // Iterate over all edges of the current polygon.
-        const sal_uInt16 nSize = aPoly.GetSize();
+            // Iterate over all edges of the current polygon.
+            const sal_uInt16 nSize = aPoly.GetSize();
 
-        if (nSize < 2)
-            continue;
-        Point aPoint (aPoly.GetPoint(0));
-        const Point aLastPoint (aPoint);
-        for (sal_uInt16 nPoint = 1; nPoint < nSize; ++nPoint)
-        {
-            const Point aNextPoint (aPoly.GetPoint(nPoint));
-            // When there is at least one edge that is neither vertical nor
-            // horizontal then the entire polygon is not rectilinear (and
-            // oriented along primary axes.)
-            if (aPoint.X() != aNextPoint.X() && aPoint.Y() != aNextPoint.Y())
-                return false;
+            if (nSize < 2)
+                continue;
+            Point aPoint (aPoly.GetPoint(0));
+            const Point aLastPoint (aPoint);
+            for (sal_uInt16 nPoint = 1; nPoint < nSize; ++nPoint)
+            {
+                const Point aNextPoint (aPoly.GetPoint(nPoint));
+                // When there is at least one edge that is neither vertical nor
+                // horizontal then the entire polygon is not rectilinear (and
+                // oriented along primary axes.)
+                if (aPoint.X() != aNextPoint.X() && aPoint.Y() != aNextPoint.Y())
+                    return false;
 
-            aPoint = aNextPoint;
+                aPoint = aNextPoint;
+            }
+            // Compare closing edge.
+            if (aLastPoint.X() != aPoint.X() && aLastPoint.Y() != aPoint.Y())
+                return false;
         }
-        // Compare closing edge.
-        if (aLastPoint.X() != aPoint.X() && aLastPoint.Y() != aPoint.Y())
-            return false;
+        return true;
     }
-    return true;
-}
-
-
-
-/** This function is similar to the ImplRegion::InsertBands() method.
-    It creates a minimal set of missing bands so that the entire vertical
-    interval from nTop to nBottom is covered by bands.
-*/
-void ImplAddMissingBands (
-    ImplRegion* pImplRegion,
-    const long nTop,
-    const long nBottom)
-{
-    // Iterate over already existing bands and add missing bands atop the
-    // first and between two bands.
-    ImplRegionBand* pPreviousBand = NULL;
-    ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
-    long nCurrentTop (nTop);
-    while (pBand != NULL && nCurrentTop<nBottom)
-    {
-        if (nCurrentTop < pBand->mnYTop)
-        {
-            // Create new band above the current band.
-            ImplRegionBand* pAboveBand = new ImplRegionBand(
-                nCurrentTop,
-                ::std::min(nBottom,pBand->mnYTop-1));
-            pImplRegion->InsertBand(pPreviousBand, pAboveBand);
-        }
-
-        // Adapt the top of the interval to prevent overlapping bands.
-        nCurrentTop = ::std::max(nTop, pBand->mnYBottom+1);
-
-        // Advance to next band.
-        pPreviousBand = pBand;
-        pBand = pBand->mpNextBand;
-    }
-
-    // We still have to cover two cases:
-    // 1. The region does not yet contain any bands.
-    // 2. The intervall nTop->nBottom extends past the bottom most band.
-    if (nCurrentTop <= nBottom
-        && (pBand==NULL || nBottom>pBand->mnYBottom))
-    {
-        // When there is no previous band then the new one will be the
-        // first.  Otherwise the new band is inserted behind the last band.
-        pImplRegion->InsertBand(
-            pPreviousBand,
-            new ImplRegionBand(
-                nCurrentTop,
-                nBottom));
-    }
-}
-
 
-
-/** Convert a rectilinear polygon (that is oriented along the primary axes)
-    to a list of bands.  For this special form of polygon we can use an
-    optimization that prevents the creation of one band per y value.
-    However, it still is possible that some temporary bands are created that
-    later can be optimized away.
-    @param rPolyPolygon
-        A set of zero, one, or more polygons, nested or not, that are
-        converted into a list of bands.
-    @return
-        A new ImplRegion object is returned that contains the bands that
-        represent the given poly-polygon.
-*/
-ImplRegion* ImplRectilinearPolygonToBands (const PolyPolygon& rPolyPoly)
-{
-    OSL_ASSERT(ImplIsPolygonRectilinear (rPolyPoly));
-
-    // Create a new ImplRegion object as container of the bands.
-    ImplRegion* pImplRegion = new ImplRegion();
-    long nLineId = 0L;
-
-    // Iterate over all polygons.
-	const sal_uInt16 nPolyCount = rPolyPoly.Count();
-    for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
+    /** Convert a rectilinear polygon (that is oriented along the primary axes)
+        to a list of bands.  For this special form of polygon we can use an
+        optimization that prevents the creation of one band per y value.
+        However, it still is possible that some temporary bands are created that
+        later can be optimized away.
+        @param rPolyPolygon
+            A set of zero, one, or more polygons, nested or not, that are
+            converted into a list of bands.
+        @return
+            A new RegionBand object is returned that contains the bands that
+            represent the given poly-polygon.
+    */
+    RegionBand* ImplRectilinearPolygonToBands(const PolyPolygon& rPolyPoly)
     {
-        const Polygon&	aPoly = rPolyPoly.GetObject(nPoly);
+        OSL_ASSERT(ImplIsPolygonRectilinear (rPolyPoly));
 
-        // Iterate over all edges of the current polygon.
-        const sal_uInt16 nSize = aPoly.GetSize();
-        if (nSize < 2)
-            continue;
-        // Avoid fetching every point twice (each point is the start point
-        // of one and the end point of another edge.)
-        Point aStart (aPoly.GetPoint(0));
-        Point aEnd;
-        for (sal_uInt16 nPoint = 1; nPoint <= nSize; ++nPoint, aStart=aEnd)
-        {
-            // We take the implicit closing edge into account by mapping
-            // index nSize to 0.
-            aEnd = aPoly.GetPoint(nPoint%nSize);
-            if (aStart.Y() == aEnd.Y())
-            {
-                // Horizontal lines are ignored.
+        // Create a new RegionBand object as container of the bands.
+        RegionBand* pRegionBand = new RegionBand();
+        long nLineId = 0L;
+
+        // Iterate over all polygons.
+	    const sal_uInt16 nPolyCount = rPolyPoly.Count();
+        for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
+        {
+            const Polygon&	aPoly = rPolyPoly.GetObject(nPoly);
+
+            // Iterate over all edges of the current polygon.
+            const sal_uInt16 nSize = aPoly.GetSize();
+            if (nSize < 2)
                 continue;
-            }
+            // Avoid fetching every point twice (each point is the start point
+            // of one and the end point of another edge.)
+            Point aStart (aPoly.GetPoint(0));
+            Point aEnd;
+            for (sal_uInt16 nPoint = 1; nPoint <= nSize; ++nPoint, aStart=aEnd)
+            {
+                // We take the implicit closing edge into account by mapping
+                // index nSize to 0.
+                aEnd = aPoly.GetPoint(nPoint%nSize);
+                if (aStart.Y() == aEnd.Y())
+                {
+                    // Horizontal lines are ignored.
+                    continue;
+                }
 
-            // At this point the line has to be vertical.
-            OSL_ASSERT(aStart.X() == aEnd.X());
+                // At this point the line has to be vertical.
+                OSL_ASSERT(aStart.X() == aEnd.X());
 
-            // Sort y-coordinates to simplify the algorithm and store the
-            // direction seperately.  The direction is calculated as it is
-            // in other places (but seems to be the wrong way.)
-            const long nTop (::std::min(aStart.Y(), aEnd.Y()));
-            const long nBottom (::std::max(aStart.Y(), aEnd.Y()));
-            const LineType eLineType (aStart.Y() > aEnd.Y() ? LINE_DESCENDING : LINE_ASCENDING);
+                // Sort y-coordinates to simplify the algorithm and store the
+                // direction seperately.  The direction is calculated as it is
+                // in other places (but seems to be the wrong way.)
+                const long nTop (::std::min(aStart.Y(), aEnd.Y()));
+                const long nBottom (::std::max(aStart.Y(), aEnd.Y()));
+                const LineType eLineType (aStart.Y() > aEnd.Y() ? LINE_DESCENDING : LINE_ASCENDING);
         
-            // Make sure that the current line is covered by bands.
-            ImplAddMissingBands(pImplRegion, nTop,nBottom);
-
-            // Find top-most band that may contain nTop.
-            ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
-            while (pBand!=NULL && pBand->mnYBottom < nTop)
-                pBand = pBand->mpNextBand;
-            ImplRegionBand* pTopBand = pBand;
-            // If necessary split the band at nTop so that nTop is contained
-            // in the lower band.
-            if (pBand!=NULL
-                   // Prevent the current band from becoming 0 pixel high
-                && pBand->mnYTop<nTop
-                   // this allows the lowest pixel of the band to be split off
-                && pBand->mnYBottom>=nTop
-                   // do not split a band that is just one pixel high
-                && pBand->mnYTop<pBand->mnYBottom)
-            {
-                // Split the top band.
-                pTopBand = pBand->SplitBand(nTop);
-            }
+                // Make sure that the current line is covered by bands.
+                pRegionBand->ImplAddMissingBands(nTop,nBottom);
 
-            // Advance to band that may contain nBottom.
-            while (pBand!=NULL && pBand->mnYBottom < nBottom)
-                pBand = pBand->mpNextBand;
-            // The lowest band may have to be split at nBottom so that
-            // nBottom itself remains in the upper band.
-            if (pBand!=NULL
-                   // allow the current band becoming 1 pixel high
-                && pBand->mnYTop<=nBottom
-                   // prevent splitting off a band that is 0 pixel high
-                && pBand->mnYBottom>nBottom
-                   // do not split a band that is just one pixel high
-                && pBand->mnYTop<pBand->mnYBottom)
-            {
-                // Split the bottom band.
-                pBand->SplitBand(nBottom+1);
-            }
+                // Find top-most band that may contain nTop.
+                ImplRegionBand* pBand = pRegionBand->ImplGetFirstRegionBand();
+                while (pBand!=NULL && pBand->mnYBottom < nTop)
+                    pBand = pBand->mpNextBand;
+                ImplRegionBand* pTopBand = pBand;
+                // If necessary split the band at nTop so that nTop is contained
+                // in the lower band.
+                if (pBand!=NULL
+                       // Prevent the current band from becoming 0 pixel high
+                    && pBand->mnYTop<nTop
+                       // this allows the lowest pixel of the band to be split off
+                    && pBand->mnYBottom>=nTop
+                       // do not split a band that is just one pixel high
+                    && pBand->mnYTop<pBand->mnYBottom)
+                {
+                    // Split the top band.
+                    pTopBand = pBand->SplitBand(nTop);
+                }
 
-            // Note that we remember the top band (in pTopBand) but not the
-            // bottom band.  The later can be determined by comparing y
-            // coordinates.
+                // Advance to band that may contain nBottom.
+                while (pBand!=NULL && pBand->mnYBottom < nBottom)
+                    pBand = pBand->mpNextBand;
+                // The lowest band may have to be split at nBottom so that
+                // nBottom itself remains in the upper band.
+                if (pBand!=NULL
+                       // allow the current band becoming 1 pixel high
+                    && pBand->mnYTop<=nBottom
+                       // prevent splitting off a band that is 0 pixel high
+                    && pBand->mnYBottom>nBottom
+                       // do not split a band that is just one pixel high
+                    && pBand->mnYTop<pBand->mnYBottom)
+                {
+                    // Split the bottom band.
+                    pBand->SplitBand(nBottom+1);
+                }
 
-            // Add the x-value as point to all bands in the nTop->nBottom range.
-            for (pBand=pTopBand; pBand!=NULL&&pBand->mnYTop<=nBottom; pBand=pBand->mpNextBand)
-                pBand->InsertPoint(aStart.X(), nLineId++, sal_True, eLineType);
+                // Note that we remember the top band (in pTopBand) but not the
+                // bottom band.  The later can be determined by comparing y
+                // coordinates.
+
+                // Add the x-value as point to all bands in the nTop->nBottom range.
+                for (pBand=pTopBand; pBand!=NULL&&pBand->mnYTop<=nBottom; pBand=pBand->mpNextBand)
+                    pBand->InsertPoint(aStart.X(), nLineId++, true, eLineType);
+            }
         }
-    }
 
-    return pImplRegion;
-}
+        return pRegionBand;
+    }
 
+    /** Convert a general polygon (one for which ImplIsPolygonRectilinear()
+        returns <FALSE/>) to bands.
+    */
+    RegionBand* ImplGeneralPolygonToBands(const PolyPolygon& rPolyPoly, const Rectangle& rPolygonBoundingBox)
+    {
+        long nLineID = 0L;
 
+        // initialisation and creation of Bands
+        RegionBand* pRegionBand = new RegionBand();
+        pRegionBand->CreateBandRange(rPolygonBoundingBox.Top(), rPolygonBoundingBox.Bottom());
+            
+        // insert polygons
+	    const sal_uInt16 nPolyCount = rPolyPoly.Count();
 
+        for ( sal_uInt16 nPoly = 0; nPoly < nPolyCount; nPoly++ )
+        {
+            // get reference to current polygon
+            const Polygon&	aPoly = rPolyPoly.GetObject( nPoly );
+            const sal_uInt16	nSize = aPoly.GetSize();
 
-/** Convert a general polygon (one for which ImplIsPolygonRectilinear()
-    returns <FALSE/>) to bands.
-*/
-ImplRegion* ImplGeneralPolygonToBands (
-    const PolyPolygon& rPolyPoly,
-    const Rectangle& rPolygonBoundingBox)
-{
-    long nLineID = 0L;
+            // not enough points ( <= 2 )? -> nothing to do!
+            if ( nSize <= 2 )
+                continue;
 
-    // initialisation and creation of Bands
-    ImplRegion* pImplRegion = new ImplRegion();
-    pImplRegion->CreateBandRange( rPolygonBoundingBox.Top(), rPolygonBoundingBox.Bottom() );
-            
-    // insert polygons
-	const sal_uInt16 nPolyCount = rPolyPoly.Count();
-    for ( sal_uInt16 nPoly = 0; nPoly < nPolyCount; nPoly++ )
-    {
-        // get reference to current polygon
-        const Polygon&	aPoly = rPolyPoly.GetObject( nPoly );
-        const sal_uInt16	nSize = aPoly.GetSize();
+            // band the polygon
+            for ( sal_uInt16 nPoint = 1; nPoint < nSize; nPoint++ )
+            {
+                pRegionBand->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
+            }
 
-        // not enough points ( <= 2 )? -> nothing to do!
-        if ( nSize <= 2 )
-            continue;
+            // close polygon with line from first point to last point, if neccesary
+            const Point rLastPoint = aPoly.GetPoint(nSize-1);
+            const Point rFirstPoint = aPoly.GetPoint(0);
 
-        // band the polygon
-        for ( sal_uInt16 nPoint = 1; nPoint < nSize; nPoint++ )
-            pImplRegion->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
+            if ( rLastPoint != rFirstPoint )
+            {
+                pRegionBand->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
+            }
+        }
 
-        // close polygon with line from first point to last point, if neccesary
-        const Point rLastPoint = aPoly.GetPoint(nSize-1);
-        const Point rFirstPoint = aPoly.GetPoint(0);
-        if ( rLastPoint != rFirstPoint )
-            pImplRegion->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
+        return pRegionBand;
     }
+} // end of anonymous namespace
 
-    return pImplRegion;
-}
+//////////////////////////////////////////////////////////////////////////////
 
+bool Region::IsEmpty() const
+{
+    return !mbIsNull && !mpB2DPolyPolygon.get() && !mpPolyPolygon.get() && !mpRegionBand.get();
+}
 
-} // end of anonymous namespace
+bool Region::IsNull() const
+{
+    return mbIsNull;
+}
 
+RegionBand* ImplCreateRegionBandFromPolyPolygon(const PolyPolygon& rPolyPolygon)
+{
+    RegionBand* pRetval = 0;
 
-// -----------------------------------------------------------------------
+    if(rPolyPolygon.Count())
+    {
+        // ensure to subdivide when bezier segemnts are used, it's going to
+        // be expanded to rectangles
+        PolyPolygon aPolyPolygon;
 
-#ifdef DBG_UTIL
-const char* ImplDbgTestRegion( const void* pObj )
-{
-	Region* 	  pRegion = (Region*)pObj;
-	ImplRegion*   pImplRegion = pRegion->ImplGetImplRegion();
+        rPolyPolygon.AdaptiveSubdivide(aPolyPolygon);
 
-	if ( aImplNullRegion.mnRefCount )
-		return "Null-Region-RefCount modified";
-	if ( aImplNullRegion.mnRectCount )
-		return "Null-Region-RectCount modified";
-	if ( aImplNullRegion.mpPolyPoly )
-		return "Null-Region-PolyPoly modified";
-	if ( aImplEmptyRegion.mnRefCount )
-		return "Emptry-Region-RefCount modified";
-	if ( aImplEmptyRegion.mnRectCount )
-		return "Emptry-Region-RectCount modified";
-	if ( aImplEmptyRegion.mpPolyPoly )
-		return "Emptry-Region-PolyPoly modified";
+        if(aPolyPolygon.Count())
+        {
+            const Rectangle aRect(aPolyPolygon.GetBoundRect());
 
-	if ( (pImplRegion != &aImplEmptyRegion) && (pImplRegion != &aImplNullRegion) )
-	{
-		sal_uLong					nCount = 0;
-		const ImplRegionBand*	pBand = pImplRegion->ImplGetFirstRegionBand();
-		while ( pBand )
-		{
-			if ( pBand->mnYBottom < pBand->mnYTop )
-				return "YBottom < YTop";
-			if ( pBand->mpNextBand )
-			{
-				if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
-					return "overlapping bands in region";
-			}
-			if ( pBand->mbTouched > 1 )
-				return "Band-mbTouched overwrite";
-
-			ImplRegionBandSep* pSep = pBand->mpFirstSep;
-			while ( pSep )
-			{
-				if ( pSep->mnXRight < pSep->mnXLeft )
-					return "XLeft < XRight";
-				if ( pSep->mpNextSep )
-				{
-					if ( pSep->mnXRight >= pSep->mpNextSep->mnXLeft )
-						return "overlapping separations in region";
-				}
-				if ( pSep->mbRemoved > 1 )
-					return "Sep-mbRemoved overwrite";
-
-				nCount++;
-				pSep = pSep->mpNextSep;
-			}
+            if(!aRect.IsEmpty())
+            {
+                if(ImplIsPolygonRectilinear(aPolyPolygon))
+                {
+                    // For rectilinear polygons there is an optimized band conversion.
+                    pRetval = ImplRectilinearPolygonToBands(aPolyPolygon);
+                }
+                else
+                {
+                    pRetval = ImplGeneralPolygonToBands(aPolyPolygon, aRect);
+                }
 
-			pBand = pBand->mpNextBand;
-		}
+                // Convert points into seps.
+                if(pRetval)
+                {
+                    pRetval->processPoints();
 
-		if ( pImplRegion->mnRectCount != nCount )
-			return "mnRetCount is not valid";
-	}
+                    // Optimize list of bands.  Adjacent bands with identical lists
+                    // of seps are joined.
+                    if(!pRetval->OptimizeBandList())
+                    {
+                        delete pRetval;
+                        pRetval = 0;
+                    }
+                }
+            }
+        }
+    }
 
-	return NULL;
+    return pRetval;
 }
 
-void TraceBands (const ImplRegionBand* pFirstBand)
+PolyPolygon Region::ImplCreatePolyPolygonFromRegionBand() const
 {
-    int nBandIndex  (0);
-    const ImplRegionBand* pBand = pFirstBand;
-    while (pBand != NULL)
-    {
-        OSL_TRACE("            band %d  %d->%d : ", nBandIndex++,
-            pBand->mnYTop, pBand->mnYBottom);
+    PolyPolygon aRetval;
 
-        ImplRegionBandPoint* pPoint = pBand->mpFirstBandPoint;
-        while (pPoint != NULL)
-        {
-            OSL_TRACE(" %d ", pPoint->mnX);
-            pPoint = pPoint->mpNextBandPoint;
-        }
-        OSL_TRACE("  |  ");
+    if(getRegionBand())
+    {
+        RectangleVector aRectangles;
+        GetRegionRectangles(aRectangles);
 
-        ImplRegionBandSep* pSep = pBand->mpFirstSep;
-        while (pSep != NULL)
+        for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
         {
-            OSL_TRACE(" %d->%d ", pSep->mnXLeft, pSep->mnXRight);
-            pSep = pSep->mpNextSep;
+            aRetval.Insert(Polygon(*aRectIter));
         }
-        OSL_TRACE("\n");
-
-        pBand = pBand->mpNextBand;
     }
-}
-#endif
-
-// =======================================================================
+    else
+    {
+        OSL_ENSURE(false, "Called with no local RegionBand (!)");
+    }
 
-inline void Region::ImplPolyPolyRegionToBandRegion()
-{
-	if( mpImplRegion->mpPolyPoly || mpImplRegion->mpB2DPolyPoly )
-		ImplPolyPolyRegionToBandRegionFunc();
+    return aRetval;
 }
 
-// =======================================================================
-
-ImplRegionBase::ImplRegionBase( int nRefCount )
-:	mnRefCount( nRefCount )
-,	mnRectCount( 0 )
-,	mpPolyPoly( NULL )
-,	mpB2DPolyPoly( NULL )
-{}
+basegfx::B2DPolyPolygon Region::ImplCreateB2DPolyPolygonFromRegionBand() const
+{
+    PolyPolygon aPoly(ImplCreatePolyPolygonFromRegionBand());
 
-// ------------------------------------------------------------------------
+    return aPoly.getB2DPolyPolygon();
+}
 
-ImplRegion::ImplRegion()
+Region::Region(bool bIsNull)
+:   mpB2DPolyPolygon(),
+    mpPolyPolygon(),
+    mpRegionBand(),
+    mbIsNull(bIsNull)
 {
-	mpFirstBand 		= NULL;
-	mpLastCheckedBand	= NULL;
 }
 
-// ------------------------------------------------------------------------
-
-ImplRegion::ImplRegion( const PolyPolygon& rPolyPoly )
+Region::Region(const Rectangle& rRect)
+:   mpB2DPolyPolygon(),
+    mpPolyPolygon(),
+    mpRegionBand(),
+    mbIsNull(false)
 {
-	mpFirstBand 		= NULL;
-	mpLastCheckedBand	= NULL;
-	mpPolyPoly			= new PolyPolygon( rPolyPoly );
+    mpRegionBand.reset(rRect.IsEmpty() ? 0 : new RegionBand(rRect));
 }
 
-// ------------------------------------------------------------------------
-
-ImplRegion::ImplRegion( const basegfx::B2DPolyPolygon& rPolyPoly )
+Region::Region(const Polygon& rPolygon)
+:   mpB2DPolyPolygon(),
+    mpPolyPolygon(),
+    mpRegionBand(),
+    mbIsNull(false)
 {
-	mpFirstBand = NULL;
-	mpLastCheckedBand = NULL;
-	mpB2DPolyPoly = new basegfx::B2DPolyPolygon( rPolyPoly );
-}
+	DBG_CHKOBJ( &rPolygon, Polygon, NULL );
 
-// -----------------------------------------------------------------------
+    if(rPolygon.GetSize())
+    {
+    	ImplCreatePolyPolyRegion(rPolygon);
+    }
+}
 
-ImplRegion::ImplRegion( const ImplRegion& rImplRegion )
-:	ImplRegionBase()
+Region::Region(const PolyPolygon& rPolyPoly)
+:   mpB2DPolyPolygon(),
+    mpPolyPolygon(),
+    mpRegionBand(),
+    mbIsNull(false)
 {
-	mpFirstBand = NULL;
-	mpLastCheckedBand = NULL;
-	mnRectCount = rImplRegion.mnRectCount;
-
-	if ( rImplRegion.mpPolyPoly )
-		mpPolyPoly = new PolyPolygon( *rImplRegion.mpPolyPoly );
-	else if( rImplRegion.mpB2DPolyPoly )
-		mpB2DPolyPoly = new basegfx::B2DPolyPolygon( *rImplRegion.mpB2DPolyPoly );
-
-	// insert band(s) into the list
-	ImplRegionBand* pNewBand;
-	ImplRegionBand* pPrevBand = 0;
-	ImplRegionBand* pBand = rImplRegion.mpFirstBand;
-	while ( pBand )
-	{
-		pNewBand = new ImplRegionBand( *pBand );
-
-		// first element? -> set as first into the list
-		if ( pBand == rImplRegion.mpFirstBand )
-			mpFirstBand = pNewBand;
-		else
-			pPrevBand->mpNextBand = pNewBand;
+	DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
 
-		pPrevBand = pNewBand;
-		pBand = pBand->mpNextBand;
-	}
+    if(rPolyPoly.Count())
+    {
+    	ImplCreatePolyPolyRegion(rPolyPoly);
+    }
 }
 
-// -----------------------------------------------------------------------
-
-ImplRegion::~ImplRegion()
+Region::Region(const basegfx::B2DPolyPolygon& rPolyPoly)
+:   mpB2DPolyPolygon(),
+    mpPolyPolygon(),
+    mpRegionBand(),
+    mbIsNull(false)
 {
-	DBG_ASSERT( (this != &aImplEmptyRegion) && (this != &aImplNullRegion),
-				"ImplRegion::~ImplRegion() - Empty oder NULL-Region" );
+	DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
 
-	ImplRegionBand* pBand = mpFirstBand;
-	while ( pBand )
-	{
-		ImplRegionBand* pTempBand = pBand->mpNextBand;
-		delete pBand;
-		pBand = pTempBand;
-	}
+    if(rPolyPoly.count())
+    {
+    	ImplCreatePolyPolyRegion(rPolyPoly);
+    }
 }
 
-// -----------------------------------------------------------------------
-
-ImplRegionBase::~ImplRegionBase()
+Region::Region(const Region& rRegion)
+:   mpB2DPolyPolygon(rRegion.mpB2DPolyPolygon),
+    mpPolyPolygon(rRegion.mpPolyPolygon),
+    mpRegionBand(rRegion.mpRegionBand),
+    mbIsNull(rRegion.mbIsNull)
 {
-	delete mpPolyPoly;
-	delete mpB2DPolyPoly;
 }
 
-// -----------------------------------------------------------------------
-//
-// create complete range of bands in single steps
-
-void ImplRegion::CreateBandRange( long nYTop, long nYBottom )
+Region::~Region()
 {
-	// add top band
-	mpFirstBand = new ImplRegionBand( nYTop-1, nYTop-1 );
-
-	// begin first search from the first element
-	mpLastCheckedBand = mpFirstBand;
-
-	ImplRegionBand* pBand = mpFirstBand;
-	for ( int i = nYTop; i <= nYBottom+1; i++ )
-	{
-		// create new band
-		ImplRegionBand* pNewBand = new ImplRegionBand( i, i );
-		pBand->mpNextBand = pNewBand;
-		if ( pBand != mpFirstBand )
-			pNewBand->mpPrevBand = pBand;
-
-		pBand = pBand->mpNextBand;
-	}
 }
 
-// -----------------------------------------------------------------------
-
-sal_Bool ImplRegion::InsertLine( const Point& rStartPt, const Point& rEndPt,
-							 long nLineId )
+void Region::ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly )
 {
-	long nX, nY;
-
-	// lines consisting of a single point do not interest here
-	if ( rStartPt == rEndPt )
-		return sal_True;
+	const sal_uInt16 nPolyCount = rPolyPoly.Count();
 
-	LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
-	if ( rStartPt.X() == rEndPt.X() )
+    if(nPolyCount)
 	{
-		// vertical line
-		const long nEndY = rEndPt.Y();
-
-		nX = rStartPt.X();
-		nY = rStartPt.Y();
+		// polypolygon empty? -> empty region
+		const Rectangle aRect(rPolyPoly.GetBoundRect());
 
-		if( nEndY > nY )
-		{
-			for ( ; nY <= nEndY; nY++ )
-			{
-				Point aNewPoint( nX, nY );
-				InsertPoint( aNewPoint, nLineId,
-							 (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
-							 eLineType );
-			}
-		}
-		else
+		if(!aRect.IsEmpty())
 		{
-			for ( ; nY >= nEndY; nY-- )
-			{
-				Point aNewPoint( nX, nY );
-				InsertPoint( aNewPoint, nLineId,
-							 (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
-							 eLineType );
-			}
-		}
-	}
-	else if ( rStartPt.Y() != rEndPt.Y() )
-	{
-		const long	nDX = labs( rEndPt.X() - rStartPt.X() );
-		const long	nDY = labs( rEndPt.Y() - rStartPt.Y() );
-		const long	nStartX = rStartPt.X();
-		const long	nStartY = rStartPt.Y();
-		const long	nEndX = rEndPt.X();
-		const long	nEndY = rEndPt.Y();
-		const long	nXInc = ( nStartX < nEndX ) ? 1L : -1L;
-		const long	nYInc = ( nStartY < nEndY ) ? 1L : -1L;
+			// width OR height == 1 ? => Rectangular region
+			if((1 == aRect.GetWidth()) || (1 == aRect.GetHeight()) || rPolyPoly.IsRect())
+            {
+                mpRegionBand.reset(new RegionBand(aRect));
+            }
+			else
+            {
+                mpPolyPolygon.reset(new PolyPolygon(rPolyPoly));
+            }
 
-		if ( nDX >= nDY )
-		{
-			const long	nDYX = ( nDY - nDX ) << 1;
-			const long	nDY2 = nDY << 1;
-			long		nD = nDY2 - nDX;
-
-			for ( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
-			{
-				InsertPoint( Point( nX, nY ), nLineId, nStartX == nX, eLineType );
-
-				if ( nD < 0L )
-					nD += nDY2;
-				else
-					nD += nDYX, nY += nYInc;
-			}
-		}
-		else
-		{
-			const long	nDYX = ( nDX - nDY ) << 1;
-			const long	nDY2 = nDX << 1;
-			long		nD = nDY2 - nDY;
-
-			for ( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
-			{
-				InsertPoint( Point( nX, nY ), nLineId, nStartY == nY, eLineType );
-
-				if ( nD < 0L )
-					nD += nDY2;
-				else
-					nD += nDYX, nX += nXInc;
-			}
+            mbIsNull = false;
 		}
-
-		// last point
-		InsertPoint( Point( nEndX, nEndY ), nLineId, sal_True, eLineType );
 	}
-
-	return sal_True;
 }
 
-// -----------------------------------------------------------------------
-//
-// search for appropriate place for the new point
-
-sal_Bool ImplRegion::InsertPoint( const Point &rPoint, long nLineID,
-							  sal_Bool bEndPoint, LineType eLineType )
+void Region::ImplCreatePolyPolyRegion( const basegfx::B2DPolyPolygon& rPolyPoly )
 {
-	DBG_ASSERT( mpFirstBand != NULL, "ImplRegion::InsertPoint - no bands available!" );
-
-	if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
-	{
-		mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
-		return sal_True;
-	}
-
-	if ( rPoint.Y() > mpLastCheckedBand->mnYTop )
-	{
-		// Search ascending
-		while ( mpLastCheckedBand )
-		{
-			// Insert point if possible
-			if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
-			{
-				mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
-				return sal_True;
-			}
-
-			mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
-		}
+    if(rPolyPoly.count() && !rPolyPoly.getB2DRange().isEmpty())
+    {
+        mpB2DPolyPolygon.reset(new basegfx::B2DPolyPolygon(rPolyPoly));
+        mbIsNull = false;
+    }
+}
 
-		DBG_ERROR( "ImplRegion::InsertPoint reached the end of the list!" );
-	}
-	else
-	{
-		// Search descending
-		while ( mpLastCheckedBand )
-		{
-			// Insert point if possible
-			if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
-			{
-				mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
-				return sal_True;
-			}
+void Region::Move( long nHorzMove, long nVertMove )
+{
+	if(IsNull() || IsEmpty())
+    {
+        // empty or null need no move
+		return;
+    }
 
-			mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
-		}
+    if(!nHorzMove && !nVertMove)
+    {
+        // no move defined
+        return;
+    }
 
-		DBG_ERROR( "ImplRegion::InsertPoint reached the beginning of the list!" );
-	}
+    if(getB2DPolyPolygon())
+    {
+        basegfx::B2DPolyPolygon aPoly(*getB2DPolyPolygon());
 
-	DBG_ERROR( "ImplRegion::InsertPoint point not inserted!" );
+        aPoly.transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
+        mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
+        mpPolyPolygon.reset();
+        mpRegionBand.reset();
+    }
+    else if(getPolyPolygon())
+    {
+        PolyPolygon aPoly(*getPolyPolygon());
 
-	// reinitialize pointer (should never be reached!)
-	mpLastCheckedBand = mpFirstBand;
+    	aPoly.Move(nHorzMove, nVertMove);
+        mpB2DPolyPolygon.reset();
+        mpPolyPolygon.reset(aPoly.Count() ? new PolyPolygon(aPoly) : 0);
+        mpRegionBand.reset();
+    }
+    else if(getRegionBand())
+    {
+        RegionBand* pNew = new RegionBand(*getRegionBand());
 
-	return sal_False;
+        pNew->Move(nHorzMove, nVertMove);
+        mpB2DPolyPolygon.reset();
+        mpPolyPolygon.reset();
+        mpRegionBand.reset(pNew);
+    }
+    else
+    {
+        OSL_ENSURE(false, "Region::Move error: impossible combination (!)");
+    }
 }
 
-// -----------------------------------------------------------------------
-//
-// search for appropriate places for the new bands
-
-void ImplRegion::InsertBands( long nTop, long nBottom )
+void Region::Scale( double fScaleX, double fScaleY )
 {
-	// region empty? -> set rectagle as first entry!
-	if ( !mpFirstBand )
-	{
-		// add band with boundaries of the rectangle
-		mpFirstBand = new ImplRegionBand( nTop, nBottom );
+	if(IsNull() || IsEmpty())
+    {
+        // empty or null need no scale
 		return;
-	}
+    }
 
-	// find/insert bands for the boundaries of the rectangle
-	sal_Bool bTopBoundaryInserted = sal_False;
-	sal_Bool bTop2BoundaryInserted = sal_False;
-	sal_Bool bBottomBoundaryInserted = sal_False;
-
-	// special case: top boundary is above the first band
-	ImplRegionBand* pNewBand;
-	if ( nTop < mpFirstBand->mnYTop )
-	{
-		// create new band above the first in the list
-		pNewBand = new ImplRegionBand( nTop, mpFirstBand->mnYTop );
-		if ( nBottom < mpFirstBand->mnYTop )
-			pNewBand->mnYBottom = nBottom;
-
-		// insert band into the list
-		pNewBand->mpNextBand = mpFirstBand;
-		mpFirstBand = pNewBand;
+    if(basegfx::fTools::equalZero(fScaleX) && basegfx::fTools::equalZero(fScaleY))
+    {
+        // no scale defined
+        return;
+    }
 
-		bTopBoundaryInserted = sal_True;
-	}
+    if(getB2DPolyPolygon())
+    {
+        basegfx::B2DPolyPolygon aPoly(*getB2DPolyPolygon());
 
-	// insert band(s) into the list
-	ImplRegionBand* pBand = mpFirstBand;
-	while ( pBand )
-	{
-		// Insert Bands if possible
-		if ( !bTopBoundaryInserted )
-			bTopBoundaryInserted = InsertSingleBand( pBand, nTop - 1 );
-
-		if ( !bTop2BoundaryInserted )
-			bTop2BoundaryInserted = InsertSingleBand( pBand, nTop );
-
-		if ( !bBottomBoundaryInserted && (nTop != nBottom) )
-			bBottomBoundaryInserted = InsertSingleBand( pBand, nBottom );
-
-		// both boundaries inserted? -> nothing more to do
-		if ( bTopBoundaryInserted && bTop2BoundaryInserted && bBottomBoundaryInserted )
-			break;
+        aPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
+        mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
+        mpPolyPolygon.reset();
+        mpRegionBand.reset();
+    }
+    else if(getPolyPolygon())
+    {
+        PolyPolygon aPoly(*getPolyPolygon());
 
-		// insert bands between two bands if neccessary
-		if ( pBand->mpNextBand )
-		{
-			if ( (pBand->mnYBottom + 1) < pBand->mpNextBand->mnYTop )
-			{
-				// copy band with list and set new boundary
-				pNewBand = new ImplRegionBand( pBand->mnYBottom+1,
-											   pBand->mpNextBand->mnYTop-1 );
-
-				// insert band into the list
-				pNewBand->mpNextBand = pBand->mpNextBand;
-				pBand->mpNextBand = pNewBand;
-			}
-		}
+        aPoly.Scale(fScaleX, fScaleY);
+        mpB2DPolyPolygon.reset();
+        mpPolyPolygon.reset(aPoly.Count() ? new PolyPolygon(aPoly) : 0);
+        mpRegionBand.reset();
+    }
+    else if(getRegionBand())
+    {
+        RegionBand* pNew = new RegionBand(*getRegionBand());
 
-		pBand = pBand->mpNextBand;
-	}
+        pNew->Scale(fScaleX, fScaleY);
+        mpB2DPolyPolygon.reset();
+        mpPolyPolygon.reset();
+        mpRegionBand.reset(pNew);
+    }
+    else
+    {
+        OSL_ENSURE(false, "Region::Scale error: impossible combination (!)");
+    }
 }
 
-// -----------------------------------------------------------------------
-//
-// create new band and insert it into the list
-
-sal_Bool ImplRegion::InsertSingleBand( ImplRegionBand* pBand,
-								   long nYBandPosition )
+bool Region::Union( const Rectangle& rRect )
 {
-	// boundary already included in band with height 1? -> nothing to do!
-	if ( (pBand->mnYTop == pBand->mnYBottom) &&
-		 (nYBandPosition == pBand->mnYTop) )
-		return sal_True;
-
-	// insert single height band on top?
-	ImplRegionBand* pNewBand;
-	if ( nYBandPosition == pBand->mnYTop )
-	{
-		// copy band with list and set new boundary
-		pNewBand = new ImplRegionBand( *pBand );
-		pNewBand->mnYTop = nYBandPosition+1;
-
-		// insert band into the list
-		pNewBand->mpNextBand = pBand->mpNextBand;
-		pBand->mnYBottom = nYBandPosition;
-		pBand->mpNextBand = pNewBand;
+    if(rRect.IsEmpty())
+    {
+        // empty rectangle will not expand the existing union, nothing to do
+        return true;
+    }
 
-		return sal_True;
-	}
+    if(IsEmpty())
+    {
+        // no local data, the union will be equal to source. Create using rectangle
+        *this = rRect;
+        return true;
+    }
 
-	// top of new rectangle within the current band? -> insert new band and copy data
-	if ( (nYBandPosition > pBand->mnYTop) &&
-		 (nYBandPosition < pBand->mnYBottom) )
-	{
-		// copy band with list and set new boundary
-		pNewBand = new ImplRegionBand( *pBand );
-		pNewBand->mnYTop = nYBandPosition;
-
-		// insert band into the list
-		pNewBand->mpNextBand = pBand->mpNextBand;
-		pBand->mnYBottom = nYBandPosition;
-		pBand->mpNextBand = pNewBand;
-
-		// copy band with list and set new boundary
-		pNewBand = new ImplRegionBand( *pBand );
-		pNewBand->mnYTop = nYBandPosition;
-
-		// insert band into the list
-		pBand->mpNextBand->mnYTop = nYBandPosition+1;
-
-		pNewBand->mpNextBand = pBand->mpNextBand;
-		pBand->mnYBottom = nYBandPosition - 1;
-		pBand->mpNextBand = pNewBand;
+    if(HasPolyPolygonOrB2DPolyPolygon())
+    {
+        // get this B2DPolyPolygon, solve on polygon base
+        basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
 
-		return sal_True;
-	}
+        aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
+        
+        if(!aThisPolyPoly.count())
+        {
+            // no local polygon, use the rectangle as new region
+            *this = rRect;
+        }
+        else
+        {
+            // get the other B2DPolyPolygon and use logical Or-Operation
+            const basegfx::B2DPolygon aRectPoly( 
+                basegfx::tools::createPolygonFromRect( 
+                    basegfx::B2DRectangle(
+                        rRect.Left(), 
+                        rRect.Top(), 
+                        rRect.Right(), 
+                        rRect.Bottom())));
+            const basegfx::B2DPolyPolygon aClip(
+                basegfx::tools::solvePolygonOperationOr(
+                    aThisPolyPoly, 
+                    basegfx::B2DPolyPolygon(aRectPoly)));
+            *this = Region(aClip);
+        }
 
-	// create new band behind the current in the list
-	if ( !pBand->mpNextBand )
-	{
-		if ( nYBandPosition == pBand->mnYBottom )
-		{
-			// copy band with list and set new boundary
-			pNewBand = new ImplRegionBand( *pBand );
-			pNewBand->mnYTop = pBand->mnYBottom;
-			pNewBand->mnYBottom = nYBandPosition;
-
-			pBand->mnYBottom = nYBandPosition-1;
-
-			// append band to the list
-			pBand->mpNextBand = pNewBand;
-			return sal_True;
-		}
+        return true;
+    }
 
-		if ( nYBandPosition > pBand->mnYBottom )
-		{
-			// create new band
-			pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
+    // only region band mode possibility left here or null/empty
+    const RegionBand* pCurrent = getRegionBand();
 
-			// append band to the list
-			pBand->mpNextBand = pNewBand;
-			return sal_True;
-		}
-	}
+    if(!pCurrent)
+    {
+        // no region band, create using the rectangle
+        *this = rRect;
+        return true;
+    }
 
-	return sal_False;
-}
+    RegionBand* pNew = new RegionBand(*pCurrent);
+        
+    // get justified rectangle
+    const long nLeft(std::min(rRect.Left(), rRect.Right()));
+    const long nTop(std::min(rRect.Top(), rRect.Bottom()));
+    const long nRight(std::max(rRect.Left(), rRect.Right()));
+    const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
 
-// ------------------------------------------------------------------------
+    // insert bands if the boundaries are not allready in the list
+    pNew->InsertBands(nTop, nBottom);
 
-void ImplRegion::InsertBand (ImplRegionBand* pPreviousBand, ImplRegionBand* pBandToInsert)
-{
-    OSL_ASSERT(pBandToInsert!=NULL);
+    // process union
+    pNew->Union(nLeft, nTop, nRight, nBottom);
 
-    if (pPreviousBand == NULL)
+    // cleanup
+    if(!pNew->OptimizeBandList())
     {
-        // Insert band before all others.
-        if (mpFirstBand != NULL)
-            mpFirstBand->mpPrevBand = pBandToInsert;
-        pBandToInsert->mpNextBand = mpFirstBand;
-        mpFirstBand = pBandToInsert;
+        delete pNew;
+        pNew = 0;
     }
-    else
-    {
-        // Insert band directly after pPreviousBand.
-        pBandToInsert->mpNextBand = pPreviousBand->mpNextBand;
-        pPreviousBand->mpNextBand = pBandToInsert;
-        pBandToInsert->mpPrevBand = pPreviousBand;
-    }
-}
 
-// ------------------------------------------------------------------------
+    mpRegionBand.reset(pNew);
+    return true;
+}
 
-void ImplRegion::Union( long nLeft, long nTop, long nRight, long nBottom )
+bool Region::Intersect( const Rectangle& rRect )
 {
-	DBG_ASSERT( nLeft <= nRight, "ImplRegion::Union() - nLeft > nRight" );
-	DBG_ASSERT( nTop <= nBottom, "ImplRegion::Union() - nTop > nBottom" );
-
-	// process union
-	ImplRegionBand* pBand = mpFirstBand;
-	while ( pBand )
+	if ( rRect.IsEmpty() )
 	{
-		if ( pBand->mnYTop >= nTop )
-		{
-			if ( pBand->mnYBottom <= nBottom )
-				pBand->Union( nLeft, nRight );
-			else
-			{
-#ifdef DBG_UTIL
-				long nCurY = pBand->mnYBottom;
-				pBand = pBand->mpNextBand;
-				while ( pBand )
-				{
-					if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
-					{
-						DBG_ERROR( "ImplRegion::Union() - Bands not sorted!" );
-					}
-					pBand = pBand->mpNextBand;
-				}
-#endif
-				break;
-			}
-		}
-
-		pBand = pBand->mpNextBand;
-	}
-}
-
-// -----------------------------------------------------------------------
-
-void ImplRegion::Exclude( long nLeft, long nTop, long nRight, long nBottom )
-{
-	DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
-	DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
-
-	// process exclude
-	ImplRegionBand* pBand = mpFirstBand;
-	while ( pBand )
-	{
-		if ( pBand->mnYTop >= nTop )
-		{
-			if ( pBand->mnYBottom <= nBottom )
-				pBand->Exclude( nLeft, nRight );
-			else
-			{
-#ifdef DBG_UTIL
-				long nCurY = pBand->mnYBottom;
-				pBand = pBand->mpNextBand;
-				while ( pBand )
-				{
-					if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
-					{
-						DBG_ERROR( "ImplRegion::Exclude() - Bands not sorted!" );
-					}
-					pBand = pBand->mpNextBand;
-				}
-#endif
-				break;
-			}
-		}
-
-		pBand = pBand->mpNextBand;
-	}
-}
-
-// -----------------------------------------------------------------------
-
-void ImplRegion::XOr( long nLeft, long nTop, long nRight, long nBottom )
-{
-	DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
-	DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
-
-	// process xor
-	ImplRegionBand* pBand = mpFirstBand;
-	while ( pBand )
-	{
-		if ( pBand->mnYTop >= nTop )
-		{
-			if ( pBand->mnYBottom <= nBottom )
-				pBand->XOr( nLeft, nRight );
-			else
-			{
-#ifdef DBG_UTIL
-				long nCurY = pBand->mnYBottom;
-				pBand = pBand->mpNextBand;
-				while ( pBand )
-				{
-					if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
-					{
-						DBG_ERROR( "ImplRegion::XOr() - Bands not sorted!" );
-					}
-					pBand = pBand->mpNextBand;
-				}
-#endif
-				break;
-			}
-		}
-
-		pBand = pBand->mpNextBand;
-	}
-}
-
-// -----------------------------------------------------------------------
-//
-// remove empty bands
-
-sal_Bool ImplRegion::OptimizeBandList()
-{
-	DBG_ASSERT( (this != &aImplNullRegion) && (this != &aImplEmptyRegion),
-				"ImplRegion::OptimizeBandList() - Empty oder NULL-Region" );
-
-	mnRectCount = 0;
-
-	ImplRegionBand* pPrevBand = 0;
-	ImplRegionBand* pBand = mpFirstBand;
-	while ( pBand )
-	{
-		const sal_Bool bBTEqual = pBand->mpNextBand &&
-							  (pBand->mnYBottom == pBand->mpNextBand->mnYTop);
-
-		// no separation? -> remove!
-		if ( pBand->IsEmpty() || (bBTEqual && (pBand->mnYBottom == pBand->mnYTop)) )
-		{
-			// save pointer
-			ImplRegionBand* pOldBand = pBand;
-
-			// previous element of the list
-			if ( pBand == mpFirstBand )
-				mpFirstBand = pBand->mpNextBand;
-			else
-				pPrevBand->mpNextBand = pBand->mpNextBand;
-
-			pBand = pBand->mpNextBand;
-			delete pOldBand;
-		}
-		else
-		{
-			// fixup
-			if ( bBTEqual )
-				pBand->mnYBottom = pBand->mpNextBand->mnYTop-1;
-
-			// this and next band with equal separations? -> combine!
-			if ( pBand->mpNextBand &&
-				 ((pBand->mnYBottom+1) == pBand->mpNextBand->mnYTop) &&
-				 (*pBand == *pBand->mpNextBand) )
-			{
-				// expand current height
-				pBand->mnYBottom = pBand->mpNextBand->mnYBottom;
-
-				// remove next band from list
-				ImplRegionBand* pDeletedBand = pBand->mpNextBand;
-				pBand->mpNextBand = pDeletedBand->mpNextBand;
-				delete pDeletedBand;
-
-				// check band again!
-			}
-			else
-			{
-				// count rectangles within band
-				ImplRegionBandSep* pSep = pBand->mpFirstSep;
-				while ( pSep )
-				{
-					mnRectCount++;
-					pSep = pSep->mpNextSep;
-				}
-
-				pPrevBand = pBand;
-				pBand = pBand->mpNextBand;
-			}
-		}
-	}
-
-#ifdef DBG_UTIL
-	pBand = mpFirstBand;
-	while ( pBand )
-	{
-		DBG_ASSERT( pBand->mpFirstSep != NULL,
-					"Exiting ImplRegion::OptimizeBandList(): empty band in region!" );
-
-		if ( pBand->mnYBottom < pBand->mnYTop )
-			DBG_ERROR( "ImplRegion::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
-
-		if ( pBand->mpNextBand )
-		{
-			if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
-				DBG_ERROR( "ImplRegion::OptimizeBandList(): overlapping bands in region!" );
-		}
-
-		pBand = pBand->mpNextBand;
+    	// empty rectangle will create empty region
+        SetEmpty();
+		return true;
 	}
-#endif
-
-	return (mnRectCount != 0);
-}
-
-// =======================================================================
-
-void Region::ImplCopyData()
-{
-	mpImplRegion->mnRefCount--;
-	mpImplRegion = new ImplRegion( *mpImplRegion );
-}
-
-// =======================================================================
-
-Region::Region()
-{
-	DBG_CTOR( Region, ImplDbgTestRegion );
-
-	mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-}
 
-// -----------------------------------------------------------------------
-
-Region::Region( RegionType eType )
-{
-	DBG_CTOR( Region, ImplDbgTestRegion );
-	DBG_ASSERT( (eType == REGION_NULL) || (eType == REGION_EMPTY),
-				"Region( RegionType ) - RegionType != EMPTY/NULL" );
-
-	if ( eType == REGION_NULL )
-		mpImplRegion = (ImplRegion*)(&aImplNullRegion);
-	else
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-}
-
-// -----------------------------------------------------------------------
-
-Region::Region( const Rectangle& rRect )
-{
-	DBG_CTOR( Region, ImplDbgTestRegion );
-
-	ImplCreateRectRegion( rRect );
-}
-
-// -----------------------------------------------------------------------
-
-Region::Region( const Polygon& rPolygon )
-{
-	DBG_CTOR( Region, ImplDbgTestRegion );
-	DBG_CHKOBJ( &rPolygon, Polygon, NULL );
+    if(IsNull())
+    {
+        // null region (everything) intersect with rect will give rect
+        *this = rRect;
+        return true;
+    }
 
-	ImplCreatePolyPolyRegion( rPolygon );
-}
+    if(IsEmpty())
+    {
+        // no content, cannot get more empty
+        return true;
+    }
 
-// -----------------------------------------------------------------------
+    if(HasPolyPolygonOrB2DPolyPolygon())
+    {
+        // if polygon data prefer double precision, the other will be lost (if buffered)
+        if(getB2DPolyPolygon())
+        {
+            const basegfx::B2DPolyPolygon aPoly(
+                basegfx::tools::clipPolyPolygonOnRange(
+                    *getB2DPolyPolygon(),
+                    basegfx::B2DRange( 
+                        rRect.Left(), 
+                        rRect.Top(),
+                        rRect.Right() + 1, 
+                        rRect.Bottom() + 1),
+                    true, 
+                    false));
+
+            mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
+            mpPolyPolygon.reset();
+            mpRegionBand.reset();
+        }
+        else // if(getPolyPolygon())
+        {
+            PolyPolygon aPoly(*getPolyPolygon());
 
-Region::Region( const PolyPolygon& rPolyPoly )
-{
-	DBG_CTOR( Region, ImplDbgTestRegion );
-	DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
+            // use the PolyPolygon::Clip method for rectangles, this is
+            // fairly simple (does not even use GPC) and saves us from
+            // unnecessary banding
+            aPoly.Clip(rRect);
+
+            mpB2DPolyPolygon.reset();
+            mpPolyPolygon.reset(aPoly.Count() ? new PolyPolygon(aPoly) : 0);
+            mpRegionBand.reset();
+        }
 
-	ImplCreatePolyPolyRegion( rPolyPoly );
-}
+        return true;
+    }
 
-// -----------------------------------------------------------------------
+    // only region band mode possibility left here or null/empty
+    const RegionBand* pCurrent = getRegionBand();
 
-Region::Region( const basegfx::B2DPolyPolygon& rPolyPoly )
-{
-	DBG_CTOR( Region, ImplDbgTestRegion );
-	DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
+    if(!pCurrent)
+    {
+        // region is empty -> nothing to do!
+        return true;
+    }
 
-	ImplCreatePolyPolyRegion( rPolyPoly );
-}
+    RegionBand* pNew = new RegionBand(*pCurrent);
 
-// -----------------------------------------------------------------------
+    // get justified rectangle
+    const long nLeft(std::min(rRect.Left(), rRect.Right()));
+    const long nTop(std::min(rRect.Top(), rRect.Bottom()));
+    const long nRight(std::max(rRect.Left(), rRect.Right()));
+    const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
 
-Region::Region( const Region& rRegion )
-{
-	DBG_CTOR( Region, ImplDbgTestRegion );
-	DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
-	DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
-
-	// copy pointer to instance of implementation
-	mpImplRegion = rRegion.mpImplRegion;
-	if ( mpImplRegion->mnRefCount )
-		mpImplRegion->mnRefCount++;
-}
+    // insert bands if the boundaries are not allready in the list
+    pNew->InsertBands(nTop, nBottom);
 
-// -----------------------------------------------------------------------
+    // process intersect
+    pNew->Intersect(nLeft, nTop, nRight, nBottom);
 
-Region::~Region()
-{
-	DBG_DTOR( Region, ImplDbgTestRegion );
+    // cleanup
+    if(!pNew->OptimizeBandList())
+    {
+        delete pNew;
+        pNew = 0;
+    }
 
-	// statische Object haben RefCount von 0
-	if ( mpImplRegion->mnRefCount )
-	{
-		if ( mpImplRegion->mnRefCount > 1 )
-			mpImplRegion->mnRefCount--;
-		else
-			delete mpImplRegion;
-	}
+    mpRegionBand.reset(pNew);
+    return true;
 }
 
-// -----------------------------------------------------------------------
-
-void Region::ImplCreateRectRegion( const Rectangle& rRect )
+bool Region::Exclude( const Rectangle& rRect )
 {
 	if ( rRect.IsEmpty() )
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	else
-	{
-		// get justified rectangle
-		long nTop		= Min( rRect.Top(), rRect.Bottom() );
-		long nBottom	= Max( rRect.Top(), rRect.Bottom() );
-		long nLeft		= Min( rRect.Left(), rRect.Right() );
-		long nRight 	= Max( rRect.Left(), rRect.Right() );
-
-		// create instance of implementation class
-		mpImplRegion = new ImplRegion();
-
-		// add band with boundaries of the rectangle
-		mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
-
-		// Set left and right boundaries of the band
-		mpImplRegion->mpFirstBand->Union( nLeft, nRight );
-		mpImplRegion->mnRectCount = 1;
-	}
-}
-
-// -----------------------------------------------------------------------
-
-void Region::ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly )
-{
-	const sal_uInt16 nPolyCount = rPolyPoly.Count();
-	if ( nPolyCount )
-	{
-		// polypolygon empty? -> empty region
-		const Rectangle aRect( rPolyPoly.GetBoundRect() );
-
-		if ( !aRect.IsEmpty() )
-		{
-			// width OR height == 1 ? => Rectangular region
-			if ( (aRect.GetWidth() == 1)
-                || (aRect.GetHeight() == 1)
-                || rPolyPoly.IsRect() )
-            {
-				ImplCreateRectRegion( aRect );
-            }
-			else
-				mpImplRegion = new ImplRegion( rPolyPoly );
-		}
-		else
-			mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	}
-	else
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-}
-
-// -----------------------------------------------------------------------
-
-void Region::ImplCreatePolyPolyRegion( const basegfx::B2DPolyPolygon& rPolyPoly )
-{
-    if (rPolyPoly.count()==0 || rPolyPoly.getB2DRange().isEmpty())
-        mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-    else
-        mpImplRegion = new ImplRegion( rPolyPoly );
-}
-
-// -----------------------------------------------------------------------
-
-void Region::ImplPolyPolyRegionToBandRegionFunc()
-{
-    // ensure to subdivide when bezier segemnts are used, it's going to
-    // be expanded to rectangles
-	PolyPolygon aPolyPoly;
-    GetPolyPolygon().AdaptiveSubdivide(aPolyPoly);
-
-	if ( mpImplRegion->mnRefCount > 1 )
-		mpImplRegion->mnRefCount--;
-	else
-		delete mpImplRegion;
-
-	if ( aPolyPoly.Count() )
-	{
-		// polypolygon empty? -> empty region
-		const Rectangle aRect( aPolyPoly.GetBoundRect() );
-
-		if ( !aRect.IsEmpty() )
-		{
-            if (ImplIsPolygonRectilinear(aPolyPoly))
-            {
-                // For rectilinear polygons there is an optimized band conversion.
-                mpImplRegion = ImplRectilinearPolygonToBands(aPolyPoly);
-            }
-            else
-            {
-                mpImplRegion = ImplGeneralPolygonToBands(aPolyPoly, aRect);
-            }
-
-            // Convert points into seps.
-			ImplRegionBand* pRegionBand = mpImplRegion->mpFirstBand;
-			while ( pRegionBand )
-			{
-				// generate separations from the lines and process union
-				pRegionBand->ProcessPoints();
-				pRegionBand = pRegionBand->mpNextBand;
-			}
-
-            // Optimize list of bands.  Adjacent bands with identical lists
-            // of seps are joined.
-			if ( !mpImplRegion->OptimizeBandList() )
-			{
-				delete mpImplRegion;
-				mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-			}
-		}
-		else
-			mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	}
-	else
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-}
-
-// -----------------------------------------------------------------------
-
-void Region::Move( long nHorzMove, long nVertMove )
-{
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
-	// no region data? -> nothing to do
-	if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
-		return;
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	if ( mpImplRegion->mpPolyPoly )
-		mpImplRegion->mpPolyPoly->Move( nHorzMove, nVertMove );
-	else if( mpImplRegion->mpB2DPolyPoly )
-	{
-        mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
-	}
-	else
-	{
-		ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
-		while ( pBand )
-		{
-			// process the vertical move
-			if ( nVertMove != 0)
-			{
-				pBand->mnYTop = pBand->mnYTop + nVertMove;
-				pBand->mnYBottom = pBand->mnYBottom + nVertMove;
-			}
-
-			// process the horizontal move
-			if ( nHorzMove != 0)
-				pBand->MoveX( nHorzMove );
-
-			pBand = pBand->mpNextBand;
-		}
-	}
-}
-
-// -----------------------------------------------------------------------
-
-void Region::Scale( double fScaleX, double fScaleY )
-{
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
-	// no region data? -> nothing to do
-	if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
-		return;
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	if ( mpImplRegion->mpPolyPoly )
-		mpImplRegion->mpPolyPoly->Scale( fScaleX, fScaleY );
-	else if( mpImplRegion->mpB2DPolyPoly )
-	{
-		mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
-	}
-	else
-	{
-		ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
-		while ( pBand )
-		{
-			// process the vertical move
-			if ( fScaleY != 0.0 )
-			{
-				pBand->mnYTop = FRound( pBand->mnYTop * fScaleY );
-				pBand->mnYBottom = FRound( pBand->mnYBottom * fScaleY );
-			}
-
-			// process the horizontal move
-			if ( fScaleX != 0.0 )
-				pBand->ScaleX( fScaleX );
-
-			pBand = pBand->mpNextBand;
-		}
-	}
-}
-
-// -----------------------------------------------------------------------
+    {
+    	// excluding nothing will do no change
+		return true;
+    }
 
-sal_Bool Region::Union( const Rectangle& rRect )
-{
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
+    if(IsEmpty())
+    {
+        // cannot exclude from empty, done
+        return true;
+    }
 
-	// is rectangle empty? -> nothing to do
-	if ( rRect.IsEmpty() )
-		return sal_True;
+    if(IsNull())
+    {
+        // error; cannnot exclude from null region since this is not representable
+        // in the data
+        OSL_ENSURE(false, "Region::Exclude error: Cannot exclude from null region (!)");
+        return true;
+    }
 
-	if( HasPolyPolygon() )
+	if( HasPolyPolygonOrB2DPolyPolygon() )
 	{
 	    // get this B2DPolyPolygon
-	    basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
-	    aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+	    basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
 	    
-	    if( aThisPolyPoly.count() == 0 )
-	    {
-	        *this = rRect;
+        aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
+	    
+	    if(!aThisPolyPoly.count())
+        {
+            // when local polygon is empty, nothing can be excluded
 	        return true;
-	    }
-
-        // get the other B2DPolyPolygon
-        basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
-        basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
-        
-        basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );        
-        *this = Region( aClip );
-
-	    return sal_True;
-	}
-
-	ImplPolyPolyRegionToBandRegion();
-
-	// no instance data? -> create!
-	if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
-		mpImplRegion = new ImplRegion();
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	// get justified rectangle
-	long nLeft		= Min( rRect.Left(), rRect.Right() );
-	long nTop		= Min( rRect.Top(), rRect.Bottom() );
-	long nRight 	= Max( rRect.Left(), rRect.Right() );
-	long nBottom	= Max( rRect.Top(), rRect.Bottom() );
-
-	// insert bands if the boundaries are not allready in the list
-	mpImplRegion->InsertBands( nTop, nBottom );
-
-	// process union
-	mpImplRegion->Union( nLeft, nTop, nRight, nBottom );
-
-	// cleanup
-	if ( !mpImplRegion->OptimizeBandList() )
-	{
-		delete mpImplRegion;
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	}
-
-	return sal_True;
-}
-
-// -----------------------------------------------------------------------
+        }
+	    
+	    // get the other B2DPolyPolygon
+	    const basegfx::B2DPolygon aRectPoly( 
+            basegfx::tools::createPolygonFromRect( 
+                basegfx::B2DRectangle(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom())));
+	    const basegfx::B2DPolyPolygon aOtherPolyPoly(aRectPoly);
+	    const basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff(aThisPolyPoly, aOtherPolyPoly);
 
-sal_Bool Region::Intersect( const Rectangle& rRect )
-{
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
+        *this = Region(aClip);
 
-	// is rectangle empty? -> nothing to do
-	if ( rRect.IsEmpty() )
-	{
-		// statische Object haben RefCount von 0
-		if ( mpImplRegion->mnRefCount )
-		{
-			if ( mpImplRegion->mnRefCount > 1 )
-				mpImplRegion->mnRefCount--;
-			else
-				delete mpImplRegion;
-		}
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-		return sal_True;
+	    return true;
 	}
 
-    // #103137# Avoid banding for special cases
-    if ( mpImplRegion->mpPolyPoly )
-    {
-        // #127431# make ImplRegion unique, if not already.
-		if( mpImplRegion->mnRefCount > 1 )
-        {
-            mpImplRegion->mnRefCount--;
-            mpImplRegion = new ImplRegion( *mpImplRegion->mpPolyPoly );
-        }
+    // only region band mode possibility left here or null/empty
+    const RegionBand* pCurrent = getRegionBand();
 
-        // use the PolyPolygon::Clip method for rectangles, this is
-        // fairly simple (does not even use GPC) and saves us from
-        // unnecessary banding
-        mpImplRegion->mpPolyPoly->Clip( rRect );
-
-        // The clipping above may lead to empty ClipRegion
-        if(!mpImplRegion->mpPolyPoly->Count())
-        {
-            // react on empty ClipRegion; ImplRegion already is unique (see above)
-            delete mpImplRegion;
-            mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-        }
-
-        return sal_True;
-    }
-    else if( mpImplRegion->mpB2DPolyPoly )
+    if(!pCurrent)
     {
-        // #127431# make ImplRegion unique, if not already.
-		if( mpImplRegion->mnRefCount > 1 )
-        {
-            mpImplRegion->mnRefCount--;
-            mpImplRegion = new ImplRegion( *mpImplRegion->mpB2DPolyPoly );
-        }
-
-        *mpImplRegion->mpB2DPolyPoly =
-            basegfx::tools::clipPolyPolygonOnRange(
-                *mpImplRegion->mpB2DPolyPoly,
-                basegfx::B2DRange( 
-                    rRect.Left(), 
-                    rRect.Top(),
-                    rRect.Right() + 1, 
-                    rRect.Bottom() + 1),
-                true, 
-                false);
-
-        // The clipping above may lead to empty ClipRegion
-        if(!mpImplRegion->mpB2DPolyPoly->count())
-        {
-            // react on empty ClipRegion; ImplRegion already is unique (see above)
-            delete mpImplRegion;
-            mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-        }
-
-        return sal_True;
+        // empty? -> done!
+        return true;
     }
-    else
-        ImplPolyPolyRegionToBandRegion();
 
-	// is region empty? -> nothing to do!
-	if ( mpImplRegion == &aImplEmptyRegion )
-		return sal_True;
-
-	// get justified rectangle
-	long nLeft		= Min( rRect.Left(), rRect.Right() );
-	long nTop		= Min( rRect.Top(), rRect.Bottom() );
-	long nRight 	= Max( rRect.Left(), rRect.Right() );
-	long nBottom	= Max( rRect.Top(), rRect.Bottom() );
+    RegionBand* pNew = new RegionBand(*pCurrent);
 
-	// is own region NULL-region? -> copy data!
-	if ( mpImplRegion == &aImplNullRegion )
-	{
-		// create instance of implementation class
-		mpImplRegion = new ImplRegion();
+    // get justified rectangle
+    const long nLeft(std::min(rRect.Left(), rRect.Right()));
+    const long nTop(std::min(rRect.Top(), rRect.Bottom()));
+    const long nRight(std::max(rRect.Left(), rRect.Right()));
+    const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
 
-		// add band with boundaries of the rectangle
-		mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
+    // insert bands if the boundaries are not allready in the list
+    pNew->InsertBands(nTop, nBottom);
 
-		// Set left and right boundaries of the band
-		mpImplRegion->mpFirstBand->Union( nLeft, nRight );
-		mpImplRegion->mnRectCount = 1;
+    // process exclude
+    pNew->Exclude(nLeft, nTop, nRight, nBottom);
 
-		return sal_True;
-	}
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	// insert bands if the boundaries are not allready in the list
-	mpImplRegion->InsertBands( nTop, nBottom );
-
-	// process intersections
-	ImplRegionBand* pPrevBand = 0;
-	ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
-	while ( pBand )
-	{
-		// band within intersection boundary? -> process. otherwise remove
-		if ( (pBand->mnYTop >= nTop) &&
-			 (pBand->mnYBottom <= nBottom) )
-		{
-			// process intersection
-			pBand->Intersect( nLeft, nRight );
-
-			pPrevBand = pBand;
-			pBand = pBand->mpNextBand;
-		}
-		else
-		{
-			ImplRegionBand* pOldBand = pBand;
-			if ( pBand == mpImplRegion->mpFirstBand )
-				mpImplRegion->mpFirstBand = pBand->mpNextBand;
-			else
-				pPrevBand->mpNextBand = pBand->mpNextBand;
-			pBand = pBand->mpNextBand;
-			delete pOldBand;
-		}
-	}
-
-	// cleanup
-	if ( !mpImplRegion->OptimizeBandList() )
-	{
-		delete mpImplRegion;
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	}
+    // cleanup
+    if(!pNew->OptimizeBandList())
+    {
+        delete pNew;
+        pNew = 0;
+    }
 
-	return sal_True;
+    mpRegionBand.reset(pNew);
+    return true;
 }
 
-// -----------------------------------------------------------------------
-
-sal_Bool Region::Exclude( const Rectangle& rRect )
+bool Region::XOr( const Rectangle& rRect )
 {
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
-	// is rectangle empty? -> nothing to do
 	if ( rRect.IsEmpty() )
-		return sal_True;
-
-	if( HasPolyPolygon() )
-	{
-	    // get this B2DPolyPolygon
-	    basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
-	    aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
-	    
-	    if( aThisPolyPoly.count() == 0 )
-	        return sal_True;
-	    
-	    // get the other B2DPolyPolygon
-	    basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
-	    basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
-	    
-	    basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );	    
-	    *this = Region( aClip );
-
-	    return sal_True;
-	}
-
-	ImplPolyPolyRegionToBandRegion();
-
-	// no instance data? -> create!
-	if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
-		return sal_True;
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	// get justified rectangle
-	long nLeft		= Min( rRect.Left(), rRect.Right() );
-	long nTop		= Min( rRect.Top(), rRect.Bottom() );
-	long nRight 	= Max( rRect.Left(), rRect.Right() );
-	long nBottom	= Max( rRect.Top(), rRect.Bottom() );
-
-	// insert bands if the boundaries are not allready in the list
-	mpImplRegion->InsertBands( nTop, nBottom );
-
-	// process exclude
-	mpImplRegion->Exclude( nLeft, nTop, nRight, nBottom );
-
-	// cleanup
-	if ( !mpImplRegion->OptimizeBandList() )
-	{
-		delete mpImplRegion;
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	}
-
-	return sal_True;
-}
-
-// -----------------------------------------------------------------------
+    {
+    	// empty rectangle will not change local content
+		return true;
+    }
 
-sal_Bool Region::XOr( const Rectangle& rRect )
-{
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
+    if(IsEmpty())
+    {
+        // rRect will be the xored-form (local off, rect on)
+        *this = rRect;
+        return true;
+    }
 
-	// is rectangle empty? -> nothing to do
-	if ( rRect.IsEmpty() )
-		return sal_True;
+    if(IsNull())
+    {
+        // error; cannnot exclude from null region since this is not representable
+        // in the data
+        OSL_ENSURE(false, "Region::XOr error: Cannot XOr with null region (!)");
+        return true;
+    }
 
-	if( HasPolyPolygon() )
+    if( HasPolyPolygonOrB2DPolyPolygon() )
 	{
 	    // get this B2DPolyPolygon
-	    basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
-	    aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+	    basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
+
+        aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
 	    
-	    if( aThisPolyPoly.count() == 0 )
+	    if(!aThisPolyPoly.count())
 	    {
+            // no local content, XOr will be equal to rectangle
 	        *this = rRect;
-	        return sal_True;
+	        return true;
 	    }
 	    
 	    // get the other B2DPolyPolygon
-	    basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
-	    basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
-	    
-	    basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );	    
-	    *this = Region( aClip );
+	    const basegfx::B2DPolygon aRectPoly( 
+            basegfx::tools::createPolygonFromRect( 
+                basegfx::B2DRectangle(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom())));
+	    const basegfx::B2DPolyPolygon aOtherPolyPoly(aRectPoly);
+	    const basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor(aThisPolyPoly, aOtherPolyPoly);
 
-	    return sal_True;
+        *this = Region(aClip);
+
+	    return true;
 	}
 
-	ImplPolyPolyRegionToBandRegion();
+    // only region band mode possibility left here or null/empty
+    const RegionBand* pCurrent = getRegionBand();
 
-	// no instance data? -> create!
-	if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
-		mpImplRegion = new ImplRegion();
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	// get justified rectangle
-	long nLeft		= Min( rRect.Left(), rRect.Right() );
-	long nTop		= Min( rRect.Top(), rRect.Bottom() );
-	long nRight 	= Max( rRect.Left(), rRect.Right() );
-	long nBottom	= Max( rRect.Top(), rRect.Bottom() );
+    if(!pCurrent)
+    {
+        // rRect will be the xored-form (local off, rect on)
+        *this = rRect;
+        return true;
+    }
 
-	// insert bands if the boundaries are not allready in the list
-	mpImplRegion->InsertBands( nTop, nBottom );
+    // only region band mode possibility left here or null/empty
+    RegionBand* pNew = new RegionBand(*getRegionBand());
 
-	// process xor
-	mpImplRegion->XOr( nLeft, nTop, nRight, nBottom );
+    // get justified rectangle
+    const long nLeft(std::min(rRect.Left(), rRect.Right()));
+    const long nTop(std::min(rRect.Top(), rRect.Bottom()));
+    const long nRight(std::max(rRect.Left(), rRect.Right()));
+    const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
 
-	// cleanup
-	if ( !mpImplRegion->OptimizeBandList() )
-	{
-		delete mpImplRegion;
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	}
+    // insert bands if the boundaries are not allready in the list
+    pNew->InsertBands(nTop, nBottom);
 
-	return sal_True;
-}
+    // process xor
+    pNew->XOr(nLeft, nTop, nRight, nBottom);
 
-// -----------------------------------------------------------------------
-void Region::ImplUnionPolyPolygon( const Region& i_rRegion )
-{
-    // get this B2DPolyPolygon
-    basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
-    aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
-    
-    if( aThisPolyPoly.count() == 0 )
+    // cleanup
+    if(!pNew->OptimizeBandList())
     {
-        *this = i_rRegion;
-        return;
+        delete pNew;
+        pNew = 0;
     }
 
-    // get the other B2DPolyPolygon
-    basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
-    aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
-    
-    
-    basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
-    
-    *this = Region( aClip );
+    mpRegionBand.reset(pNew);
+    return true;
 }
 
-sal_Bool Region::Union( const Region& rRegion )
+bool Region::Union( const Region& rRegion )
 {
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
+    if(rRegion.IsEmpty())
+    {
+        // no extension at all
+        return true;
+    }
+
+    if(rRegion.IsNull())
+    {
+        // extending with null region -> null region
+        *this = Region(true);
+	    return true;
+    }
+
+    if(IsEmpty())
+    {
+        // local is empty, union will give source region
+        *this = rRegion;
+	    return true;
+    }
+
+    if(IsNull())
+    {
+        // already fully expanded (is null region), cannot be extended
+        return true;
+    }
 
-	if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+	if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
 	{
-	    ImplUnionPolyPolygon( rRegion );
-	    return sal_True;
+        // get this B2DPolyPolygon
+        basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
+
+        aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
+    
+        if(!aThisPolyPoly.count())
+        {
+            // when no local content, union will be equal to rRegion
+            *this = rRegion;
+            return true;
+        }
+
+        // get the other B2DPolyPolygon
+        basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
+        aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation(aOtherPolyPoly);
+
+        // use logical OR operation
+        basegfx::B2DPolyPolygon aClip(basegfx::tools::solvePolygonOperationOr(aThisPolyPoly, aOtherPolyPoly));
+    
+        *this = Region( aClip );
+	    return true;
 	}
 
-	ImplPolyPolyRegionToBandRegion();
-	((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+    // only region band mode possibility left here or null/empty
+    const RegionBand* pCurrent = getRegionBand();
 
-	// is region empty or null? -> nothing to do
-	if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
-		return sal_True;
-
-	// no instance data? -> create!
-	if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
-		mpImplRegion = new ImplRegion();
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	// Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
-	ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
-	while ( pBand )
-	{
-		// insert bands if the boundaries are not allready in the list
-		mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+    if(!pCurrent)
+    {
+        // local is empty, union will give source region
+        *this = rRegion;
+	    return true;
+    }
 
-		// process all elements of the list
-		ImplRegionBandSep* pSep = pBand->mpFirstSep;
-		while ( pSep )
-		{
-			mpImplRegion->Union( pSep->mnXLeft, pBand->mnYTop,
-								 pSep->mnXRight, pBand->mnYBottom );
-			pSep = pSep->mpNextSep;
-		}
+    const RegionBand* pSource = rRegion.getRegionBand();
 
-		pBand = pBand->mpNextBand;
-	}
+    if(!pSource)
+    {
+        // no extension at all
+        return true;
+    }
 
-	// cleanup
-	if ( !mpImplRegion->OptimizeBandList() )
-	{
-		delete mpImplRegion;
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-	}
+    // prepare source and target
+    RegionBand* pNew = new RegionBand(*pCurrent);
 
-	return sal_True;
-}
+    // union with source
+    pNew->Union(*pSource);
 
-// -----------------------------------------------------------------------
-void Region::ImplIntersectWithPolyPolygon( const Region& i_rRegion )
-{
-    // get this B2DPolyPolygon
-    basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
-    if( aThisPolyPoly.count() == 0 )
+    // cleanup
+    if(!pNew->OptimizeBandList())
     {
-        *this = i_rRegion;
-        return;
+        delete pNew;
+        pNew = 0;
     }
 
-    // get the other B2DPolyPolygon
-    basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
-    
-    basegfx::B2DPolyPolygon aClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aOtherPolyPoly, aThisPolyPoly, true, false );
-    *this = Region( aClip );
+    mpRegionBand.reset(pNew);
+    return true;
 }
 
-sal_Bool Region::Intersect( const Region& rRegion )
+bool Region::Intersect( const Region& rRegion )
 {
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
+    // same instance data? -> nothing to do!
+    if(getB2DPolyPolygon() && getB2DPolyPolygon() == rRegion.getB2DPolyPolygon())
+    {
+        return true;
+    }
 
-	// same instance data? -> nothing to do!
-	if ( mpImplRegion == rRegion.mpImplRegion )
-		return sal_True;
-	
-	if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
-	{
-	    ImplIntersectWithPolyPolygon( rRegion );
-	    return sal_True;
-	}
-    
-	ImplPolyPolyRegionToBandRegion();
-	((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+    if(getPolyPolygon() && getPolyPolygon() == rRegion.getPolyPolygon())
+    {
+        return true;
+    }
 
-	if ( mpImplRegion == &aImplEmptyRegion )
-		return sal_True;
+    if(getRegionBand() && getRegionBand() == rRegion.getRegionBand())
+    {
+        return true;
+    }
 
-	// is region null? -> nothing to do
-	if ( rRegion.mpImplRegion == &aImplNullRegion )
-		return sal_True;
+    if(rRegion.IsNull())
+    {
+        // source region is null-region, intersect will not change local region
+        return true;
+    }
 
-	// is rectangle empty? -> nothing to do
-	if ( rRegion.mpImplRegion == &aImplEmptyRegion )
-	{
-		// statische Object haben RefCount von 0
-		if ( mpImplRegion->mnRefCount )
-		{
-			if ( mpImplRegion->mnRefCount > 1 )
-				mpImplRegion->mnRefCount--;
-			else
-				delete mpImplRegion;
-		}
-		mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-		return sal_True;
-	}
+    if(IsNull())
+    {
+        // when local region is null-region, intersect will be equal to source
+        *this = rRegion;
+        return true;
+    }
 
-	// is own region NULL-region? -> copy data!
-	if ( mpImplRegion == &aImplNullRegion)
+	if(rRegion.IsEmpty())
 	{
-		mpImplRegion = rRegion.mpImplRegion;
-		rRegion.mpImplRegion->mnRefCount++;
-		return sal_True;
+        // source region is empty, intersection will always be empty
+        SetEmpty();
+		return true;
 	}
 
-	// Wenn wir weniger Rechtecke haben, drehen wir den Intersect-Aufruf um
-	if ( mpImplRegion->mnRectCount+2 < rRegion.mpImplRegion->mnRectCount )
+    if(IsEmpty())
+    {
+        // local region is empty, cannot get more emty than that. Nothing to do
+        return true;
+    }
+
+    if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
 	{
-		Region aTempRegion = rRegion;
-		aTempRegion.Intersect( *this );
-		*this = aTempRegion;
+        // get this B2DPolyPolygon
+        basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
+
+        if(!aThisPolyPoly.count())
+        {
+            // local region is empty, cannot get more emty than that. Nothing to do
+            return true;
+        }
+
+        // get the other B2DPolyPolygon
+        basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
+
+        if(!aOtherPolyPoly.count())
+        {
+            // source region is empty, intersection will always be empty
+            SetEmpty();
+		    return true;
+        }
+
+        const basegfx::B2DPolyPolygon aClip(
+            basegfx::tools::clipPolyPolygonOnPolyPolygon( 
+                aOtherPolyPoly, 
+                aThisPolyPoly, 
+                true, 
+                false));
+        *this = Region( aClip );
+	    return true;
 	}
-	else
-	{
-		// no own instance data? -> make own copy!
-		if ( mpImplRegion->mnRefCount > 1 )
-			ImplCopyData();
-
-		// mark all bands as untouched
-		ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
-		while ( pBand )
-		{
-			pBand->mbTouched = sal_False;
-			pBand = pBand->mpNextBand;
-		}
 
-		pBand = rRegion.mpImplRegion->mpFirstBand;
-		while ( pBand )
-		{
-			// insert bands if the boundaries are not allready in the list
-			mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+    // only region band mode possibility left here or null/empty
+    const RegionBand* pCurrent = getRegionBand();
 
-			// process all elements of the list
-			ImplRegionBandSep* pSep = pBand->mpFirstSep;
-			while ( pSep )
-			{
-				// left boundary?
-				if ( pSep == pBand->mpFirstSep )
-				{
-					// process intersection and do not remove untouched bands
-					mpImplRegion->Exclude( LONG_MIN+1, pBand->mnYTop,
-										   pSep->mnXLeft-1, pBand->mnYBottom );
-				}
-
-				// right boundary?
-				if ( pSep->mpNextSep == NULL )
-				{
-					// process intersection and do not remove untouched bands
-					mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
-										   LONG_MAX-1, pBand->mnYBottom );
-				}
-				else
-				{
-					// process intersection and do not remove untouched bands
-					mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
-										   pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
-				}
+    if(!pCurrent)
+    {
+        // local region is empty, cannot get more emty than that. Nothing to do
+        return true;
+    }
 
-				pSep = pSep->mpNextSep;
-			}
+    const RegionBand* pSource = rRegion.getRegionBand();
 
-			pBand = pBand->mpNextBand;
-		}
+    if(!pSource)
+    {
+        // source region is empty, intersection will always be empty
+        SetEmpty();
+		return true;
+    }
 
-		// remove all untouched bands if bands allready left
-		ImplRegionBand* pPrevBand = 0;
-		pBand = mpImplRegion->mpFirstBand;
-		while ( pBand )
-		{
-			if ( !pBand->mbTouched )
-			{
-				// save pointer
-				ImplRegionBand* pOldBand = pBand;
-
-				// previous element of the list
-				if ( pBand == mpImplRegion->mpFirstBand )
-					mpImplRegion->mpFirstBand = pBand->mpNextBand;
-				else
-					pPrevBand->mpNextBand = pBand->mpNextBand;
-
-				pBand = pBand->mpNextBand;
-				delete pOldBand;
-			}
-			else
-			{
-				pPrevBand = pBand;
-				pBand = pBand->mpNextBand;
-			}
-		}
+    // both RegionBands exist and are not empty
+    if(pCurrent->getRectangleCount() + 2 < pSource->getRectangleCount())
+    {
+        // when we have less rectangles, turn around the call
+        Region aTempRegion = rRegion;
+        aTempRegion.Intersect( *this );
+        *this = aTempRegion;
+    }
+    else
+    {
+        // prepare new regionBand
+        RegionBand* pNew = pCurrent ? new RegionBand(*pCurrent) : new RegionBand();
 
-		// cleanup
-		if ( !mpImplRegion->OptimizeBandList() )
-		{
-			delete mpImplRegion;
-			mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-		}
-	}
+        // intersect with source
+        pNew->Intersect(*pSource);
 
-	return sal_True;
-}
+        // cleanup
+        if(!pNew->OptimizeBandList())
+        {
+            delete pNew;
+            pNew = 0;
+        }
 
-// -----------------------------------------------------------------------
-void Region::ImplExcludePolyPolygon( const Region& i_rRegion )
-{
-    // get this B2DPolyPolygon
-    basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
-    if( aThisPolyPoly.count() == 0 )
-        return;
-    aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+        mpRegionBand.reset(pNew);
+    }
 
-    // get the other B2DPolyPolygon
-    basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
-    aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
-    
-    basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
-    *this = Region( aClip );
+    return true;
 }
 
-sal_Bool Region::Exclude( const Region& rRegion )
+bool Region::Exclude( const Region& rRegion )
 {
-	DBG_CHKTHIS( Region, ImplDbgTestRegion );
+	if ( rRegion.IsEmpty() )
+    {
+    	// excluding nothing will do no change
+		return true;
+    }
 
-	if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
-	{
-	    ImplExcludePolyPolygon( rRegion );
-	    return sal_True;
-	}
+	if ( rRegion.IsNull() )
+    {
+    	// excluding everything will create empty region
+        SetEmpty();
+		return true;
+    }
 
-	ImplPolyPolyRegionToBandRegion();
-	((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+    if(IsEmpty())
+    {
+        // cannot exclude from empty, done
+        return true;
+    }
+
+    if(IsNull())
+    {
+        // error; cannnot exclude from null region since this is not representable
+        // in the data
+        OSL_ENSURE(false, "Region::Exclude error: Cannot exclude from null region (!)");
+        return true;
+    }
 
-	// is region empty or null? -> nothing to do
-	if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
-		return sal_True;
-
-	// no instance data? -> nothing to do
-	if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
-		return sal_True;
-
-	// no own instance data? -> make own copy!
-	if ( mpImplRegion->mnRefCount > 1 )
-		ImplCopyData();
-
-	// Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
-	ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
-	while ( pBand )
+	if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
 	{
-		// insert bands if the boundaries are not allready in the list
-		mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+        // get this B2DPolyPolygon
+        basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
 
-		// process all elements of the list
-		ImplRegionBandSep* pSep = pBand->mpFirstSep;
-		while ( pSep )
-		{
-			mpImplRegion->Exclude( pSep->mnXLeft, pBand->mnYTop,
-								   pSep->mnXRight, pBand->mnYBottom );
-			pSep = pSep->mpNextSep;
-		}
+        if(!aThisPolyPoly.count())
+        {
+            // cannot exclude from empty, done
+            return true;
+        }
 
-		// Wir optimieren schon in der Schleife, da wir davon
-		// ausgehen, das wir insgesammt weniger Baender ueberpruefen
-		// muessen
-		if ( !mpImplRegion->OptimizeBandList() )
-		{
-			delete mpImplRegion;
-			mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
-			break;
-		}
+        aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
 
-		pBand = pBand->mpNextBand;
+        // get the other B2DPolyPolygon
+        basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
+        aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
+    

[... 1566 lines stripped ...]


Mime
View raw message