summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2012-10-23 12:46:28 +0000
committerCaolán McNamara <caolanm@redhat.com>2013-06-12 14:31:10 +0100
commite717d1dcce7f8906311c5ccdbb2326b61a702630 (patch)
tree91290db5179fa4b4927af94c0f023f40dcda434c
parent9e50e5f82927742c56e89258b80bc8cd93bb7e3b (diff)
Resolves: #i121237# Rework/Cleanup of Region code...
due to missing complete support for B2DPolygon class (cherry picked from commit cab10eeb7878edf224a004fd7640bd4adf8d3c51) Conflicts: cppcanvas/source/mtfrenderer/implrenderer.cxx svx/source/sdr/overlay/overlaymanagerbuffered.cxx svx/source/svdraw/svdpntv.cxx vcl/aqua/source/gdi/salgdi.cxx vcl/inc/region.h vcl/inc/unx/gtk/gtkgdi.hxx vcl/inc/vcl/regband.hxx vcl/inc/vcl/region.hxx vcl/os2/source/gdi/salgdi.cxx vcl/source/gdi/bmpacc3.cxx vcl/source/gdi/outdev2.cxx vcl/source/gdi/outmap.cxx vcl/source/gdi/regband.cxx vcl/source/gdi/region.cxx vcl/source/window/window.cxx vcl/unx/generic/gdi/pspgraphics.cxx vcl/unx/headless/svpgdi.cxx vcl/unx/headless/svppspgraphics.cxx vcl/win/source/gdi/salgdi.cxx Change-Id: Iee9a66ff431c3cecb7603e445147b67715de0f7d Remove unused variable to prevent compiler warning (cherry picked from commit 0ac65ccf079e3e22ac23cbe7ae546504c863c31f) Change-Id: Icbcaa9d576a7e560d96debc7360bdbe9090b3fd3 Wrong comparison with bool corrected (cherry picked from commit 612cefdcf6176b6bb847ce899d89af40ef313a90) Change-Id: I1cf5de6734b588f78d8e870ba7b7860634b461ce
-rw-r--r--canvas/source/vcl/canvashelper.cxx2
-rw-r--r--cppcanvas/source/mtfrenderer/implrenderer.cxx16
-rw-r--r--drawinglayer/source/primitive2d/metafileprimitive2d.cxx20
-rw-r--r--filter/source/graphicfilter/eps/eps.cxx111
-rw-r--r--include/vcl/bmpacc.hxx6
-rw-r--r--include/vcl/outdev.hxx12
-rw-r--r--include/vcl/regband.hxx23
-rw-r--r--include/vcl/region.hxx167
-rw-r--r--sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx23
-rw-r--r--svx/source/sdr/overlay/overlaymanagerbuffered.cxx80
-rw-r--r--svx/source/sdr/properties/itemsettools.cxx6
-rw-r--r--svx/source/svdraw/sdrpaintwindow.cxx47
-rw-r--r--svx/source/svdraw/svdfmtf.cxx4
-rw-r--r--svx/source/svdraw/svdpntv.cxx45
-rw-r--r--sw/source/core/view/viewsh.cxx20
-rw-r--r--toolkit/source/awt/vclxregion.cxx27
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/aqua/source/gdi/salgdicommon.cxx28
-rw-r--r--vcl/generic/fontmanager/fontsubst.cxx1
-rw-r--r--vcl/generic/print/genpspgraphics.cxx42
-rw-r--r--vcl/headless/svpgdi.cxx63
-rw-r--r--vcl/inc/region.h128
-rw-r--r--vcl/inc/regionband.hxx83
-rw-r--r--vcl/source/gdi/bitmap.cxx72
-rw-r--r--vcl/source/gdi/bmpacc3.cxx129
-rw-r--r--vcl/source/gdi/gdimtf.cxx12
-rw-r--r--vcl/source/gdi/outdev.cxx55
-rw-r--r--vcl/source/gdi/outdev2.cxx75
-rw-r--r--vcl/source/gdi/outmap.cxx304
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx4
-rw-r--r--vcl/source/gdi/regband.cxx106
-rw-r--r--vcl/source/gdi/region.cxx3521
-rw-r--r--vcl/source/gdi/regionband.cxx1377
-rw-r--r--vcl/source/gdi/salgdilayout.cxx41
-rw-r--r--vcl/source/window/window.cxx128
-rw-r--r--vcl/unx/generic/gdi/salgdi.cxx49
-rw-r--r--vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx29
-rw-r--r--vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx3
-rw-r--r--vcl/win/source/gdi/salgdi.cxx124
39 files changed, 3904 insertions, 3080 deletions
diff --git a/canvas/source/vcl/canvashelper.cxx b/canvas/source/vcl/canvashelper.cxx
index 0f3718feed64..10a6f5328f01 100644
--- a/canvas/source/vcl/canvashelper.cxx
+++ b/canvas/source/vcl/canvashelper.cxx
@@ -1231,7 +1231,7 @@ namespace vclcanvas
// accumulate non-empty clips into one region
// ==========================================
- Region aClipRegion( REGION_NULL );
+ Region aClipRegion(true);
if( viewState.Clip.is() )
{
diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx
index 2fcff5ad4ba1..a85239140b0e 100644
--- a/cppcanvas/source/mtfrenderer/implrenderer.cxx
+++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx
@@ -1368,7 +1368,7 @@ namespace cppcanvas
}
else
{
- if( !pClipAction->GetRegion().HasPolyPolygon() )
+ if( !pClipAction->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
{
VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
"region encountered, falling back to bounding box!" );
@@ -1390,9 +1390,11 @@ namespace cppcanvas
// with old one, just set it)
// #121806# explicitly kept integer
+ basegfx::B2DPolyPolygon aPolyPolygon(pClipAction->GetRegion().GetAsB2DPolyPolygon());
+
+ aPolyPolygon.transform(rVDev.GetViewTransformation());
updateClipping(
- rVDev.LogicToPixel(
- pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
+ aPolyPolygon,
rFactoryParms,
false );
}
@@ -1422,7 +1424,7 @@ namespace cppcanvas
{
MetaISectRegionClipRegionAction* pClipAction = static_cast<MetaISectRegionClipRegionAction*>(pCurrAct);
- if( !pClipAction->GetRegion().HasPolyPolygon() )
+ if( !pClipAction->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
{
VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
"region encountered, falling back to bounding box!" );
@@ -1442,9 +1444,11 @@ namespace cppcanvas
// intersect current clip with given clip polygon
// #121806# explicitly kept integer
+ basegfx::B2DPolyPolygon aPolyPolygon(pClipAction->GetRegion().GetAsB2DPolyPolygon());
+
+ aPolyPolygon.transform(rVDev.GetViewTransformation());
updateClipping(
- rVDev.LogicToPixel(
- pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
+ aPolyPolygon,
rFactoryParms,
true );
}
diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
index 4a0719ea0ffb..d08a8ed89ffa 100644
--- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
@@ -380,26 +380,8 @@ namespace
if(!rRegion.IsEmpty())
{
Region aRegion(rRegion);
- aRetval = aRegion.GetB2DPolyPolygon();
- if(!aRetval.count())
- {
- RegionHandle aRegionHandle(aRegion.BeginEnumRects());
- Rectangle aRegionRectangle;
-
- while(aRegion.GetEnumRects(aRegionHandle, aRegionRectangle))
- {
- if(!aRegionRectangle.IsEmpty())
- {
- const basegfx::B2DRange aRegionRange(
- aRegionRectangle.Left(), aRegionRectangle.Top(),
- aRegionRectangle.Right(), aRegionRectangle.Bottom());
- aRetval.append(basegfx::tools::createPolygonFromRect(aRegionRange));
- }
- }
-
- aRegion.EndEnumRects(aRegionHandle);
- }
+ aRetval = aRegion.GetAsB2DPolyPolygon();
}
return aRetval;
diff --git a/filter/source/graphicfilter/eps/eps.cxx b/filter/source/graphicfilter/eps/eps.cxx
index 454d683393ed..12a18e69de14 100644
--- a/filter/source/graphicfilter/eps/eps.cxx
+++ b/filter/source/graphicfilter/eps/eps.cxx
@@ -1649,15 +1649,16 @@ void PSWriter::ImplSetClipRegion( Region& rClipRegion )
{
if ( !rClipRegion.IsEmpty() )
{
- Rectangle aRect;
- RegionHandle hRegionHandle = rClipRegion.BeginEnumRects();
+ RectangleVector aRectangles;
+ rClipRegion.GetRegionRectangles(aRectangles);
- while ( rClipRegion.GetNextEnumRect( hRegionHandle, aRect ) )
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- double nX1 = aRect.Left();
- double nY1 = aRect.Top();
- double nX2 = aRect.Right();
- double nY2 = aRect.Bottom();
+ double nX1(aRectIter->Left());
+ double nY1(aRectIter->Top());
+ double nX2(aRectIter->Right());
+ double nY2(aRectIter->Bottom());
+
ImplWriteDouble( nX1 );
ImplWriteDouble( nY1 );
ImplWriteByte( 'm' );
@@ -1673,8 +1674,34 @@ void PSWriter::ImplSetClipRegion( Region& rClipRegion )
ImplWriteDouble( nX1 );
ImplWriteDouble( nY1 );
ImplWriteByte( 'l', PS_SPACE | PS_WRAP );
- };
- rClipRegion.EndEnumRects( hRegionHandle );
+ }
+
+ //Rectangle aRect;
+ //RegionHandle hRegionHandle = rClipRegion.BeginEnumRects();
+ //
+ //while ( rClipRegion.GetEnumRects( hRegionHandle, aRect ) )
+ //{
+ // double nX1 = aRect.Left();
+ // double nY1 = aRect.Top();
+ // double nX2 = aRect.Right();
+ // double nY2 = aRect.Bottom();
+ // ImplWriteDouble( nX1 );
+ // ImplWriteDouble( nY1 );
+ // ImplWriteByte( 'm' );
+ // ImplWriteDouble( nX2 );
+ // ImplWriteDouble( nY1 );
+ // ImplWriteByte( 'l' );
+ // ImplWriteDouble( nX2 );
+ // ImplWriteDouble( nY2 );
+ // ImplWriteByte( 'l' );
+ // ImplWriteDouble( nX1 );
+ // ImplWriteDouble( nY2 );
+ // ImplWriteByte( 'l' );
+ // ImplWriteDouble( nX1 );
+ // ImplWriteDouble( nY1 );
+ // ImplWriteByte( 'l', PS_SPACE | PS_WRAP );
+ //};
+ //rClipRegion.EndEnumRects( hRegionHandle );
ImplWriteLine( "eoclip newpath" );
}
}
@@ -1723,12 +1750,18 @@ void PSWriter::ImplBmp( Bitmap* pBitmap, Bitmap* pMaskBitmap, const Point & rPoi
aRect = Rectangle( Point( 0, nHeightOrg - nHeightLeft ), Size( (long)nWidth, (long)nHeight ) );
aRegion = Region( pMaskBitmap->CreateRegion( COL_BLACK, aRect ) );
- if ( ( mnLevel == 1 ) && ( aRegion.GetRectCount() * 5 > 1000 ) )
+ if( mnLevel == 1 )
{
- nHeight >>= 1;
- if ( nHeight < 2 )
- return;
- continue;
+ RectangleVector aRectangleVector;
+ aRegion.GetRegionRectangles(aRectangleVector);
+
+ if ( aRectangleVector.size() * 5 > 1000 )
+ {
+ nHeight >>= 1;
+ if ( nHeight < 2 )
+ return;
+ continue;
+ }
}
break;
}
@@ -1743,26 +1776,50 @@ void PSWriter::ImplBmp( Bitmap* pBitmap, Bitmap* pMaskBitmap, const Point & rPoi
ImplWriteLine( "gs\npum" );
ImplTranslate( aSourcePos.X(), aSourcePos.Y() );
ImplScale( nXWidth / nWidth, nYHeight / nHeight );
- RegionHandle hRegionHandle = aRegion.BeginEnumRects();
- while ( aRegion.GetNextEnumRect( hRegionHandle, aRect ) )
+ RectangleVector aRectangles;
+ aRegion.GetRegionRectangles(aRectangles);
+ const long nMoveVertical(nHeightLeft - nHeightOrg);
+
+ for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- aRect.Move( 0, - ( nHeightOrg - nHeightLeft ) );
- ImplWriteLong( aRect.Left() );
- ImplWriteLong( aRect.Top() );
+ aRectIter->Move(0, nMoveVertical);
+
+ ImplWriteLong( aRectIter->Left() );
+ ImplWriteLong( aRectIter->Top() );
ImplWriteByte( 'm' );
- ImplWriteLong( aRect.Right() + 1 );
- ImplWriteLong( aRect.Top() );
+ ImplWriteLong( aRectIter->Right() + 1 );
+ ImplWriteLong( aRectIter->Top() );
ImplWriteByte( 'l' );
- ImplWriteLong( aRect.Right() + 1 );
- ImplWriteLong( aRect.Bottom() + 1 );
+ ImplWriteLong( aRectIter->Right() + 1 );
+ ImplWriteLong( aRectIter->Bottom() + 1 );
ImplWriteByte( 'l' );
- ImplWriteLong( aRect.Left() );
- ImplWriteLong( aRect.Bottom() + 1 );
+ ImplWriteLong( aRectIter->Left() );
+ ImplWriteLong( aRectIter->Bottom() + 1 );
ImplWriteByte( 'l' );
ImplWriteByte( 'p', PS_SPACE | PS_WRAP );
- };
- aRegion.EndEnumRects( hRegionHandle );
+ }
+
+ //RegionHandle hRegionHandle = aRegion.BeginEnumRects();
+ //
+ //while ( aRegion.GetEnumRects( hRegionHandle, aRect ) )
+ //{
+ // aRect.Move( 0, - ( nHeightOrg - nHeightLeft ) );
+ // ImplWriteLong( aRect.Left() );
+ // ImplWriteLong( aRect.Top() );
+ // ImplWriteByte( 'm' );
+ // ImplWriteLong( aRect.Right() + 1 );
+ // ImplWriteLong( aRect.Top() );
+ // ImplWriteByte( 'l' );
+ // ImplWriteLong( aRect.Right() + 1 );
+ // ImplWriteLong( aRect.Bottom() + 1 );
+ // ImplWriteByte( 'l' );
+ // ImplWriteLong( aRect.Left() );
+ // ImplWriteLong( aRect.Bottom() + 1 );
+ // ImplWriteByte( 'l' );
+ // ImplWriteByte( 'p', PS_SPACE | PS_WRAP );
+ //};
+ //aRegion.EndEnumRects( hRegionHandle );
ImplWriteLine( "eoclip newpath" );
ImplWriteLine( "pom" );
}
diff --git a/include/vcl/bmpacc.hxx b/include/vcl/bmpacc.hxx
index 306f28a5b0b2..f3f5301c2567 100644
--- a/include/vcl/bmpacc.hxx
+++ b/include/vcl/bmpacc.hxx
@@ -195,6 +195,12 @@ public:
void FillRect( const Rectangle& rRect );
void DrawRect( const Rectangle& rRect );
+ void FillPolygon( const Polygon& rPoly );
+ void DrawPolygon( const Polygon& rPoly );
+
+ void FillPolyPolygon( const PolyPolygon& rPoly );
+ void DrawPolyPolygon( const PolyPolygon& rPolyPoly );
+
private:
BitmapColor* mpLineColor;
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index b3a2f9ef87e1..b76598f08452 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -965,6 +965,7 @@ public:
Rectangle LogicToPixel( const Rectangle& rLogicRect ) const;
Polygon LogicToPixel( const Polygon& rLogicPoly ) const;
PolyPolygon LogicToPixel( const PolyPolygon& rLogicPolyPoly ) const;
+ basegfx::B2DPolyPolygon LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly ) const;
Region LogicToPixel( const Region& rLogicRegion )const;
Point LogicToPixel( const Point& rLogicPt,
const MapMode& rMapMode ) const;
@@ -974,12 +975,19 @@ public:
const MapMode& rMapMode ) const;
Polygon LogicToPixel( const Polygon& rLogicPoly,
const MapMode& rMapMode ) const;
+ basegfx::B2DPolygon LogicToPixel( const basegfx::B2DPolygon& rLogicPoly,
+ const MapMode& rMapMode ) const;
+ PolyPolygon LogicToPixel( const PolyPolygon& rLogicPolyPoly,
+ const MapMode& rMapMode ) const;
basegfx::B2DPolyPolygon LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly,
const MapMode& rMapMode ) const;
+ Region LogicToPixel( const Region& rLogicRegion,
+ const MapMode& rMapMode ) const;
Point PixelToLogic( const Point& rDevicePt ) const;
Size PixelToLogic( const Size& rDeviceSize ) const;
Rectangle PixelToLogic( const Rectangle& rDeviceRect ) const;
Polygon PixelToLogic( const Polygon& rDevicePoly ) const;
+ basegfx::B2DPolygon LogicToPixel( const basegfx::B2DPolygon& rLogicPoly ) const;
PolyPolygon PixelToLogic( const PolyPolygon& rDevicePolyPoly ) const;
basegfx::B2DPolyPolygon PixelToLogic( const basegfx::B2DPolyPolygon& rDevicePolyPoly ) const;
Region PixelToLogic( const Region& rDeviceRegion ) const;
@@ -993,8 +1001,12 @@ public:
const MapMode& rMapMode ) const;
basegfx::B2DPolygon PixelToLogic( const basegfx::B2DPolygon& rDevicePoly,
const MapMode& rMapMode ) const;
+ PolyPolygon PixelToLogic( const PolyPolygon& rDevicePolyPoly,
+ const MapMode& rMapMode ) const;
basegfx::B2DPolyPolygon PixelToLogic( const basegfx::B2DPolyPolygon& rDevicePolyPoly,
const MapMode& rMapMode ) const;
+ Region PixelToLogic( const Region& rDeviceRegion,
+ const MapMode& rMapMode ) const;
Point LogicToLogic( const Point& rPtSource,
const MapMode* pMapModeSource,
const MapMode* pMapModeDest ) const;
diff --git a/include/vcl/regband.hxx b/include/vcl/regband.hxx
index 0b60a801d83e..24fe7584a7b7 100644
--- a/include/vcl/regband.hxx
+++ b/include/vcl/regband.hxx
@@ -49,7 +49,7 @@ struct ImplRegionBandSep
ImplRegionBandSep* mpNextSep;
long mnXLeft;
long mnXRight;
- sal_Bool mbRemoved;
+ bool mbRemoved;
};
enum LineType { LINE_ASCENDING, LINE_DESCENDING, LINE_HORIZONTAL };
@@ -60,7 +60,7 @@ struct ImplRegionBandPoint
ImplRegionBandPoint* mpNextBandPoint;
long mnX;
long mnLineId;
- sal_Bool mbEndPoint;
+ bool mbEndPoint;
LineType meLineType;
};
@@ -77,7 +77,9 @@ public:
ImplRegionBandPoint* mpFirstBandPoint; // root of the list with lines
long mnYTop; // actual boundary of the band
long mnYBottom;
- sal_Bool mbTouched;
+
+ // bitfield
+ bool mbTouched : 1;
// create y-band with boundaries
ImplRegionBand( long nYTop, long nYBottom );
@@ -102,14 +104,14 @@ public:
long GetXRightBoundary() const;
// combine overlapping bands
- sal_Bool OptimizeBand();
+ bool OptimizeBand();
// generate separations from lines and process
// union with existing separations
void ProcessPoints();
// insert point in the list for later processing
- sal_Bool InsertPoint( long nX, long nLineID,
- sal_Bool bEndPoint, LineType eLineType );
+ bool InsertPoint( long nX, long nLineID,
+ bool bEndPoint, LineType eLineType );
void Union( long nXLeft, long nXRight );
void Intersect( long nXLeft, long nXRight );
@@ -119,11 +121,14 @@ public:
void MoveX( long nHorzMove );
void ScaleX( double fHorzScale );
- sal_Bool IsInside( long nX );
+ bool IsInside( long nX );
+ bool IsInside( long nLeft, long nRight );
+ bool IsOver( long nLeft, long nRight );
+
- sal_Bool IsEmpty() const { return ((!mpFirstSep) && (!mpFirstBandPoint)); }
+ bool IsEmpty() const { return ((!mpFirstSep) && (!mpFirstBandPoint)); }
- sal_Bool operator==( const ImplRegionBand& rRegionBand ) const;
+ bool operator==( const ImplRegionBand& rRegionBand ) const;
/** Split the called band at the given vertical coordinate. After the
split the called band will cover the upper part not including nY.
diff --git a/include/vcl/region.hxx b/include/vcl/region.hxx
index 88c55ea5b5fc..f2298e7a5d2a 100644
--- a/include/vcl/region.hxx
+++ b/include/vcl/region.hxx
@@ -25,115 +25,96 @@
#include <vcl/dllapi.h>
#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <boost/shared_ptr.hpp>
-class ImplRegion;
class ImplRegionBand;
+class RegionBand;
class Polygon;
class PolyPolygon;
-struct ImplRegionInfo;
-// --------------
-// - RegionType -
-// --------------
+//////////////////////////////////////////////////////////////////////////////
-enum RegionType { REGION_NULL, REGION_EMPTY, REGION_RECTANGLE, REGION_COMPLEX };
-enum RegionOverlapType { REGION_INSIDE, REGION_OVER, REGION_OUTSIDE };
+typedef boost::shared_ptr< RegionBand > RegionBandPtr;
+typedef boost::shared_ptr< PolyPolygon > PolyPolygonPtr;
+typedef boost::shared_ptr< basegfx::B2DPolyPolygon > B2DPolyPolygonPtr;
+typedef std::vector< Rectangle > RectangleVector;
-typedef sal_IntPtr RegionHandle;
-
-// ----------
-// - Region -
-// ----------
+//////////////////////////////////////////////////////////////////////////////
class VCL_DLLPUBLIC Region
{
+private:
friend class OutputDevice;
friend class Window;
friend class Bitmap;
-private:
- ImplRegion* mpImplRegion;
-
- SAL_DLLPRIVATE void ImplCopyData();
- SAL_DLLPRIVATE void ImplCreateRectRegion( const Rectangle& rRect );
- SAL_DLLPRIVATE void ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly );
- SAL_DLLPRIVATE void ImplCreatePolyPolyRegion( const basegfx::B2DPolyPolygon& rPolyPoly );
- SAL_DLLPRIVATE void ImplPolyPolyRegionToBandRegionFunc();
- SAL_DLLPRIVATE inline void ImplPolyPolyRegionToBandRegion();
- SAL_DLLPRIVATE const ImplRegion* ImplGetImplRegion() const { return mpImplRegion; }
- SAL_DLLPRIVATE ImplRegion* ImplGetImplRegion() { return mpImplRegion; }
- SAL_DLLPRIVATE void ImplBeginAddRect( );
- SAL_DLLPRIVATE sal_Bool ImplAddRect( const Rectangle& rRect );
- SAL_DLLPRIVATE void ImplEndAddRect( );
- SAL_DLLPRIVATE void ImplIntersectWithPolyPolygon( const Region& );
- SAL_DLLPRIVATE void ImplExcludePolyPolygon( const Region& );
- SAL_DLLPRIVATE void ImplUnionPolyPolygon( const Region& );
- SAL_DLLPRIVATE void ImplXOrPolyPolygon( const Region& );
-
-public: // public within vcl
- VCL_PLUGIN_PUBLIC bool ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
- long& nX, long& nY, long& nWidth, long& nHeight ) const;
- VCL_PLUGIN_PUBLIC bool ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
- long& nX, long& nY, long& nWidth, long& nHeight ) const;
-#ifdef DBG_UTIL
- friend const char* ImplDbgTestRegion( const void* pObj );
-#endif
+ // possible contents
+ B2DPolyPolygonPtr mpB2DPolyPolygon;
+ PolyPolygonPtr mpPolyPolygon;
+ RegionBandPtr mpRegionBand;
+
+ /// bitfield
+ bool mbIsNull : 1;
+
+ // helpers
+ SAL_DLLPRIVATE void ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly );
+ SAL_DLLPRIVATE void ImplCreatePolyPolyRegion( const basegfx::B2DPolyPolygon& rPolyPoly );
+
+ SAL_DLLPRIVATE PolyPolygon ImplCreatePolyPolygonFromRegionBand() const;
+ SAL_DLLPRIVATE basegfx::B2DPolyPolygon ImplCreateB2DPolyPolygonFromRegionBand() const;
public:
- explicit Region();
- explicit Region( RegionType eType );
- explicit Region( const Rectangle& rRect );
- explicit Region( const Polygon& rPolygon );
- explicit Region( const PolyPolygon& rPolyPoly );
- explicit Region( const basegfx::B2DPolyPolygon& );
- Region( const Region& rRegion );
- ~Region();
-
- void Move( long nHorzMove, long nVertMove );
- void Scale( double fScaleX, double fScaleY );
- void Union( const Rectangle& rRegion );
- void Intersect( const Rectangle& rRegion );
- void Exclude( const Rectangle& rRegion );
- void XOr( const Rectangle& rRegion );
- void Union( const Region& rRegion );
- void Intersect( const Region& rRegion );
- void Exclude( const Region& rRegion );
- void XOr( const Region& rRegion );
-
- RegionType GetType() const;
- sal_Bool IsEmpty() const { return GetType() == REGION_EMPTY; };
- sal_Bool IsNull() const { return GetType() == REGION_NULL; };
-
- void SetEmpty();
- void SetNull();
-
- Rectangle GetBoundRect() const;
-
- sal_Bool HasPolyPolygon() const;
- PolyPolygon GetPolyPolygon() const;
- // returns an empty polypolygon in case HasPolyPolygon is sal_False
- const basegfx::B2DPolyPolygon GetB2DPolyPolygon() const;
- // returns a PolyPolygon either copied from the set PolyPolygon region
- // or created from the constituent rectangles
- basegfx::B2DPolyPolygon ConvertToB2DPolyPolygon();
-
- sal_uLong GetRectCount() const;
- RegionHandle BeginEnumRects();
- sal_Bool GetEnumRects( RegionHandle hRegionHandle, Rectangle& rRect );
- sal_Bool GetNextEnumRect( RegionHandle hRegionHandle, Rectangle& rRect )
- { return GetEnumRects( hRegionHandle, rRect ); }
- void EndEnumRects( RegionHandle hRegionHandle );
-
- sal_Bool IsInside( const Point& rPoint ) const;
- sal_Bool IsInside( const Rectangle& rRect ) const;
- sal_Bool IsOver( const Rectangle& rRect ) const;
-
- Region& operator=( const Region& rRegion );
- Region& operator=( const Rectangle& rRect );
-
- sal_Bool operator==( const Region& rRegion ) const;
- sal_Bool operator!=( const Region& rRegion ) const
- { return !(Region::operator==( rRegion )); }
+
+ explicit Region(bool bIsNull = false); // default creates empty region, with true a null region is created
+ explicit Region(const Rectangle& rRect);
+ explicit Region(const Polygon& rPolygon);
+ explicit Region(const PolyPolygon& rPolyPoly);
+ explicit Region(const basegfx::B2DPolyPolygon&);
+ Region(const Region& rRegion);
+ ~Region();
+
+ // direct access to contents
+ const basegfx::B2DPolyPolygon* getB2DPolyPolygon() const { return mpB2DPolyPolygon.get(); }
+ const PolyPolygon* getPolyPolygon() const { return mpPolyPolygon.get(); }
+ const RegionBand* getRegionBand() const { return mpRegionBand.get(); }
+
+ // access with converters, the asked data will be created from the most
+ // valuable data, buffered and returned
+ const PolyPolygon GetAsPolyPolygon() const;
+ const basegfx::B2DPolyPolygon GetAsB2DPolyPolygon() const;
+ const RegionBand* GetAsRegionBand() const;
+
+ // manipulators
+ void Move( long nHorzMove, long nVertMove );
+ void Scale( double fScaleX, double fScaleY );
+ bool Union( const Rectangle& rRegion );
+ bool Intersect( const Rectangle& rRegion );
+ bool Exclude( const Rectangle& rRegion );
+ bool XOr( const Rectangle& rRegion );
+ bool Union( const Region& rRegion );
+ bool Intersect( const Region& rRegion );
+ bool Exclude( const Region& rRegion );
+ bool XOr( const Region& rRegion );
+
+ bool IsEmpty() const;
+ bool IsNull() const;
+
+ void SetEmpty();
+ void SetNull();
+
+ Rectangle GetBoundRect() const;
+ bool HasPolyPolygonOrB2DPolyPolygon() const { return (getB2DPolyPolygon() || getPolyPolygon()); }
+ void GetRegionRectangles(RectangleVector& rTarget) const;
+
+ bool IsInside( const Point& rPoint ) const;
+ bool IsInside( const Rectangle& rRect ) const;
+ bool IsOver( const Rectangle& rRect ) const;
+
+ Region& operator=( const Region& rRegion );
+ Region& operator=( const Rectangle& rRect );
+
+ bool operator==( const Region& rRegion ) const;
+ bool operator!=( const Region& rRegion ) const { return !(Region::operator==( rRegion )); }
friend VCL_DLLPUBLIC SvStream& operator>>( SvStream& rIStm, Region& rRegion );
friend VCL_DLLPUBLIC SvStream& operator<<( SvStream& rOStm, const Region& rRegion );
diff --git a/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx b/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx
index 601525951231..3575c24e5656 100644
--- a/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx
+++ b/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx
@@ -79,19 +79,26 @@ void DeviceCopy (
void ForAllRectangles (const Region& rRegion, ::boost::function<void(const Rectangle&)> aFunction)
{
OSL_ASSERT(aFunction);
+ RectangleVector aRectangles;
+ rRegion.GetRegionRectangles(aRectangles);
- if (rRegion.GetRectCount() <= 1)
+ if(0 == aRectangles.size())
{
- aFunction(rRegion.GetBoundRect());
+ aFunction(Rectangle());
}
else
{
- Region aMutableRegionCopy (rRegion);
- RegionHandle aHandle(aMutableRegionCopy.BeginEnumRects());
- Rectangle aBox;
- while (aMutableRegionCopy.GetNextEnumRect(aHandle, aBox))
- aFunction(aBox);
- aMutableRegionCopy.EndEnumRects(aHandle);
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
+ {
+ aFunction(*aRectIter);
+ }
+
+ //Region aMutableRegionCopy (rRegion);
+ //RegionHandle aHandle(aMutableRegionCopy.BeginEnumRects());
+ //Rectangle aBox;
+ //while (aMutableRegionCopy.GetEnumRects(aHandle, aBox))
+ // aFunction(aBox);
+ //aMutableRegionCopy.EndEnumRects(aHandle);
}
}
diff --git a/svx/source/sdr/overlay/overlaymanagerbuffered.cxx b/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
index 81b53b27bb0e..47d76f835d00 100644
--- a/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
+++ b/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
@@ -109,33 +109,33 @@ namespace sdr
void OverlayManagerBuffered::ImpRestoreBackground(const Region& rRegionPixel) const
{
- // local region
- Region aRegionPixel(rRegionPixel);
- RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
- Rectangle aRegionRectanglePixel;
-
// MapModes off
const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
const bool bMapModeWasEnabledSource(maBufferDevice.IsMapModeEnabled());
getOutputDevice().EnableMapMode(false);
((OverlayManagerBuffered*)this)->maBufferDevice.EnableMapMode(false);
- while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
+ // local region
+ RectangleVector aRectangles;
+ rRegionPixel.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
#ifdef DBG_UTIL
// #i72754# possible graphical region test only with non-pro
static bool bDoPaintForVisualControl(false);
+
if(bDoPaintForVisualControl)
{
getOutputDevice().SetLineColor(COL_LIGHTGREEN);
getOutputDevice().SetFillColor();
- getOutputDevice().DrawRect(aRegionRectanglePixel);
+ getOutputDevice().DrawRect(*aRectIter);
}
#endif
// restore the area
- const Point aTopLeft(aRegionRectanglePixel.TopLeft());
- const Size aSize(aRegionRectanglePixel.GetSize());
+ const Point aTopLeft(aRectIter->TopLeft());
+ const Size aSize(aRectIter->GetSize());
getOutputDevice().DrawOutDev(
aTopLeft, aSize, // destination
@@ -143,7 +143,33 @@ namespace sdr
maBufferDevice);
}
- aRegionPixel.EndEnumRects(aRegionHandle);
+ //Region aRegionPixel(rRegionPixel);
+ //RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
+ //Rectangle aRegionRectanglePixel;
+ //
+ //while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
+ //{
+#ifdef DBG_U//TIL
+ // // #i72754# possible graphical region test only with non-pro
+ // static bool bDoPaintForVisualControl(false);
+ // if(bDoPaintForVisualControl)
+ // {
+ // getOutputDevice().SetLineColor(COL_LIGHTGREEN);
+ // getOutputDevice().SetFillColor();
+ // getOutputDevice().DrawRect(aRegionRectanglePixel);
+ // }
+#endif //
+ // // restore the area
+ // const Point aTopLeft(aRegionRectanglePixel.TopLeft());
+ // const Size aSize(aRegionRectanglePixel.GetSize());
+ //
+ // getOutputDevice().DrawOutDev(
+ // aTopLeft, aSize, // destination
+ // aTopLeft, aSize, // source
+ // maBufferDevice);
+ //}
+ //
+ //aRegionPixel.EndEnumRects(aRegionHandle);
// restore MapModes
getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
@@ -175,24 +201,24 @@ namespace sdr
}
// also limit to buffer size
- const Rectangle aBufferDeviceRectanglePixel = Rectangle(Point(), maBufferDevice.GetOutputSizePixel());
+ const Rectangle aBufferDeviceRectanglePixel(Point(), maBufferDevice.GetOutputSizePixel());
aRegion.Intersect(aBufferDeviceRectanglePixel);
- // prepare to iterate over the rectangles from the region in pixels
- RegionHandle aRegionHandle(aRegion.BeginEnumRects());
- Rectangle aRegionRectanglePixel;
-
// MapModes off
const bool bMapModeWasEnabledDest(rSource.IsMapModeEnabled());
const bool bMapModeWasEnabledSource(maBufferDevice.IsMapModeEnabled());
rSource.EnableMapMode(false);
maBufferDevice.EnableMapMode(false);
- while(aRegion.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
+ // prepare to iterate over the rectangles from the region in pixels
+ RectangleVector aRectangles;
+ aRegion.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
// for each rectangle, save the area
- Point aTopLeft(aRegionRectanglePixel.TopLeft());
- Size aSize(aRegionRectanglePixel.GetSize());
+ const Point aTopLeft(aRectIter->TopLeft());
+ const Size aSize(aRectIter->GetSize());
maBufferDevice.DrawOutDev(
aTopLeft, aSize, // destination
@@ -200,7 +226,23 @@ namespace sdr
rSource);
}
- aRegion.EndEnumRects(aRegionHandle);
+ //RegionHandle aRegionHandle(aRegion.BeginEnumRects());
+ //Rectangle aRegionRectanglePixel;
+ //
+ //while(aRegion.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
+ //{
+ // // for each rectangle, save the area
+ // Point aTopLeft(aRegionRectanglePixel.TopLeft());
+ // Size aSize(aRegionRectanglePixel.GetSize());
+ //
+ // maBufferDevice.DrawOutDev(
+ // aTopLeft, aSize, // destination
+ // aTopLeft, aSize, // source
+ // rSource);
+ //
+ //}
+ //
+ //aRegion.EndEnumRects(aRegionHandle);
// restore MapModes
rSource.EnableMapMode(bMapModeWasEnabledDest);
diff --git a/svx/source/sdr/properties/itemsettools.cxx b/svx/source/sdr/properties/itemsettools.cxx
index b5f763ab6245..cea89d0e6248 100644
--- a/svx/source/sdr/properties/itemsettools.cxx
+++ b/svx/source/sdr/properties/itemsettools.cxx
@@ -21,10 +21,9 @@
#include <tools/debug.hxx>
#include <svl/itemset.hxx>
#include <svl/whiter.hxx>
-
-#include <vector>
#include <svx/svdogrp.hxx>
#include <svx/svditer.hxx>
+#include <vcl/region.hxx>
//////////////////////////////////////////////////////////////////////////////
// class to remember broadcast start positions
@@ -33,9 +32,6 @@ namespace sdr
{
namespace properties
{
- // helper vector to remember rectangles
- typedef ::std::vector< Rectangle > RectangleVector;
-
ItemChangeBroadcaster::ItemChangeBroadcaster(const SdrObject& rObj)
{
if(rObj.ISA(SdrObjGroup))
diff --git a/svx/source/svdraw/sdrpaintwindow.cxx b/svx/source/svdraw/sdrpaintwindow.cxx
index 3df44a1bac2b..9651ae710cae 100644
--- a/svx/source/svdraw/sdrpaintwindow.cxx
+++ b/svx/source/svdraw/sdrpaintwindow.cxx
@@ -56,9 +56,9 @@ void SdrPreRenderDevice::PreparePreRenderDevice()
void SdrPreRenderDevice::OutputPreRenderDevice(const Region& rExpandedRegion)
{
// region to pixels
- Region aRegionPixel(mrOutputDevice.LogicToPixel(rExpandedRegion));
- RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
- Rectangle aRegionRectanglePixel;
+ const Region aRegionPixel(mrOutputDevice.LogicToPixel(rExpandedRegion));
+ //RegionHandle aRegionHandle(aRegionPixel.BeginEnumRects());
+ //Rectangle aRegionRectanglePixel;
// MapModes off
sal_Bool bMapModeWasEnabledDest(mrOutputDevice.IsMapModeEnabled());
@@ -66,11 +66,14 @@ void SdrPreRenderDevice::OutputPreRenderDevice(const Region& rExpandedRegion)
mrOutputDevice.EnableMapMode(sal_False);
maPreRenderDevice.EnableMapMode(sal_False);
- while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
+ RectangleVector aRectangles;
+ aRegionPixel.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
// for each rectangle, copy the area
- const Point aTopLeft(aRegionRectanglePixel.TopLeft());
- const Size aSize(aRegionRectanglePixel.GetSize());
+ const Point aTopLeft(aRectIter->TopLeft());
+ const Size aSize(aRectIter->GetSize());
mrOutputDevice.DrawOutDev(
aTopLeft, aSize,
@@ -80,17 +83,43 @@ void SdrPreRenderDevice::OutputPreRenderDevice(const Region& rExpandedRegion)
#ifdef DBG_UTIL
// #i74769#
static bool bDoPaintForVisualControlRegion(false);
+
if(bDoPaintForVisualControlRegion)
{
- Color aColor((((((rand()&0x7f)|0x80)<<8L)|((rand()&0x7f)|0x80))<<8L)|((rand()&0x7f)|0x80));
+ const Color aColor((((((rand()&0x7f)|0x80)<<8L)|((rand()&0x7f)|0x80))<<8L)|((rand()&0x7f)|0x80));
+
mrOutputDevice.SetLineColor(aColor);
mrOutputDevice.SetFillColor();
- mrOutputDevice.DrawRect(aRegionRectanglePixel);
+ mrOutputDevice.DrawRect(*aRectIter);
}
#endif
}
- aRegionPixel.EndEnumRects(aRegionHandle);
+// while(aRegionPixel.GetEnumRects(aRegionHandle, aRegionRectanglePixel))
+// {
+// // for each rectangle, copy the area
+// const Point aTopLeft(aRegionRectanglePixel.TopLeft());
+// const Size aSize(aRegionRectanglePixel.GetSize());
+//
+// mrOutputDevice.DrawOutDev(
+// aTopLeft, aSize,
+// aTopLeft, aSize,
+// maPreRenderDevice);
+//
+//#ifdef DBG_UTIL
+// // #i74769#
+// static bool bDoPaintForVisualControlRegion(false);
+// if(bDoPaintForVisualControlRegion)
+// {
+// Color aColor((((((rand()&0x7f)|0x80)<<8L)|((rand()&0x7f)|0x80))<<8L)|((rand()&0x7f)|0x80));
+// mrOutputDevice.SetLineColor(aColor);
+// mrOutputDevice.SetFillColor();
+// mrOutputDevice.DrawRect(aRegionRectanglePixel);
+// }
+//#endif
+// }
+//
+// aRegionPixel.EndEnumRects(aRegionHandle);
mrOutputDevice.EnableMapMode(bMapModeWasEnabledDest);
maPreRenderDevice.EnableMapMode(bMapModeWasEnabledSource);
diff --git a/svx/source/svdraw/svdfmtf.cxx b/svx/source/svdraw/svdfmtf.cxx
index 0789a39f3af5..f6c485859713 100644
--- a/svx/source/svdraw/svdfmtf.cxx
+++ b/svx/source/svdraw/svdfmtf.cxx
@@ -800,9 +800,7 @@ void ImpSdrGDIMetaFileImport::checkClip()
{
if(maVD.IsClipRegion())
{
- Region aRegion(maVD.GetClipRegion());
-
- maClip = aRegion.ConvertToB2DPolyPolygon();
+ maClip = maVD.GetClipRegion().GetAsB2DPolyPolygon();
if(isClip())
{
diff --git a/svx/source/svdraw/svdpntv.cxx b/svx/source/svdraw/svdpntv.cxx
index db7feab72467..222b05c314c5 100644
--- a/svx/source/svdraw/svdpntv.cxx
+++ b/svx/source/svdraw/svdpntv.cxx
@@ -617,19 +617,31 @@ void SdrPaintView::CompleteRedraw(OutputDevice* pOut, const Region& rReg, sdr::c
#ifdef DBG_UTIL
// #i74769# test-paint repaint region
static bool bDoPaintForVisualControl(false);
+
if(bDoPaintForVisualControl)
{
- RegionHandle aRegionHandle(aOptimizedRepaintRegion.BeginEnumRects());
- Rectangle aRegionRectangle;
+ RectangleVector aRectangles;
+ aOptimizedRepaintRegion.GetRegionRectangles(aRectangles);
+
+ pWindow->SetLineColor(COL_LIGHTGREEN);
+ pWindow->SetFillColor();
- while(aOptimizedRepaintRegion.GetEnumRects(aRegionHandle, aRegionRectangle))
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- pWindow->SetLineColor(COL_LIGHTGREEN);
- pWindow->SetFillColor();
- pWindow->DrawRect(aRegionRectangle);
+ pWindow->DrawRect(*aRectIter);
}
- aOptimizedRepaintRegion.EndEnumRects(aRegionHandle);
+ //RegionHandle aRegionHandle(aOptimizedRepaintRegion.BeginEnumRects());
+ //Rectangle aRegionRectangle;
+ //
+ //while(aOptimizedRepaintRegion.GetEnumRects(aRegionHandle, aRegionRectangle))
+ //{
+ // pWindow->SetLineColor(COL_LIGHTGREEN);
+ // pWindow->SetFillColor();
+ // pWindow->DrawRect(aRegionRectangle);
+ //}
+ //
+ //aOptimizedRepaintRegion.EndEnumRects(aRegionHandle);
}
#endif
}
@@ -840,25 +852,6 @@ Region SdrPaintView::OptimizeDrawLayersRegion(OutputDevice* pOut, const Region&
if(!pWindow->GetPaintRegion().IsEmpty())
{
aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion());
-
-#ifdef DBG_UTIL
- // #i74769# test-paint repaint region
- static bool bDoPaintForVisualControl(false);
- if(bDoPaintForVisualControl)
- {
- RegionHandle aRegionHandle(aOptimizedRepaintRegion.BeginEnumRects());
- Rectangle aRegionRectangle;
-
- while(aOptimizedRepaintRegion.GetEnumRects(aRegionHandle, aRegionRectangle))
- {
- pWindow->SetLineColor(COL_LIGHTGREEN);
- pWindow->SetFillColor();
- pWindow->DrawRect(aRegionRectangle);
- }
-
- aOptimizedRepaintRegion.EndEnumRects(aRegionHandle);
- }
-#endif
}
}
}
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index b1ac5c30314c..6dabfbcd3319 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -1729,12 +1729,20 @@ void ViewShell::Paint(const Rectangle &rRect)
if ( mbInEndAction && GetWin() )
{
- Region aRegion( GetWin()->GetPaintRegion() );
- RegionHandle hHdl( aRegion.BeginEnumRects() );
- Rectangle aRect;
- while ( aRegion.GetNextEnumRect( hHdl, aRect ) )
- Imp()->AddPaintRect( aRect );
- aRegion.EndEnumRects( hHdl );
+ const Region aRegion(GetWin()->GetPaintRegion());
+ RectangleVector aRectangles;
+ aRegion.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
+ {
+ Imp()->AddPaintRect(*aRectIter);
+ }
+
+ //RegionHandle hHdl( aRegion.BeginEnumRects() );
+ //Rectangle aRect;
+ //while ( aRegion.GetEnumRects( hHdl, aRect ) )
+ // Imp()->AddPaintRect( aRect );
+ //aRegion.EndEnumRects( hHdl );
}
else if ( SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) &&
GetOut() == GetWin() )
diff --git a/toolkit/source/awt/vclxregion.cxx b/toolkit/source/awt/vclxregion.cxx
index 7ed03bfc08a2..2375befe403a 100644
--- a/toolkit/source/awt/vclxregion.cxx
+++ b/toolkit/source/awt/vclxregion.cxx
@@ -141,15 +141,24 @@ void VCLXRegion::xOrRegion( const ::com::sun::star::uno::Reference< ::com::sun::
{
::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
- sal_uLong nRects = maRegion.GetRectCount();
- ::com::sun::star::uno::Sequence< ::com::sun::star::awt::Rectangle > aRects( nRects );
-
- Rectangle aRect;
- sal_uInt32 nR = 0;
- RegionHandle h = maRegion.BeginEnumRects();
- while ( maRegion.GetNextEnumRect( h, aRect ) )
- aRects.getArray()[nR++] = AWTRectangle( aRect );
- maRegion.EndEnumRects( h );
+ RectangleVector aRectangles;
+ maRegion.GetRegionRectangles(aRectangles);
+
+// sal_uLong nRects = maRegion.GetRectCount();
+ ::com::sun::star::uno::Sequence< ::com::sun::star::awt::Rectangle > aRects(aRectangles.size());
+ sal_uInt32 a(0);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
+ {
+ aRects.getArray()[a++] = AWTRectangle(*aRectIter);
+ }
+
+ //Rectangle aRect;
+ //sal_uInt32 nR = 0;
+ //RegionHandle h = maRegion.BeginEnumRects();
+ //while ( maRegion.GetEnumRects( h, aRect ) )
+ // aRects.getArray()[nR++] = AWTRectangle( aRect );
+ //maRegion.EndEnumRects( h );
return aRects;
}
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 8daa5bb87333..d9b19fa332c0 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -246,6 +246,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/gdi/print \
vcl/source/gdi/regband \
vcl/source/gdi/region \
+ vcl/source/gdi/regionband \
vcl/source/gdi/salgdilayout \
vcl/source/gdi/sallayout \
vcl/source/gdi/salmisc \
diff --git a/vcl/aqua/source/gdi/salgdicommon.cxx b/vcl/aqua/source/gdi/salgdicommon.cxx
index afedd3b9a339..ad484e28d84f 100644
--- a/vcl/aqua/source/gdi/salgdicommon.cxx
+++ b/vcl/aqua/source/gdi/salgdicommon.cxx
@@ -27,7 +27,6 @@
#include "aqua/salgdi.h"
#include "fontsubset.hxx"
-#include "region.h"
#include "sft.hxx"
using namespace vcl;
@@ -1444,24 +1443,31 @@ bool AquaSalGraphics::setClipRegion( const Region& i_rClip )
mxClipPath = CGPathCreateMutable();
// set current path, either as polypolgon or sequence of rectangles
- if( i_rClip.HasPolyPolygon() )
+ if(i_rClip.HasPolyPolygonOrB2DPolyPolygon())
{
- basegfx::B2DPolyPolygon aClip( const_cast<Region&>(i_rClip).ConvertToB2DPolyPolygon() );
+ const basegfx::B2DPolyPolygon aClip(i_rClip.GetAsB2DPolyPolygon());
+
AddPolyPolygonToPath( mxClipPath, aClip, !getAntiAliasB2DDraw(), false );
}
else
{
- long nX, nY, nW, nH;
- ImplRegionInfo aInfo;
- bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
- while( bRegionRect )
+ RectangleVector aRectangles;
+ i_rClip.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- if( nW && nH )
+ const long nW(aRectIter->Right() - aRectIter->Left() + 1); // uses +1 logic in original
+
+ if(nW)
{
- CGRect aRect = { { static_cast<CGFloat>(nX), static_cast<CGFloat>(nY) }, { static_cast<CGFloat>(nW), static_cast<CGFloat>(nH) } };
- CGPathAddRect( mxClipPath, NULL, aRect );
+ const long nH(aRectIter->Bottom() - aRectIter->Top() + 1); // uses +1 logic in original
+
+ if(nH)
+ {
+ CGRect aRect = {{ aRectIter->Left(), aRectIter->Top() }, { nW, nH }};
+ CGPathAddRect( mxClipPath, NULL, aRect );
+ }
}
- bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
}
}
// set the current path as clip region
diff --git a/vcl/generic/fontmanager/fontsubst.cxx b/vcl/generic/fontmanager/fontsubst.cxx
index 22b3d837863b..35f8294900be 100644
--- a/vcl/generic/fontmanager/fontsubst.cxx
+++ b/vcl/generic/fontmanager/fontsubst.cxx
@@ -30,7 +30,6 @@
#include "outdev.h"
#include "fontsubset.hxx"
#include "salprn.hxx"
-#include "region.h"
#include <unotools/fontdefs.hxx>
#include <list>
diff --git a/vcl/generic/print/genpspgraphics.cxx b/vcl/generic/print/genpspgraphics.cxx
index 10af66051ddb..b9a1164b6aa8 100644
--- a/vcl/generic/print/genpspgraphics.cxx
+++ b/vcl/generic/print/genpspgraphics.cxx
@@ -43,7 +43,6 @@
#include "outfont.hxx"
#include "fontsubset.hxx"
#include "salprn.hxx"
-#include "region.h"
#include "langboost.hxx"
#include <config_graphite.h>
@@ -322,20 +321,45 @@ void GenPspGraphics::ResetClipRegion()
bool GenPspGraphics::setClipRegion( const Region& i_rClip )
{
// TODO: support polygonal clipregions here
- m_pPrinterGfx->BeginSetClipRegion( i_rClip.GetRectCount() );
+ RectangleVector aRectangles;
+ i_rClip.GetRegionRectangles(aRectangles);
+ m_pPrinterGfx->BeginSetClipRegion(aRectangles.size());
- ImplRegionInfo aInfo;
- long nX, nY, nW, nH;
- bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
- while( bRegionRect )
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- if ( nW && nH )
+ const long nW(aRectIter->GetWidth());
+
+ if(nW)
{
- m_pPrinterGfx->UnionClipRegion( nX, nY, nW, nH );
+ const long nH(aRectIter->GetHeight());
+
+ if(nH)
+ {
+ m_pPrinterGfx->UnionClipRegion(
+ aRectIter->Left(),
+ aRectIter->Top(),
+ nW,
+ nH);
+ }
}
- bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
}
+
m_pPrinterGfx->EndSetClipRegion();
+
+ //m_pPrinterGfx->BeginSetClipRegion( i_rClip.GetRectCount() );
+ //
+ //ImplRegionInfo aInfo;
+ //long nX, nY, nW, nH;
+ //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
+ //while( bRegionRect )
+ //{
+ // if ( nW && nH )
+ // {
+ // m_pPrinterGfx->UnionClipRegion( nX, nY, nW, nH );
+ // }
+ // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
+ //}
+ //m_pPrinterGfx->EndSetClipRegion();
return true;
}
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index dbd233c3692f..baab42e5d25d 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -37,7 +37,6 @@
#include <sys/stat.h>
#endif
-#include <region.h>
#include <stdio.h>
inline void dbgOut( const basebmp::BitmapDeviceSharedPtr&
@@ -165,21 +164,30 @@ void SvpSalGraphics::ensureClip()
m_aClipMap = basebmp::createBitmapDevice( aSize, false, basebmp::Format::ONE_BIT_MSB_GREY );
m_aClipMap->clear( basebmp::Color(0xFFFFFFFF) );
- // fprintf( stderr, "non rect clip region set with %d rects:\n",
- // (int)m_aClipRegion.GetRectCount() );
- ImplRegionInfo aInfo;
- long nX, nY, nW, nH;
- bool bRegionRect = m_aClipRegion.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
- while( bRegionRect )
+ RectangleVector aRectangles;
+ m_aClipRegion.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- if ( nW && nH )
+ const long nW(aRectIter->GetWidth());
+ if(nW)
{
- basegfx::B2DPolyPolygon aFull;
- aFull.append( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX, nY, nX+nW, nY+nH ) ) );
- m_aClipMap->fillPolyPolygon( aFull, basebmp::Color(0), basebmp::DrawMode_PAINT );
+ const long nH(aRectIter->GetHeight());
+
+ if(nH)
+ {
+ basegfx::B2DPolyPolygon aFull;
+
+ aFull.append(
+ basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRectangle(
+ aRectIter->Left(),
+ aRectIter->Top(),
+ aRectIter->Left() + nW,
+ aRectIter->Top() + nH)));
+ m_aClipMap->fillPolyPolygon(aFull, basebmp::Color(0), basebmp::DrawMode_PAINT);
+ }
}
- // fprintf( stderr, "\t %ld,%ld %ldx%ld\n", nX, nY, nW, nH );
- bRegionRect = m_aClipRegion.ImplGetNextRect( aInfo, nX, nY, nW, nH );
}
m_bClipSetup = true;
}
@@ -213,17 +221,17 @@ bool SvpSalGraphics::isClippedSetup( const basegfx::B2IBox &aRange, SvpSalGraphi
// then see if we are overlapping with just one
int nHit = 0;
- Rectangle aIterRect, aHitRect;
- RegionHandle aHnd = m_aClipRegion.BeginEnumRects();
- while( m_aClipRegion.GetNextEnumRect( aHnd, aIterRect ) )
+ Rectangle aHitRect;
+ RectangleVector aRectangles;
+ m_aClipRegion.GetRegionRectangles(aRectangles);
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- if( aIterRect.IsOver( aRect ) )
+ if( aRectIter->IsOver( aRect ) )
{
- aHitRect = aIterRect;
+ aHitRect = *aRectIter;
nHit++;
}
}
- m_aClipRegion.EndEnumRects (aHnd);
if( nHit == 0 ) // rendering outside any clipping region
{
@@ -270,14 +278,23 @@ bool SvpSalGraphics::setClipRegion( const Region& i_rClip )
m_aClipRegion = i_rClip;
m_aClipMap.reset();
if( i_rClip.IsEmpty() )
+ {
m_bClipSetup = true;
+ return true;
+ }
+
+ RectangleVector aRectangles;
+ i_rClip.GetRegionRectangles(aRectangles);
- else if( i_rClip.GetRectCount() == 1 )
+ if(1 == aRectangles.size())
{
m_aClipMap.reset();
- Rectangle aBoundRect( i_rClip.GetBoundRect() );
- m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice,
- basegfx::B2IBox(aBoundRect.Left(),aBoundRect.Top(),aBoundRect.Right(),aBoundRect.Bottom()) );
+
+ const Rectangle& aBoundRect = aRectangles[0];
+ m_aDevice = basebmp::subsetBitmapDevice(
+ m_aOrigDevice,
+ basegfx::B2IBox(aBoundRect.Left(),aBoundRect.Top(),aBoundRect.Right(),aBoundRect.Bottom()) );
+
m_bClipSetup = true;
}
else
diff --git a/vcl/inc/region.h b/vcl/inc/region.h
deleted file mode 100644
index 457bb1e6fa79..000000000000
--- a/vcl/inc/region.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#ifndef _SV_REGION_H
-#define _SV_REGION_H
-
-#include <vcl/regband.hxx>
-#include <tools/poly.hxx>
-#include <vcl/region.hxx>
-
-// -----------------
-// - Hilfsmethoden -
-// -----------------
-
-#ifdef DBG_UTIL
-const char* ImplDbgTestRegion( const void* pObj );
-#endif
-
-// --------------------
-// - ImplRegionHandle -
-// --------------------
-
-struct ImplRegionHandle
-{
- Region* mpRegion;
- ImplRegionBand* mpCurrRectBand;
- ImplRegionBandSep* mpCurrRectBandSep;
- sal_Bool mbFirst;
-};
-
-// ------------------
-// - ImplRegionInfo -
-// ------------------
-
-struct ImplRegionInfo
-{
- void* mpVoidCurrRectBand;
- void* mpVoidCurrRectBandSep;
-};
-
-// --------------
-// - ImplRegion -
-// --------------
-
-struct ImplRegionBase
-{
-public:
- ImplRegionBase( int nCount = 1 ); // TODO: replace manual refcounting
- virtual ~ImplRegionBase();
-public:
- sal_uIntPtr mnRefCount;
- sal_uIntPtr mnRectCount;
- PolyPolygon* mpPolyPoly;
- basegfx::B2DPolyPolygon* mpB2DPolyPoly;
-};
-
-class ImplRegion : public ImplRegionBase
-{
- friend class Region;
-
-private:
- ImplRegionBand* mpFirstBand; // root of the list with y-bands
- ImplRegionBand* mpLastCheckedBand;
-
-public:
- ImplRegion();
- ImplRegion( const PolyPolygon& rPolyPoly );
- ImplRegion( const basegfx::B2DPolyPolygon& );
- ImplRegion( const ImplRegion& rImplRegion );
- ~ImplRegion();
-
- ImplRegionBand* ImplGetFirstRegionBand() const { return mpFirstBand; }
- PolyPolygon* ImplGetPolyPoly() const { return mpPolyPoly; }
-
- void CreateBandRange( long nYTop, long nYBottom );
- void InsertBands( long nYTop, long nYBottom );
- sal_Bool InsertSingleBand( ImplRegionBand* mpImplRegionBand,
- long nYBandPosition );
- sal_Bool InsertLine( const Point & rFirstPoint,
- const Point & rSecondPoint,
- long nLineID );
- sal_Bool InsertPoint( const Point &rPoint,
- long nLineID,
- sal_Bool bEndPoint, LineType eLineType );
-
- /** Insert one band either after another band or as the first or only
- band. Both the forward as well as the backward links are updated.
- @param pPreviousBand
- When <NULL/> then pBandToInsert is inserted as first band or as
- only band when there are no other bands.
- When not <NULL/> then pBandToInsert is inserted directly after
- pPreviousBand.
- @param pBandToInsert
- The band to insert.
- */
- void InsertBand (ImplRegionBand* pPreviousBand,
- ImplRegionBand* pBandToInsert);
-
- void Union( long nLeft, long nTop, long nRight, long nBottom );
- void Exclude( long nLeft, long nTop, long nRight, long nBottom );
- void XOr( long nLeft, long nTop, long nRight, long nBottom );
-
- // remove emtpy rects
- sal_Bool OptimizeBandList();
-
- friend SvStream& operator>>( SvStream& rIStm, Region& rRegion );
- friend SvStream& operator<<( SvStream& rOStm, const Region& rRegion );
-};
-
-#endif // _SV_REGION_H
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/regionband.hxx b/vcl/inc/regionband.hxx
new file mode 100644
index 000000000000..89657036adff
--- /dev/null
+++ b/vcl/inc/regionband.hxx
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef _SV_REGIONBAND_HXX
+#define _SV_REGIONBAND_HXX
+
+#include <vcl/regband.hxx>
+#include <vcl/region.hxx>
+
+#ifdef DBG_UTIL
+const char* ImplDbgTestRegionBand(const void*);
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+
+class RegionBand
+{
+private:
+ friend const char* ImplDbgTestRegionBand(const void*);
+
+ ImplRegionBand* mpFirstBand; // root of the list with y-bands
+ ImplRegionBand* mpLastCheckedBand;
+
+ void implReset();
+
+public:
+ RegionBand();
+ RegionBand(const RegionBand&);
+ RegionBand& operator=(const RegionBand&);
+ RegionBand(const Rectangle&);
+ ~RegionBand();
+
+ bool operator==( const RegionBand& rRegionBand ) const;
+ bool operator!=( const RegionBand& rRegionBand ) const { return !(RegionBand::operator==( rRegionBand )); }
+
+ void load(SvStream& rIStrm);
+ void save(SvStream& rIStrm) const;
+
+ bool isSingleRectangle() const;
+ ImplRegionBand* ImplGetFirstRegionBand() const { return mpFirstBand; }
+ void ImplAddMissingBands(const long nTop, const long nBottom);
+ void InsertBand(ImplRegionBand* pPreviousBand, ImplRegionBand* pBandToInsert);
+ void processPoints();
+ void CreateBandRange(long nYTop, long nYBottom);
+ bool InsertLine(const Point& rStartPt, const Point& rEndPt, long nLineId);
+ bool InsertPoint(const Point &rPoint, long nLineID, bool bEndPoint, LineType eLineType);
+ bool OptimizeBandList();
+ void Move(long nHorzMove, long nVertMove);
+ void Scale(double fScaleX, double fScaleY);
+ void InsertBands(long nTop, long nBottom);
+ bool InsertSingleBand(ImplRegionBand* pBand, long nYBandPosition);
+ void Union(long nLeft, long nTop, long nRight, long nBottom);
+ void Intersect(long nLeft, long nTop, long nRight, long nBottom);
+ void Union(const RegionBand& rSource);
+ void Exclude(long nLeft, long nTop, long nRight, long nBottom);
+ void XOr(long nLeft, long nTop, long nRight, long nBottom);
+ void Intersect(const RegionBand& rSource);
+ bool Exclude(const RegionBand& rSource);
+ void XOr(const RegionBand& rSource);
+ Rectangle GetBoundRect() const;
+ bool IsInside(const Point& rPoint) const;
+ sal_uInt32 getRectangleCount() const; // only users are Region::Intersect and PSWriter::ImplBmp
+ void GetRegionRectangles(RectangleVector& rTarget) const;
+};
+
+#endif // _SV_REGIONBAND_HXX
+
+//////////////////////////////////////////////////////////////////////////////
+//eof
diff --git a/vcl/source/gdi/bitmap.cxx b/vcl/source/gdi/bitmap.cxx
index 2bb1a9d55889..7ba90c7dbc53 100644
--- a/vcl/source/gdi/bitmap.cxx
+++ b/vcl/source/gdi/bitmap.cxx
@@ -1281,38 +1281,92 @@ Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
if( pReadAcc )
{
- Rectangle aSubRect;
+ //Rectangle aSubRect;
const long nLeft = aRect.Left();
const long nTop = aRect.Top();
const long nRight = aRect.Right();
const long nBottom = aRect.Bottom();
const BitmapColor aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
- aRegion.ImplBeginAddRect();
+ //RectangleVector aRectangles;
+ //aRegion.ImplBeginAddRect();
+ std::vector< long > aLine;
+ long nYStart(nTop);
+ long nY(nTop);
- for( long nY = nTop; nY <= nBottom; nY++ )
+ for( ; nY <= nBottom; nY++ )
{
- aSubRect.Top() = aSubRect.Bottom() = nY;
+ //aSubRect.Top() = aSubRect.Bottom() = nY;
+ std::vector< long > aNewLine;
+ long nX(nLeft);
- for( long nX = nLeft; nX <= nRight; )
+ for( ; nX <= nRight; )
{
while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
nX++;
if( nX <= nRight )
{
- aSubRect.Left() = nX;
+ aNewLine.push_back(nX);
+ //aSubRect.Left() = nX;
while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
nX++;
- aSubRect.Right() = nX - 1L;
- aRegion.ImplAddRect( aSubRect );
+ //aSubRect.Right() = nX - 1L;
+ aNewLine.push_back(nX - 1);
+
+ //aRegion.ImplAddRect( aSubRect );
+ //aRectangles.push_back(aSubRect);
+ //aRegion.Union(aSubRect);
}
}
+
+ if(aNewLine != aLine)
+ {
+ // need to write aLine, it's different from the next line
+ if(aLine.size())
+ {
+ Rectangle aSubRect;
+
+ // enter y values and proceed ystart
+ aSubRect.Top() = nYStart;
+ aSubRect.Bottom() = nY ? nY - 1 : 0;
+
+ for(sal_uInt32 a(0); a < aLine.size();)
+ {
+ aSubRect.Left() = aLine[a++];
+ aSubRect.Right() = aLine[a++];
+ aRegion.Union(aSubRect);
+ }
+ }
+
+ // copy line as new line
+ aLine = aNewLine;
+ nYStart = nY;
+ }
}
- aRegion.ImplEndAddRect();
+ // write last line if used
+ if(aLine.size())
+ {
+ Rectangle aSubRect;
+
+ // enter y values
+ aSubRect.Top() = nYStart;
+ aSubRect.Bottom() = nY ? nY - 1 : 0;
+
+ for(sal_uInt32 a(0); a < aLine.size();)
+ {
+ aSubRect.Left() = aLine[a++];
+ aSubRect.Right() = aLine[a++];
+ aRegion.Union(aSubRect);
+ }
+ }
+
+ //aRegion.ImplEndAddRect();
+ //aRegion.SetRegionRectangles(aRectangles);
+
( (Bitmap*) this )->ReleaseAccess( pReadAcc );
}
else
diff --git a/vcl/source/gdi/bmpacc3.cxx b/vcl/source/gdi/bmpacc3.cxx
index 791a75d9329d..c35f531c5433 100644
--- a/vcl/source/gdi/bmpacc3.cxx
+++ b/vcl/source/gdi/bmpacc3.cxx
@@ -243,4 +243,133 @@ void BitmapWriteAccess::DrawRect( const Rectangle& rRect )
}
}
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::FillPolygon( const Polygon& rPoly )
+{
+ const sal_uInt16 nSize = rPoly.GetSize();
+
+ if( nSize && mpFillColor )
+ {
+ const BitmapColor& rFillColor = *mpFillColor;
+ Region aRegion( rPoly );
+// Rectangle aRect;
+
+ aRegion.Intersect( Rectangle( Point(), Size( Width(), Height() ) ) );
+
+ if( !aRegion.IsEmpty() )
+ {
+ RectangleVector aRectangles;
+ aRegion.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
+ {
+ for(long nY = aRectIter->Top(), nEndY = aRectIter->Bottom(); nY <= nEndY; nY++)
+ {
+ for(long nX = aRectIter->Left(), nEndX = aRectIter->Right(); nX <= nEndX; nX++)
+ {
+ SetPixel(nY, nX, rFillColor);
+ }
+ }
+ }
+
+ //RegionHandle aRegHandle( aRegion.BeginEnumRects() );
+ //
+ //while( aRegion.GetEnumRects( aRegHandle, aRect ) )
+ // for( long nY = aRect.Top(), nEndY = aRect.Bottom(); nY <= nEndY; nY++ )
+ // for( long nX = aRect.Left(), nEndX = aRect.Right(); nX <= nEndX; nX++ )
+ // SetPixel( nY, nX, rFillColor );
+ //
+ //aRegion.EndEnumRects( aRegHandle );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawPolygon( const Polygon& rPoly )
+{
+ if( mpFillColor )
+ FillPolygon( rPoly );
+
+ if( mpLineColor && ( !mpFillColor || ( *mpFillColor != *mpLineColor ) ) )
+ {
+ const sal_uInt16 nSize = rPoly.GetSize();
+
+ for( sal_uInt16 i = 0, nSize1 = nSize - 1; i < nSize1; i++ )
+ DrawLine( rPoly[ i ], rPoly[ i + 1 ] );
+
+ if( rPoly[ nSize - 1 ] != rPoly[ 0 ] )
+ DrawLine( rPoly[ nSize - 1 ], rPoly[ 0 ] );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::FillPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ const sal_uInt16 nCount = rPolyPoly.Count();
+
+ if( nCount && mpFillColor )
+ {
+ const BitmapColor& rFillColor = *mpFillColor;
+ Region aRegion( rPolyPoly );
+ //Rectangle aRect;
+
+ aRegion.Intersect( Rectangle( Point(), Size( Width(), Height() ) ) );
+
+ if( !aRegion.IsEmpty() )
+ {
+ RectangleVector aRectangles;
+ aRegion.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
+ {
+ for(long nY = aRectIter->Top(), nEndY = aRectIter->Bottom(); nY <= nEndY; nY++)
+ {
+ for(long nX = aRectIter->Left(), nEndX = aRectIter->Right(); nX <= nEndX; nX++)
+ {
+ SetPixel(nY, nX, rFillColor);
+ }
+ }
+ }
+
+ //RegionHandle aRegHandle( aRegion.BeginEnumRects() );
+ //
+ //while( aRegion.GetEnumRects( aRegHandle, aRect ) )
+ // for( long nY = aRect.Top(), nEndY = aRect.Bottom(); nY <= nEndY; nY++ )
+ // for( long nX = aRect.Left(), nEndX = aRect.Right(); nX <= nEndX; nX++ )
+ // SetPixel( nY, nX, rFillColor );
+ //
+ //aRegion.EndEnumRects( aRegHandle );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ if( mpFillColor )
+ FillPolyPolygon( rPolyPoly );
+
+ if( mpLineColor && ( !mpFillColor || ( *mpFillColor != *mpLineColor ) ) )
+ {
+ for( sal_uInt16 n = 0, nCount = rPolyPoly.Count(); n < nCount; )
+ {
+ const Polygon& rPoly = rPolyPoly[ n++ ];
+ const sal_uInt16 nSize = rPoly.GetSize();
+
+ if( nSize )
+ {
+ for( sal_uInt16 i = 0, nSize1 = nSize - 1; i < nSize1; i++ )
+ DrawLine( rPoly[ i ], rPoly[ i + 1 ] );
+
+ if( rPoly[ nSize - 1 ] != rPoly[ 0 ] )
+ DrawLine( rPoly[ nSize - 1 ], rPoly[ 0 ] );
+ }
+ }
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx
index fce3d091ab9c..77a426f2da7e 100644
--- a/vcl/source/gdi/gdimtf.cxx
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -1282,8 +1282,8 @@ void GDIMetaFile::Rotate( long nAngle10 )
{
MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
- if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygon() )
- aMtf.AddAction( new MetaClipRegionAction( Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), sal_True ) );
+ if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
+ aMtf.AddAction( new MetaClipRegionAction( Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), sal_True ) );
else
{
pAction->Duplicate();
@@ -1306,8 +1306,8 @@ void GDIMetaFile::Rotate( long nAngle10 )
MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction;
const Region& rRegion = pAct->GetRegion();
- if( rRegion.HasPolyPolygon() )
- aMtf.AddAction( new MetaISectRegionClipRegionAction( Region( ImplGetRotatedPolyPolygon( rRegion.GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
+ if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
+ aMtf.AddAction( new MetaISectRegionClipRegionAction( Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
else
{
pAction->Duplicate();
@@ -2600,12 +2600,12 @@ sal_uLong GDIMetaFile::GetChecksum() const
MetaClipRegionAction* pAct = dynamic_cast< MetaClipRegionAction* >(pAction);
const Region& rRegion = pAct->GetRegion();
- if(rRegion.HasPolyPolygon())
+ if(rRegion.HasPolyPolygonOrB2DPolyPolygon())
{
// It has shown that this is a possible bottleneck for checksum calculation.
// In worst case a very expensive RegionHandle representation gets created.
// In this case it's cheaper to use the PolyPolygon
- const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetB2DPolyPolygon());
+ const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetAsB2DPolyPolygon());
const sal_uInt32 nPolyCount(aPolyPolygon.count());
SVBT64 aSVBT64;
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
index 65119b6141f9..090f22990a80 100644
--- a/vcl/source/gdi/outdev.cxx
+++ b/vcl/source/gdi/outdev.cxx
@@ -41,7 +41,6 @@
#include <svdata.hxx>
#include <window.h>
#include <outdev.h>
-#include <region.h>
#include <outdata.hxx>
#include <basegfx/point/b2dpoint.hxx>
@@ -322,7 +321,7 @@ void OutputDevice::ImplDrawPolyPolygon( sal_uInt16 nPoly, const PolyPolygon& rPo
// =======================================================================
OutputDevice::OutputDevice() :
- maRegion( REGION_NULL ),
+ maRegion(true),
maFillColor( COL_WHITE ),
maTextLineColor( COL_TRANSPARENT ),
maSettings( Application::GetSettings() )
@@ -530,23 +529,35 @@ void OutputDevice::ImplReMirror( Rectangle &rRect ) const
}
void OutputDevice::ImplReMirror( Region &rRegion ) const
{
- long nX;
- long nY;
- long nWidth;
- long nHeight;
- ImplRegionInfo aInfo;
- sal_Bool bRegionRect;
- Region aMirroredRegion;
+ RectangleVector aRectangles;
+ rRegion.GetRegionRectangles(aRectangles);
+ Region aMirroredRegion;
- bRegionRect = rRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
- while ( bRegionRect )
+ for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
- ImplReMirror( aRect );
- aMirroredRegion.Union( aRect );
- bRegionRect = rRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ ImplReMirror(*aRectIter);
+ aMirroredRegion.Union(*aRectIter);
}
+
rRegion = aMirroredRegion;
+
+// long nX;
+// long nY;
+// long nWidth;
+// long nHeight;
+// ImplRegionInfo aInfo;
+// sal_Bool bRegionRect;
+// Region aMirroredRegion;
+//
+// bRegionRect = rRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+// while ( bRegionRect )
+// {
+// Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
+// ImplReMirror( aRect );
+// aMirroredRegion.Union( aRect );
+// bRegionRect = rRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+// }
+// rRegion = aMirroredRegion;
}
SalGraphics* OutputDevice::ImplGetGraphics() const
@@ -1004,7 +1015,7 @@ void OutputDevice::ImplSetClipRegion( const Region* pRegion )
{
if ( mbClipRegion )
{
- maRegion = Region( REGION_NULL );
+ maRegion = Region(true);
mbClipRegion = sal_False;
mbInitClipRegion = sal_True;
}
@@ -1033,13 +1044,14 @@ void OutputDevice::SetClipRegion()
void OutputDevice::SetClipRegion( const Region& rRegion )
{
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
- DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
if ( mpMetaFile )
mpMetaFile->AddAction( new MetaClipRegionAction( rRegion, sal_True ) );
- if ( rRegion.GetType() == REGION_NULL )
+ if ( rRegion.IsNull() )
+ {
ImplSetClipRegion( NULL );
+ }
else
{
Region aRegion = LogicToPixel( rRegion );
@@ -1063,7 +1075,7 @@ Region OutputDevice::GetActiveClipRegion() const
if ( GetOutDevType() == OUTDEV_WINDOW )
{
- Region aRegion( REGION_NULL );
+ Region aRegion(true);
Window* pWindow = (Window*)this;
if ( pWindow->mpWindowImpl->mbInPaint )
{
@@ -1115,11 +1127,8 @@ void OutputDevice::IntersectClipRegion( const Rectangle& rRect )
void OutputDevice::IntersectClipRegion( const Region& rRegion )
{
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
- DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
-
- RegionType eType = rRegion.GetType();
- if ( eType != REGION_NULL )
+ if(!rRegion.IsNull())
{
if ( mpMetaFile )
mpMetaFile->AddAction( new MetaISectRegionClipRegionAction( rRegion ) );
diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx
index e17842609cf7..915fb89aa122 100644
--- a/vcl/source/gdi/outdev2.cxx
+++ b/vcl/source/gdi/outdev2.cxx
@@ -37,7 +37,6 @@
#include <image.h>
#include <outdev.h>
#include <window.h>
-#include <region.h>
#include <outdata.hxx>
DBG_NAMEEX( OutputDevice )
@@ -1945,7 +1944,7 @@ void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask
// do painting
const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
- long nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
+ long nX, nY; // , nWorkX, nWorkY, nWorkWidth, nWorkHeight;
long* pMapX = new long[ nSrcWidth + 1 ];
long* pMapY = new long[ nSrcHeight + 1 ];
const bool bOldMap = mbMap;
@@ -1960,22 +1959,38 @@ void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask
pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
// walk through all rectangles of mask
- Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
- ImplRegionInfo aInfo;
- bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ const Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel())));
+ RectangleVector aRectangles;
+ aWorkRgn.GetRegionRectangles(aRectangles);
- while( bRgnRect )
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- Bitmap aBandBmp( aPaint );
- const Rectangle aBandRect( Point( nWorkX, nWorkY ), Size( nWorkWidth, nWorkHeight ) );
- const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
- const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
-
- aBandBmp.Crop( aBandRect );
- ImplDrawBitmap( aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION );
- bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]);
+ const Size aMapSz(
+ pMapX[aRectIter->Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
+ pMapY[aRectIter->Bottom() + 1] - aMapPt.Y()); // same for Y
+ Bitmap aBandBmp(aPaint);
+
+ aBandBmp.Crop(*aRectIter);
+ ImplDrawBitmap(aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION);
}
+ //Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
+ //ImplRegionInfo aInfo;
+ //sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ //
+ //while( bRgnRect )
+ //{
+ // Bitmap aBandBmp( aPaint );
+ // const Rectangle aBandRect( Point( nWorkX, nWorkY ), Size( nWorkWidth, nWorkHeight ) );
+ // const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
+ // const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
+ //
+ // aBandBmp.Crop( aBandRect );
+ // ImplDrawBitmap( aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION );
+ // bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ //}
+
mbMap = bOldMap;
delete[] pMapX;
@@ -2028,7 +2043,7 @@ void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor,
// do painting
const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
- long nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
+ long nX, nY; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
long* pMapX = new long[ nSrcWidth + 1 ];
long* pMapY = new long[ nSrcHeight + 1 ];
GDIMetaFile* pOldMetaFile = mpMetaFile;
@@ -2050,19 +2065,33 @@ void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor,
pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
// walk through all rectangles of mask
- Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
- ImplRegionInfo aInfo;
- bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ const Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel())));
+ RectangleVector aRectangles;
+ aWorkRgn.GetRegionRectangles(aRectangles);
- while( bRgnRect )
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
- const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
+ const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]);
+ const Size aMapSz(
+ pMapX[aRectIter->Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
+ pMapY[aRectIter->Bottom() + 1] - aMapPt.Y()); // same for Y
- DrawRect( Rectangle( aMapPt, aMapSz ) );
- bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ DrawRect(Rectangle(aMapPt, aMapSz));
}
+ //Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
+ //ImplRegionInfo aInfo;
+ //sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ //
+ //while( bRgnRect )
+ //{
+ // const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
+ // const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
+ //
+ // DrawRect( Rectangle( aMapPt, aMapSz ) );
+ // bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ //}
+
Pop();
delete[] pMapX;
delete[] pMapY;
diff --git a/vcl/source/gdi/outmap.cxx b/vcl/source/gdi/outmap.cxx
index 25cbb53460bf..7ef70f8b9411 100644
--- a/vcl/source/gdi/outmap.cxx
+++ b/vcl/source/gdi/outmap.cxx
@@ -34,7 +34,6 @@
#include <vcl/outdev.hxx>
#include <svdata.hxx>
-#include <region.h>
#include <window.h>
#include <outdev.h>
#include <salgdi.hxx>
@@ -679,8 +678,6 @@ Rectangle OutputDevice::ImplDevicePixelToLogic( const Rectangle& rPixelRect ) co
Region OutputDevice::ImplPixelToDevicePixel( const Region& rRegion ) const
{
- DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
-
if ( !mnOutOffX && !mnOutOffY )
return rRegion;
@@ -1132,48 +1129,73 @@ PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly ) cons
// -----------------------------------------------------------------------
+basegfx::B2DPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolygon& rLogicPoly ) const
+{
+ basegfx::B2DPolygon aTransformedPoly = rLogicPoly;
+ const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation();
+ aTransformedPoly.transform( rTransformationMatrix );
+ return aTransformedPoly;
+}
+
+// -----------------------------------------------------------------------
+
+basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly ) const
+{
+ basegfx::B2DPolyPolygon aTransformedPoly = rLogicPolyPoly;
+ const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation();
+ aTransformedPoly.transform( rTransformationMatrix );
+ return aTransformedPoly;
+}
+
+// -----------------------------------------------------------------------
+
Region OutputDevice::LogicToPixel( const Region& rLogicRegion ) const
{
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
- DBG_CHKOBJ( &rLogicRegion, Region, ImplDbgTestRegion );
-
- RegionType eType = rLogicRegion.GetType();
- if ( !mbMap || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ if(!mbMap || rLogicRegion.IsNull() || rLogicRegion.IsEmpty())
+ {
return rLogicRegion;
+ }
- Region aRegion;
- const ImplRegion& rImplRegion = *rLogicRegion.ImplGetImplRegion();
- const PolyPolygon* pPolyPoly = rImplRegion.mpPolyPoly;
- const basegfx::B2DPolyPolygon* pB2DPolyPoly = rImplRegion.mpB2DPolyPoly;
+ Region aRegion;
- if ( pPolyPoly )
- aRegion = Region( LogicToPixel( *pPolyPoly ) );
- else if( pB2DPolyPoly )
+ if(rLogicRegion.getB2DPolyPolygon())
{
- basegfx::B2DPolyPolygon aTransformedPoly = *pB2DPolyPoly;
- const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation();
- aTransformedPoly.transform( rTransformationMatrix );
- aRegion = Region( aTransformedPoly );
+ aRegion = Region(LogicToPixel(*rLogicRegion.getB2DPolyPolygon()));
}
- else
+ else if(rLogicRegion.getPolyPolygon())
+ {
+ aRegion = Region(LogicToPixel(*rLogicRegion.getPolyPolygon()));
+ }
+ else if(rLogicRegion.getRegionBand())
{
- long nX;
- long nY;
- long nWidth;
- long nHeight;
- ImplRegionInfo aInfo;
- sal_Bool bRegionRect;
+ RectangleVector aRectangles;
+ rLogicRegion.GetRegionRectangles(aRectangles);
+ const RectangleVector& rRectangles(aRectangles); // needed to make the '!=' work
- aRegion.ImplBeginAddRect();
- bRegionRect = rLogicRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
- while ( bRegionRect )
+ // make reverse run to fill new region bottom-up, this will speed it up due to the used data structuring
+ for(RectangleVector::const_reverse_iterator aRectIter(rRectangles.rbegin()); aRectIter != rRectangles.rend(); aRectIter++)
{
- Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
- aRegion.ImplAddRect( LogicToPixel( aRect ) );
- bRegionRect = rLogicRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ aRegion.Union(LogicToPixel(*aRectIter));
}
- aRegion.ImplEndAddRect();
+
+ //long nX(0);
+ //long nY(0);
+ //long nWidth(0);
+ //long nHeight(0);
+ //ImplRegionInfo aInfo;
+ //aRegion.ImplBeginAddRect();
+ //bool bRegionRect(rLogicRegion.ImplGetFirstRect(aInfo, nX, nY, nWidth, nHeight));
+ //
+ //while(bRegionRect)
+ //{
+ // const Rectangle aRect(Point(nX, nY), Size(nWidth, nHeight));
+ // aRegion.ImplAddRect(LogicToPixel(aRect));
+ // bRegionRect = rLogicRegion.ImplGetNextRect(aInfo, nX, nY, nWidth, nHeight);
+ //}
+ //
+ //aRegion.ImplEndAddRect();
}
return aRegion;
@@ -1295,6 +1317,27 @@ Polygon OutputDevice::LogicToPixel( const Polygon& rLogicPoly,
// -----------------------------------------------------------------------
+PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPolyPoly, PolyPolygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicPolyPoly;
+
+ PolyPolygon aPolyPoly( rLogicPolyPoly );
+ sal_uInt16 nPoly = aPolyPoly.Count();
+ for( sal_uInt16 i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = LogicToPixel( rPoly, rMapMode );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly,
const MapMode& rMapMode ) const
{
@@ -1306,6 +1349,71 @@ basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygo
// -----------------------------------------------------------------------
+basegfx::B2DPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolygon& rLogicPoly,
+ const MapMode& rMapMode ) const
+{
+ basegfx::B2DPolygon aTransformedPoly = rLogicPoly;
+ const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation( rMapMode );
+ aTransformedPoly.transform( rTransformationMatrix );
+ return aTransformedPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::LogicToPixel( const Region& rLogicRegion, const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if(rMapMode.IsDefault() || rLogicRegion.IsNull() || rLogicRegion.IsEmpty())
+ {
+ return rLogicRegion;
+ }
+
+ Region aRegion;
+
+ if(rLogicRegion.getB2DPolyPolygon())
+ {
+ aRegion = Region(LogicToPixel(*rLogicRegion.getB2DPolyPolygon(), rMapMode));
+ }
+ else if(rLogicRegion.getPolyPolygon())
+ {
+ aRegion = Region(LogicToPixel(*rLogicRegion.getPolyPolygon(), rMapMode));
+ }
+ else if(rLogicRegion.getRegionBand())
+ {
+ RectangleVector aRectangles;
+ rLogicRegion.GetRegionRectangles(aRectangles);
+ const RectangleVector& rRectangles(aRectangles); // needed to make the '!=' work
+
+ // make reverse run to fill new region bottom-up, this will speed it up due to the used data structuring
+ for(RectangleVector::const_reverse_iterator aRectIter(rRectangles.rbegin()); aRectIter != rRectangles.rend(); aRectIter++)
+ {
+ aRegion.Union(LogicToPixel(*aRectIter, rMapMode));
+ }
+
+ //long nX(0);
+ //long nY(0);
+ //long nWidth(0);
+ //long nHeight(0);
+ //ImplRegionInfo aInfo;
+ //aRegion.ImplBeginAddRect();
+ //bool bRegionRect(rLogicRegion.ImplGetFirstRect(aInfo, nX, nY, nWidth, nHeight));
+ //
+ //while(bRegionRect)
+ //{
+ // const Rectangle aRect(Point(nX, nY), Size(nWidth, nHeight));
+ // aRegion.ImplAddRect(LogicToPixel(aRect, rMapMode));
+ // bRegionRect = rLogicRegion.ImplGetNextRect(aInfo, nX, nY, nWidth, nHeight);
+ //}
+ //
+ //aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
Point OutputDevice::PixelToLogic( const Point& rDevicePt ) const
{
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
@@ -1427,43 +1535,50 @@ basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygo
Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const
{
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
- DBG_CHKOBJ( &rDeviceRegion, Region, ImplDbgTestRegion );
-
- RegionType eType = rDeviceRegion.GetType();
- if ( !mbMap || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ if(!mbMap || rDeviceRegion.IsNull() || rDeviceRegion.IsEmpty())
+ {
return rDeviceRegion;
+ }
- Region aRegion;
- basegfx::B2DPolyPolygon* pB2DPolyPoly = rDeviceRegion.ImplGetImplRegion()->mpB2DPolyPoly;
- PolyPolygon* pPolyPoly = pB2DPolyPoly ? 0 : rDeviceRegion.ImplGetImplRegion()->mpPolyPoly;
+ Region aRegion;
- if ( pB2DPolyPoly ) // conversion with B2DPolyPolygon lost polygon-based ClipRegion
+ if(rDeviceRegion.getB2DPolyPolygon())
{
- aRegion = Region( PixelToLogic( *pB2DPolyPoly ) );
+ aRegion = Region(PixelToLogic(*rDeviceRegion.getB2DPolyPolygon()));
}
- else if ( pPolyPoly )
+ else if(rDeviceRegion.getPolyPolygon())
{
- aRegion = Region( PixelToLogic( *pPolyPoly ) );
+ aRegion = Region(PixelToLogic(*rDeviceRegion.getPolyPolygon()));
}
- else
+ else if(rDeviceRegion.getRegionBand())
{
- long nX;
- long nY;
- long nWidth;
- long nHeight;
- ImplRegionInfo aInfo;
- sal_Bool bRegionRect;
+ RectangleVector aRectangles;
+ rDeviceRegion.GetRegionRectangles(aRectangles);
+ const RectangleVector& rRectangles(aRectangles); // needed to make the '!=' work
- aRegion.ImplBeginAddRect();
- bRegionRect = rDeviceRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
- while ( bRegionRect )
+ // make reverse run to fill new region bottom-up, this will speed it up due to the used data structuring
+ for(RectangleVector::const_reverse_iterator aRectIter(rRectangles.rbegin()); aRectIter != rRectangles.rend(); aRectIter++)
{
- Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
- aRegion.ImplAddRect( PixelToLogic( aRect ) );
- bRegionRect = rDeviceRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ aRegion.Union(PixelToLogic(*aRectIter));
}
- aRegion.ImplEndAddRect();
+
+ //long nX(0);
+ //long nY(0);
+ //long nWidth(0);
+ //long nHeight(0);
+ //ImplRegionInfo aInfo;
+ //aRegion.ImplBeginAddRect();
+ //bool bRegionRect(rDeviceRegion.ImplGetFirstRect(aInfo, nX, nY, nWidth, nHeight));
+ //
+ //while(bRegionRect)
+ //{
+ // const Rectangle aRect(Point(nX, nY), Size(nWidth, nHeight));
+ // aRegion.ImplAddRect(PixelToLogic(aRect));
+ // bRegionRect = rDeviceRegion.ImplGetNextRect(aInfo, nX, nY, nWidth, nHeight);
+ //}
+ //
+ //aRegion.ImplEndAddRect();
}
return aRegion;
@@ -1589,6 +1704,27 @@ Polygon OutputDevice::PixelToLogic( const Polygon& rDevicePoly,
// -----------------------------------------------------------------------
+PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePolyPoly, PolyPolygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rDevicePolyPoly;
+
+ PolyPolygon aPolyPoly( rDevicePolyPoly );
+ sal_uInt16 nPoly = aPolyPoly.Count();
+ for( sal_uInt16 i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = PixelToLogic( rPoly, rMapMode );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
basegfx::B2DPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolygon& rPixelPoly,
const MapMode& rMapMode ) const
{
@@ -1611,6 +1747,60 @@ basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygo
// -----------------------------------------------------------------------
+Region OutputDevice::PixelToLogic( const Region& rDeviceRegion, const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if(rMapMode.IsDefault() || rDeviceRegion.IsNull() || rDeviceRegion.IsEmpty())
+ {
+ return rDeviceRegion;
+ }
+
+ Region aRegion;
+
+ if(rDeviceRegion.getB2DPolyPolygon())
+ {
+ aRegion = Region(PixelToLogic(*rDeviceRegion.getB2DPolyPolygon(), rMapMode));
+ }
+ else if(rDeviceRegion.getPolyPolygon())
+ {
+ aRegion = Region(PixelToLogic(*rDeviceRegion.getPolyPolygon(), rMapMode));
+ }
+ else if(rDeviceRegion.getRegionBand())
+ {
+ RectangleVector aRectangles;
+ rDeviceRegion.GetRegionRectangles(aRectangles);
+ const RectangleVector& rRectangles(aRectangles); // needed to make the '!=' work
+
+ // make reverse run to fill new region bottom-up, this will speed it up due to the used data structuring
+ for(RectangleVector::const_reverse_iterator aRectIter(rRectangles.rbegin()); aRectIter != rRectangles.rend(); aRectIter++)
+ {
+ aRegion.Union(PixelToLogic(*aRectIter, rMapMode));
+ }
+
+ //long nX(0);
+ //long nY(0);
+ //long nWidth(0);
+ //long nHeight(0);
+ //ImplRegionInfo aInfo;
+ //aRegion.ImplBeginAddRect();
+ //bool bRegionRect(rDeviceRegion.ImplGetFirstRect(aInfo, nX, nY, nWidth, nHeight));
+ //
+ //while(bRegionRect)
+ //{
+ // const Rectangle aRect(Point(nX, nY), Size(nWidth, nHeight));
+ // aRegion.ImplAddRect(PixelToLogic(aRect, rMapMode));
+ // bRegionRect = rDeviceRegion.ImplGetNextRect(aInfo, nX, nY, nWidth, nHeight);
+ //}
+ //
+ //aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
#define ENTER0( rSource, pMapModeSource, pMapModeDest ) \
if ( !pMapModeSource ) \
pMapModeSource = &maMapMode; \
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
index 4cae63095920..56765434b943 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -879,7 +879,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa
else
{
Region aReg( pA->GetRegion() );
- m_rOuterFace.SetClipRegion( aReg.ConvertToB2DPolyPolygon() );
+ m_rOuterFace.SetClipRegion( aReg.GetAsB2DPolyPolygon() );
}
}
else
@@ -898,7 +898,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa
{
const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*) pAction;
Region aReg( pA->GetRegion() );
- m_rOuterFace.IntersectClipRegion( aReg.ConvertToB2DPolyPolygon() );
+ m_rOuterFace.IntersectClipRegion( aReg.GetAsB2DPolyPolygon() );
}
break;
diff --git a/vcl/source/gdi/regband.cxx b/vcl/source/gdi/regband.cxx
index 5bd481b6f3de..a5a28fac6caa 100644
--- a/vcl/source/gdi/regband.cxx
+++ b/vcl/source/gdi/regband.cxx
@@ -54,7 +54,7 @@ ImplRegionBand::ImplRegionBand( long nTop, long nBottom )
mpPrevBand = NULL;
mpFirstSep = NULL;
mpFirstBandPoint = NULL;
- mbTouched = sal_False;
+ mbTouched = false;
}
// -----------------------------------------------------------------------
@@ -202,8 +202,8 @@ void ImplRegionBand::ProcessPoints()
// generate separations from lines and process union with existing
// separations
-sal_Bool ImplRegionBand::InsertPoint( long nX, long nLineId,
- sal_Bool bEndPoint, LineType eLineType )
+bool ImplRegionBand::InsertPoint( long nX, long nLineId,
+ bool bEndPoint, LineType eLineType )
{
if ( !mpFirstBandPoint )
{
@@ -213,7 +213,7 @@ sal_Bool ImplRegionBand::InsertPoint( long nX, long nLineId,
mpFirstBandPoint->mbEndPoint = bEndPoint;
mpFirstBandPoint->meLineType = eLineType;
mpFirstBandPoint->mpNextBandPoint = NULL;
- return sal_True;
+ return true;
}
// look if line already touched the band
@@ -232,8 +232,8 @@ sal_Bool ImplRegionBand::InsertPoint( long nX, long nLineId,
{
// if we've only got one point => replace first point
pRegionBandPoint->mnX = nX;
- pRegionBandPoint->mbEndPoint = sal_True;
- return sal_True;
+ pRegionBandPoint->mbEndPoint = true;
+ return true;
}
else
{
@@ -257,7 +257,7 @@ sal_Bool ImplRegionBand::InsertPoint( long nX, long nLineId,
}
}
else
- return sal_False;
+ return false;
}
// use next element
@@ -288,7 +288,7 @@ sal_Bool ImplRegionBand::InsertPoint( long nX, long nLineId,
else
pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
- return sal_True;
+ return true;
}
// use next element
@@ -307,7 +307,7 @@ sal_Bool ImplRegionBand::InsertPoint( long nX, long nLineId,
// connections to the new point
pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
- return sal_True;
+ return true;
}
// -----------------------------------------------------------------------
@@ -341,7 +341,7 @@ void ImplRegionBand::ScaleX( double fHorzScale )
//
// combine overlaping sparations
-sal_Bool ImplRegionBand::OptimizeBand()
+bool ImplRegionBand::OptimizeBand()
{
ImplRegionBandSep* pPrevSep = 0;
ImplRegionBandSep* pSep = mpFirstSep;
@@ -379,7 +379,7 @@ sal_Bool ImplRegionBand::OptimizeBand()
pSep = pSep->mpNextSep;
}
- return sal_True;
+ return true;
}
// -----------------------------------------------------------------------
@@ -394,7 +394,7 @@ void ImplRegionBand::Union( long nXLeft, long nXRight )
mpFirstSep = new ImplRegionBandSep;
mpFirstSep->mnXLeft = nXLeft;
mpFirstSep->mnXRight = nXRight;
- mpFirstSep->mbRemoved = sal_False;
+ mpFirstSep->mbRemoved = false;
mpFirstSep->mpNextSep = NULL;
return;
}
@@ -415,7 +415,7 @@ void ImplRegionBand::Union( long nXLeft, long nXRight )
pNewSep = new ImplRegionBandSep;
pNewSep->mnXLeft = nXLeft;
pNewSep->mnXRight = nXRight;
- pNewSep->mbRemoved = sal_False;
+ pNewSep->mbRemoved = false;
pNewSep->mpNextSep = pSep;
if ( pSep == mpFirstSep )
@@ -442,7 +442,7 @@ void ImplRegionBand::Union( long nXLeft, long nXRight )
pNewSep = new ImplRegionBandSep;
pNewSep->mnXLeft = nXLeft;
pNewSep->mnXRight = nXRight;
- pNewSep->mbRemoved = sal_False;
+ pNewSep->mbRemoved = false;
pSep->mpNextSep = pNewSep;
pNewSep->mpNextSep = NULL;
@@ -463,7 +463,7 @@ void ImplRegionBand::Intersect( long nXLeft, long nXRight )
DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Intersect(): nxLeft > nXRight" );
// band has been touched
- mbTouched = sal_True;
+ mbTouched = true;
// band empty? -> nothing to do
if ( !mpFirstSep )
@@ -476,7 +476,7 @@ void ImplRegionBand::Intersect( long nXLeft, long nXRight )
// new separation completely outside? -> remove separation
if ( (nXRight < pSep->mnXLeft) || (nXLeft > pSep->mnXRight) )
// will be removed from the optimizer
- pSep->mbRemoved = sal_True;
+ pSep->mbRemoved = true;
// new separation overlaping from left? -> reduce right boundary
if ( (nXLeft <= pSep->mnXLeft) &&
@@ -510,7 +510,7 @@ void ImplRegionBand::Exclude( long nXLeft, long nXRight )
DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Exclude(): nxLeft > nXRight" );
// band has been touched
- mbTouched = sal_True;
+ mbTouched = true;
// band empty? -> nothing to do
if ( !mpFirstSep )
@@ -522,14 +522,14 @@ void ImplRegionBand::Exclude( long nXLeft, long nXRight )
ImplRegionBandSep* pSep = mpFirstSep;
while ( pSep )
{
- sal_Bool bSepProcessed = sal_False;
+ bool bSepProcessed = false;
// new separation completely overlapping? -> remove separation
if ( (nXLeft <= pSep->mnXLeft) && (nXRight >= pSep->mnXRight) )
{
// will be removed from the optimizer
- pSep->mbRemoved = sal_True;
- bSepProcessed = sal_True;
+ pSep->mbRemoved = true;
+ bSepProcessed = true;
}
// new separation overlaping from left? -> reduce boundary
@@ -538,7 +538,7 @@ void ImplRegionBand::Exclude( long nXLeft, long nXRight )
if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
{
pSep->mnXLeft = nXRight+1;
- bSepProcessed = sal_True;
+ bSepProcessed = true;
}
}
@@ -548,7 +548,7 @@ void ImplRegionBand::Exclude( long nXLeft, long nXRight )
if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
{
pSep->mnXRight = nXLeft-1;
- bSepProcessed = sal_True;
+ bSepProcessed = true;
}
}
@@ -561,7 +561,7 @@ void ImplRegionBand::Exclude( long nXLeft, long nXRight )
pNewSep = new ImplRegionBandSep;
pNewSep->mnXLeft = pSep->mnXLeft;
pNewSep->mnXRight = nXLeft-1;
- pNewSep->mbRemoved = sal_False;
+ pNewSep->mbRemoved = false;
pSep->mnXLeft = nXRight+1;
@@ -641,7 +641,7 @@ void ImplRegionBand::XOr( long nXLeft, long nXRight )
mpFirstSep = new ImplRegionBandSep;
mpFirstSep->mnXLeft = nXLeft;
mpFirstSep->mnXRight = nXRight;
- mpFirstSep->mbRemoved = sal_False;
+ mpFirstSep->mbRemoved = false;
mpFirstSep->mpNextSep = NULL;
return;
}
@@ -670,7 +670,7 @@ void ImplRegionBand::XOr( long nXLeft, long nXRight )
pNewSep->mnXLeft = nXLeft;
pNewSep->mnXRight = nXRight;
pNewSep->mpNextSep = pSep;
- pNewSep->mbRemoved = sal_False;
+ pNewSep->mbRemoved = false;
// connections from the new separation
pNewSep->mpNextSep = pSep;
@@ -686,7 +686,7 @@ void ImplRegionBand::XOr( long nXLeft, long nXRight )
else if( nXLeft == nOldLeft && nXRight == nOldRight )
{
// #3
- pSep->mbRemoved = sal_True;
+ pSep->mbRemoved = true;
pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
break;
}
@@ -719,7 +719,7 @@ void ImplRegionBand::XOr( long nXLeft, long nXRight )
// cannot break here, simply mark segment as removed,
// and go on with adapted nXLeft/nXRight
- pSep->mbRemoved = sal_True;
+ pSep->mbRemoved = true;
}
else
{
@@ -799,7 +799,7 @@ void ImplRegionBand::XOr( long nXLeft, long nXRight )
pNewSep->mnXLeft = nXLeft;
pNewSep->mnXRight = nXRight;
pNewSep->mpNextSep = pSep->mpNextSep;
- pNewSep->mbRemoved = sal_False;
+ pNewSep->mbRemoved = false;
// connections from the new separation
pSep->mpNextSep = pNewSep;
@@ -821,7 +821,7 @@ void ImplRegionBand::XOr( long nXLeft, long nXRight )
pNewSep->mnXLeft = nXLeft;
pNewSep->mnXRight = nXRight;
pNewSep->mpNextSep = NULL;
- pNewSep->mbRemoved = sal_False;
+ pNewSep->mbRemoved = false;
// connections from the new separation
pPrevSep->mpNextSep = pNewSep;
@@ -832,18 +832,50 @@ void ImplRegionBand::XOr( long nXLeft, long nXRight )
// -----------------------------------------------------------------------
-sal_Bool ImplRegionBand::IsInside( long nX )
+bool ImplRegionBand::IsInside( long nX )
{
ImplRegionBandSep* pSep = mpFirstSep;
while ( pSep )
{
if ( (pSep->mnXLeft <= nX) && (pSep->mnXRight >= nX) )
- return sal_True;
+ return true;
pSep = pSep->mpNextSep;
}
- return sal_False;
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+bool ImplRegionBand::IsOver( long nLeft, long nRight )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft < nRight) && (pSep->mnXRight > nLeft) )
+ return true;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+bool ImplRegionBand::IsInside( long nLeft, long nRight )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft >= nLeft) && (nRight <= pSep->mnXRight) )
+ return true;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return false;
}
// -----------------------------------------------------------------------
@@ -870,7 +902,7 @@ long ImplRegionBand::GetXRightBoundary() const
// -----------------------------------------------------------------------
-sal_Bool ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
+bool ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
{
ImplRegionBandSep* pOwnRectBandSep = mpFirstSep;
ImplRegionBandSep* pSecondRectBandSep = rRegionBand.mpFirstSep;
@@ -880,12 +912,12 @@ sal_Bool ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
long nOwnXLeft = pOwnRectBandSep->mnXLeft;
long nSecondXLeft = pSecondRectBandSep->mnXLeft;
if ( nOwnXLeft != nSecondXLeft )
- return sal_False;
+ return false;
long nOwnXRight = pOwnRectBandSep->mnXRight;
long nSecondXRight = pSecondRectBandSep->mnXRight;
if ( nOwnXRight != nSecondXRight )
- return sal_False;
+ return false;
// get next separation from current band
pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
@@ -896,9 +928,9 @@ sal_Bool ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
// different number of separations?
if ( pOwnRectBandSep || pSecondRectBandSep )
- return sal_False;
+ return false;
- return sal_True;
+ return true;
}
// -----------------------------------------------------------------------
diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx
index ad33c97cb9a1..fd91eb69b615 100644
--- a/vcl/source/gdi/region.cxx
+++ b/vcl/source/gdi/region.cxx
@@ -18,15 +18,11 @@
*/
#include <limits.h>
-
#include <tools/vcompat.hxx>
#include <tools/stream.hxx>
-#include <tools/debug.hxx>
#include <tools/helpers.hxx>
#include <vcl/region.hxx>
-#include <vcl/regband.hxx>
-
-#include <region.h>
+#include <regionband.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
@@ -36,2033 +32,1238 @@
#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 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;
-
- aPoint = aNextPoint;
- }
- // Compare closing edge.
- if (aLastPoint.X() != aPoint.X() && aLastPoint.Y() != aPoint.Y())
- return false;
- }
- 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)
+ // Iterate over all polygons.
+ const sal_uInt16 nPolyCount = rPolyPoly.Count();
+ for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
{
- // Create new band above the current band.
- ImplRegionBand* pAboveBand = new ImplRegionBand(
- nCurrentTop,
- ::std::min(nBottom,pBand->mnYTop-1));
- pImplRegion->InsertBand(pPreviousBand, pAboveBand);
- }
+ const Polygon& aPoly = rPolyPoly.GetObject(nPoly);
- // Adapt the top of the interval to prevent overlapping bands.
- nCurrentTop = ::std::max(nTop, pBand->mnYBottom+1);
+ // Iterate over all edges of the current polygon.
+ const sal_uInt16 nSize = aPoly.GetSize();
- // 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)
- {
- 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.
+ if (nSize < 2)
continue;
- }
-
- // 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 separately. 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);
- }
-
- // 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)
+ Point aPoint (aPoly.GetPoint(0));
+ const Point aLastPoint (aPoint);
+ for (sal_uInt16 nPoint = 1; nPoint < nSize; ++nPoint)
{
- // Split the bottom band.
- pBand->SplitBand(nBottom+1);
+ 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;
}
-
- // 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++, sal_True, eLineType);
+ // Compare closing edge.
+ if (aLastPoint.X() != aPoint.X() && aLastPoint.Y() != aPoint.Y())
+ return false;
}
+ return true;
}
- return pImplRegion;
-}
-
-
-
-
-/** Convert a general polygon (one for which ImplIsPolygonRectilinear()
- returns <FALSE/>) to bands.
-*/
-ImplRegion* ImplGeneralPolygonToBands (
- const PolyPolygon& rPolyPoly,
- const Rectangle& rPolygonBoundingBox)
-{
- long nLineID = 0L;
-
- // 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();
-
- // not enough points ( <= 2 )? -> nothing to do!
- if ( nSize <= 2 )
- continue;
-
- // band the polygon
- for ( sal_uInt16 nPoint = 1; nPoint < nSize; nPoint++ )
- pImplRegion->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), 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 pImplRegion;
-}
-
-
-} // end of anonymous namespace
-
-
-// -----------------------------------------------------------------------
-
-#ifdef DBG_UTIL
-const char* ImplDbgTestRegion( const void* pObj )
-{
- Region* pRegion = (Region*)pObj;
- ImplRegion* pImplRegion = pRegion->ImplGetImplRegion();
-
- 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 ( (pImplRegion != &aImplEmptyRegion) && (pImplRegion != &aImplNullRegion) )
- {
- sal_uLong nCount = 0;
- const ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
- while ( pBand )
+ /** 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)
+ {
+ OSL_ASSERT(ImplIsPolygonRectilinear (rPolyPoly));
+
+ // 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)
{
- 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";
+ const Polygon& aPoly = rPolyPoly.GetObject(nPoly);
- ImplRegionBandSep* pSep = pBand->mpFirstSep;
- while ( pSep )
+ // 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)
{
- if ( pSep->mnXRight < pSep->mnXLeft )
- return "XLeft < XRight";
- if ( pSep->mpNextSep )
+ // We take the implicit closing edge into account by mapping
+ // index nSize to 0.
+ aEnd = aPoly.GetPoint(nPoint%nSize);
+ if (aStart.Y() == aEnd.Y())
{
- if ( pSep->mnXRight >= pSep->mpNextSep->mnXLeft )
- return "overlapping separations in region";
+ // Horizontal lines are ignored.
+ continue;
}
- if ( pSep->mbRemoved > 1 )
- return "Sep-mbRemoved overwrite";
- nCount++;
- pSep = pSep->mpNextSep;
- }
+ // At this point the line has to be vertical.
+ OSL_ASSERT(aStart.X() == aEnd.X());
- pBand = pBand->mpNextBand;
- }
+ // 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);
- if ( pImplRegion->mnRectCount != nCount )
- return "mnRetCount is not valid";
- }
+ // Make sure that the current line is covered by bands.
+ pRegionBand->ImplAddMissingBands(nTop,nBottom);
- return NULL;
-}
-
-#endif
-
-// =======================================================================
-
-inline void Region::ImplPolyPolyRegionToBandRegion()
-{
- if( mpImplRegion->mpPolyPoly || mpImplRegion->mpB2DPolyPoly )
- ImplPolyPolyRegionToBandRegionFunc();
-}
-
-// =======================================================================
-
-ImplRegionBase::ImplRegionBase( int nRefCount )
-: mnRefCount( nRefCount )
-, mnRectCount( 0 )
-, mpPolyPoly( NULL )
-, mpB2DPolyPoly( NULL )
-{}
-
-// ------------------------------------------------------------------------
-
-ImplRegion::ImplRegion()
-{
- mpFirstBand = NULL;
- mpLastCheckedBand = NULL;
-}
-
-// ------------------------------------------------------------------------
-
-ImplRegion::ImplRegion( const PolyPolygon& rPolyPoly )
-{
- mpFirstBand = NULL;
- mpLastCheckedBand = NULL;
- mpPolyPoly = new PolyPolygon( rPolyPoly );
-}
-
-// ------------------------------------------------------------------------
-
-ImplRegion::ImplRegion( const basegfx::B2DPolyPolygon& rPolyPoly )
-{
- mpFirstBand = NULL;
- mpLastCheckedBand = NULL;
- mpB2DPolyPoly = new basegfx::B2DPolyPolygon( rPolyPoly );
-}
-
-// -----------------------------------------------------------------------
-
-ImplRegion::ImplRegion( const ImplRegion& rImplRegion )
-: ImplRegionBase()
-{
- 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;
-
- pPrevBand = pNewBand;
- pBand = pBand->mpNextBand;
- }
-}
-
-// -----------------------------------------------------------------------
-
-ImplRegion::~ImplRegion()
-{
- DBG_ASSERT( (this != &aImplEmptyRegion) && (this != &aImplNullRegion),
- "ImplRegion::~ImplRegion() - Empty oder NULL-Region" );
-
- ImplRegionBand* pBand = mpFirstBand;
- while ( pBand )
- {
- ImplRegionBand* pTempBand = pBand->mpNextBand;
- delete pBand;
- pBand = pTempBand;
- }
-}
-
-// -----------------------------------------------------------------------
-
-ImplRegionBase::~ImplRegionBase()
-{
- delete mpPolyPoly;
- delete mpB2DPolyPoly;
-}
-
-// -----------------------------------------------------------------------
-//
-// create complete range of bands in single steps
-
-void ImplRegion::CreateBandRange( long nYTop, long nYBottom )
-{
- // 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 )
-{
- long nX, nY;
-
- // lines consisting of a single point do not interest here
- if ( rStartPt == rEndPt )
- return sal_True;
+ // 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);
+ }
- LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
- if ( rStartPt.X() == rEndPt.X() )
- {
- // vertical line
- const long nEndY = rEndPt.Y();
+ // 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);
+ }
- nX = rStartPt.X();
- nY = rStartPt.Y();
+ // Note that we remember the top band (in pTopBand) but not the
+ // bottom band. The later can be determined by comparing y
+ // coordinates.
- if( nEndY > nY )
- {
- for ( ; nY <= nEndY; nY++ )
- {
- Point aNewPoint( nX, nY );
- InsertPoint( aNewPoint, nLineId,
- (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
- eLineType );
- }
- }
- else
- {
- for ( ; nY >= nEndY; nY-- )
- {
- Point aNewPoint( nX, nY );
- InsertPoint( aNewPoint, nLineId,
- (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
- eLineType );
+ // 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 pRegionBand;
}
- else if ( rStartPt.Y() != rEndPt.Y() )
+
+ /** Convert a general polygon (one for which ImplIsPolygonRectilinear()
+ returns <FALSE/>) to bands.
+ */
+ RegionBand* ImplGeneralPolygonToBands(const PolyPolygon& rPolyPoly, const Rectangle& rPolygonBoundingBox)
{
- 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;
+ long nLineID = 0L;
- if ( nDX >= nDY )
- {
- const long nDYX = ( nDY - nDX ) << 1;
- const long nDY2 = nDY << 1;
- long nD = nDY2 - nDX;
+ // initialisation and creation of Bands
+ RegionBand* pRegionBand = new RegionBand();
+ pRegionBand->CreateBandRange(rPolygonBoundingBox.Top(), rPolygonBoundingBox.Bottom());
- for ( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
- {
- InsertPoint( Point( nX, nY ), nLineId, nStartX == nX, eLineType );
+ // insert polygons
+ const sal_uInt16 nPolyCount = rPolyPoly.Count();
- if ( nD < 0L )
- nD += nDY2;
- else
- nD += nDYX, nY += nYInc;
- }
- }
- else
+ for ( sal_uInt16 nPoly = 0; nPoly < nPolyCount; nPoly++ )
{
- const long nDYX = ( nDX - nDY ) << 1;
- const long nDY2 = nDX << 1;
- long nD = nDY2 - nDY;
+ // get reference to current polygon
+ const Polygon& aPoly = rPolyPoly.GetObject( nPoly );
+ const sal_uInt16 nSize = aPoly.GetSize();
- 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;
- }
- }
-
- // 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 )
-{
- DBG_ASSERT( mpFirstBand != NULL, "ImplRegion::InsertPoint - no bands available!" );
-
- if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
- {
- mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
- return sal_True;
- }
+ // not enough points ( <= 2 )? -> nothing to do!
+ if ( nSize <= 2 )
+ continue;
- if ( rPoint.Y() > mpLastCheckedBand->mnYTop )
- {
- // Search ascending
- while ( mpLastCheckedBand )
- {
- // Insert point if possible
- if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ // band the polygon
+ for ( sal_uInt16 nPoint = 1; nPoint < nSize; nPoint++ )
{
- mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
- return sal_True;
+ pRegionBand->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
}
- mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
- }
+ // 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);
- OSL_FAIL( "ImplRegion::InsertPoint reached the end of the list!" );
- }
- else
- {
- // Search descending
- while ( mpLastCheckedBand )
- {
- // Insert point if possible
- if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ if ( rLastPoint != rFirstPoint )
{
- mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
- return sal_True;
+ pRegionBand->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
}
-
- mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
}
- OSL_FAIL( "ImplRegion::InsertPoint reached the beginning of the list!" );
+ return pRegionBand;
}
+} // end of anonymous namespace
- OSL_FAIL( "ImplRegion::InsertPoint point not inserted!" );
-
- // reinitialize pointer (should never be reached!)
- mpLastCheckedBand = mpFirstBand;
-
- return sal_False;
-}
-
-// -----------------------------------------------------------------------
-//
-// search for appropriate places for the new bands
+//////////////////////////////////////////////////////////////////////////////
-void ImplRegion::InsertBands( long nTop, long nBottom )
+bool Region::IsEmpty() const
{
- // region empty? -> set rectagle as first entry!
- if ( !mpFirstBand )
- {
- // add band with boundaries of the rectangle
- mpFirstBand = new ImplRegionBand( nTop, nBottom );
- 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;
-
- bTopBoundaryInserted = sal_True;
- }
-
- // 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;
-
- // insert bands between two bands if necessary
- 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;
- }
- }
-
- pBand = pBand->mpNextBand;
- }
+ return !mbIsNull && !mpB2DPolyPolygon.get() && !mpPolyPolygon.get() && !mpRegionBand.get();
}
-// -----------------------------------------------------------------------
-//
-// create new band and insert it into the list
-
-sal_Bool ImplRegion::InsertSingleBand( ImplRegionBand* pBand,
- long nYBandPosition )
+bool Region::IsNull() const
{
- // 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;
-
- return sal_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;
-
- return sal_True;
- }
-
- // 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;
- }
-
- if ( nYBandPosition > pBand->mnYBottom )
- {
- // create new band
- pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
-
- // append band to the list
- pBand->mpNextBand = pNewBand;
- return sal_True;
- }
- }
-
- return sal_False;
+ return mbIsNull;
}
-// ------------------------------------------------------------------------
-
-void ImplRegion::InsertBand (ImplRegionBand* pPreviousBand, ImplRegionBand* pBandToInsert)
+RegionBand* ImplCreateRegionBandFromPolyPolygon(const PolyPolygon& rPolyPolygon)
{
- OSL_ASSERT(pBandToInsert!=NULL);
+ RegionBand* pRetval = 0;
- if (pPreviousBand == NULL)
+ if(rPolyPolygon.Count())
{
- // Insert band before all others.
- if (mpFirstBand != NULL)
- mpFirstBand->mpPrevBand = pBandToInsert;
- pBandToInsert->mpNextBand = mpFirstBand;
- mpFirstBand = pBandToInsert;
- }
- else
- {
- // Insert band directly after pPreviousBand.
- pBandToInsert->mpNextBand = pPreviousBand->mpNextBand;
- pPreviousBand->mpNextBand = pBandToInsert;
- pBandToInsert->mpPrevBand = pPreviousBand;
- }
-}
+ // ensure to subdivide when bezier segemnts are used, it's going to
+ // be expanded to rectangles
+ PolyPolygon aPolyPolygon;
-// ------------------------------------------------------------------------
+ rPolyPolygon.AdaptiveSubdivide(aPolyPolygon);
-void ImplRegion::Union( long nLeft, long nTop, long nRight, long nBottom )
-{
- DBG_ASSERT( nLeft <= nRight, "ImplRegion::Union() - nLeft > nRight" );
- DBG_ASSERT( nTop <= nBottom, "ImplRegion::Union() - nTop > nBottom" );
-
- // process union
- ImplRegionBand* pBand = mpFirstBand;
- while ( pBand )
- {
- if ( pBand->mnYTop >= nTop )
+ if(aPolyPolygon.Count())
{
- if ( pBand->mnYBottom <= nBottom )
- pBand->Union( nLeft, nRight );
- else
+ const Rectangle aRect(aPolyPolygon.GetBoundRect());
+
+ if(!aRect.IsEmpty())
{
-#ifdef DBG_UTIL
- long nCurY = pBand->mnYBottom;
- pBand = pBand->mpNextBand;
- while ( pBand )
+ if(ImplIsPolygonRectilinear(aPolyPolygon))
{
- if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
- {
- OSL_FAIL( "ImplRegion::Union() - Bands not sorted!" );
- }
- pBand = pBand->mpNextBand;
+ // For rectilinear polygons there is an optimized band conversion.
+ pRetval = ImplRectilinearPolygonToBands(aPolyPolygon);
}
-#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 )
+ else
{
- if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
- {
- OSL_FAIL( "ImplRegion::Exclude() - Bands not sorted!" );
- }
- pBand = pBand->mpNextBand;
+ pRetval = ImplGeneralPolygonToBands(aPolyPolygon, aRect);
}
-#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 )
+ // Convert points into seps.
+ if(pRetval)
{
- if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
+ pRetval->processPoints();
+
+ // Optimize list of bands. Adjacent bands with identical lists
+ // of seps are joined.
+ if(!pRetval->OptimizeBandList())
{
- OSL_FAIL( "ImplRegion::XOr() - Bands not sorted!" );
+ delete pRetval;
+ pRetval = 0;
}
- pBand = pBand->mpNextBand;
}
-#endif
- break;
}
}
-
- pBand = pBand->mpNextBand;
}
-}
-// -----------------------------------------------------------------------
-//
-// remove empty bands
+ return pRetval;
+}
-sal_Bool ImplRegion::OptimizeBandList()
+PolyPolygon Region::ImplCreatePolyPolygonFromRegionBand() const
{
- DBG_ASSERT( (this != &aImplNullRegion) && (this != &aImplEmptyRegion),
- "ImplRegion::OptimizeBandList() - Empty oder NULL-Region" );
-
- mnRectCount = 0;
+ PolyPolygon aRetval;
- ImplRegionBand* pPrevBand = 0;
- ImplRegionBand* pBand = mpFirstBand;
- while ( pBand )
+ if(getRegionBand())
{
- const sal_Bool bBTEqual = pBand->mpNextBand &&
- (pBand->mnYBottom == pBand->mpNextBand->mnYTop);
+ RectangleVector aRectangles;
+ GetRegionRectangles(aRectangles);
- // no separation? -> remove!
- if ( pBand->IsEmpty() || (bBTEqual && (pBand->mnYBottom == pBand->mnYTop)) )
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- // 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;
- }
+ aRetval.Insert(Polygon(*aRectIter));
}
}
-
-#ifdef DBG_UTIL
- pBand = mpFirstBand;
- while ( pBand )
+ else
{
- DBG_ASSERT( pBand->mpFirstSep != NULL,
- "Exiting ImplRegion::OptimizeBandList(): empty band in region!" );
-
- if ( pBand->mnYBottom < pBand->mnYTop )
- OSL_FAIL( "ImplRegion::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
-
- if ( pBand->mpNextBand )
- {
- if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
- OSL_FAIL( "ImplRegion::OptimizeBandList(): overlapping bands in region!" );
- }
-
- pBand = pBand->mpNextBand;
+ OSL_ENSURE(false, "Called with no local RegionBand (!)");
}
-#endif
-
- return (mnRectCount != 0);
-}
-
-// =======================================================================
-void Region::ImplCopyData()
-{
- mpImplRegion->mnRefCount--;
- mpImplRegion = new ImplRegion( *mpImplRegion );
+ return aRetval;
}
-// =======================================================================
-
-Region::Region()
+basegfx::B2DPolyPolygon Region::ImplCreateB2DPolyPolygonFromRegionBand() const
{
- DBG_CTOR( Region, ImplDbgTestRegion );
+ PolyPolygon aPoly(ImplCreatePolyPolygonFromRegionBand());
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ return aPoly.getB2DPolyPolygon();
}
-// -----------------------------------------------------------------------
-
-Region::Region( RegionType eType )
+Region::Region(bool bIsNull)
+: mpB2DPolyPolygon(),
+ mpPolyPolygon(),
+ mpRegionBand(),
+ mbIsNull(bIsNull)
{
- 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 )
+Region::Region(const Rectangle& rRect)
+: mpB2DPolyPolygon(),
+ mpPolyPolygon(),
+ mpRegionBand(),
+ mbIsNull(false)
{
- DBG_CTOR( Region, ImplDbgTestRegion );
-
- ImplCreateRectRegion( rRect );
+ mpRegionBand.reset(rRect.IsEmpty() ? 0 : new RegionBand(rRect));
}
-// -----------------------------------------------------------------------
-
-Region::Region( const Polygon& rPolygon )
+Region::Region(const Polygon& rPolygon)
+: mpB2DPolyPolygon(),
+ mpPolyPolygon(),
+ mpRegionBand(),
+ mbIsNull(false)
{
- DBG_CTOR( Region, ImplDbgTestRegion );
DBG_CHKOBJ( &rPolygon, Polygon, NULL );
- ImplCreatePolyPolyRegion( rPolygon );
+ if(rPolygon.GetSize())
+ {
+ ImplCreatePolyPolyRegion(rPolygon);
+ }
}
-// -----------------------------------------------------------------------
-
-Region::Region( const PolyPolygon& rPolyPoly )
+Region::Region(const PolyPolygon& rPolyPoly)
+: mpB2DPolyPolygon(),
+ mpPolyPolygon(),
+ mpRegionBand(),
+ mbIsNull(false)
{
- DBG_CTOR( Region, ImplDbgTestRegion );
DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
- ImplCreatePolyPolyRegion( rPolyPoly );
+ if(rPolyPoly.Count())
+ {
+ ImplCreatePolyPolyRegion(rPolyPoly);
+ }
}
-// -----------------------------------------------------------------------
-
-Region::Region( const basegfx::B2DPolyPolygon& rPolyPoly )
+Region::Region(const basegfx::B2DPolyPolygon& rPolyPoly)
+: mpB2DPolyPolygon(),
+ mpPolyPolygon(),
+ mpRegionBand(),
+ mbIsNull(false)
{
- DBG_CTOR( Region, ImplDbgTestRegion );
DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
- ImplCreatePolyPolyRegion( rPolyPoly );
+ if(rPolyPoly.count())
+ {
+ ImplCreatePolyPolyRegion(rPolyPoly);
+ }
}
-// -----------------------------------------------------------------------
-
-Region::Region( const Region& rRegion )
+Region::Region(const Region& rRegion)
+: mpB2DPolyPolygon(rRegion.mpB2DPolyPolygon),
+ mpPolyPolygon(rRegion.mpPolyPolygon),
+ mpRegionBand(rRegion.mpRegionBand),
+ mbIsNull(rRegion.mbIsNull)
{
- 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++;
}
-// -----------------------------------------------------------------------
-
Region::~Region()
{
- DBG_DTOR( Region, ImplDbgTestRegion );
-
- // statische Object haben RefCount von 0
- if ( mpImplRegion->mnRefCount )
- {
- if ( mpImplRegion->mnRefCount > 1 )
- mpImplRegion->mnRefCount--;
- else
- delete mpImplRegion;
- }
}
-// -----------------------------------------------------------------------
-
-void Region::ImplCreateRectRegion( const Rectangle& rRect )
-{
- if ( rRect.IsEmpty() )
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
- else
- {
- // get justified rectangle
- long nTop = std::min( rRect.Top(), rRect.Bottom() );
- long nBottom = std::max( rRect.Top(), rRect.Bottom() );
- long nLeft = std::min( rRect.Left(), rRect.Right() );
- long nRight = std::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 )
+
+ if(nPolyCount)
{
// polypolygon empty? -> empty region
- const Rectangle aRect( rPolyPoly.GetBoundRect() );
+ const Rectangle aRect(rPolyPoly.GetBoundRect());
- if ( !aRect.IsEmpty() )
+ if(!aRect.IsEmpty())
{
// width OR height == 1 ? => Rectangular region
- if ( (aRect.GetWidth() == 1)
- || (aRect.GetHeight() == 1)
- || rPolyPoly.IsRect() )
+ if((1 == aRect.GetWidth()) || (1 == aRect.GetHeight()) || rPolyPoly.IsRect())
{
- ImplCreateRectRegion( aRect );
+ mpRegionBand.reset(new RegionBand(aRect));
}
else
- mpImplRegion = new ImplRegion( rPolyPoly );
+ {
+ mpPolyPolygon.reset(new PolyPolygon(rPolyPoly));
+ }
+
+ mbIsNull = false;
}
- 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() )
+ if(rPolyPoly.count() && !rPolyPoly.getB2DRange().isEmpty())
{
- // 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);
+ mpB2DPolyPolygon.reset(new basegfx::B2DPolyPolygon(rPolyPoly));
+ mbIsNull = false;
}
- 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) )
+ if(IsNull() || IsEmpty())
+ {
+ // empty or null need no move
return;
+ }
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ if(!nHorzMove && !nVertMove)
+ {
+ // no move defined
+ return;
+ }
- if ( mpImplRegion->mpPolyPoly )
- mpImplRegion->mpPolyPoly->Move( nHorzMove, nVertMove );
- else if( mpImplRegion->mpB2DPolyPoly )
+ if(getB2DPolyPolygon())
{
- mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
+ basegfx::B2DPolyPolygon aPoly(*getB2DPolyPolygon());
+
+ aPoly.transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
+ mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
+ mpPolyPolygon.reset();
+ mpRegionBand.reset();
}
- else
+ else if(getPolyPolygon())
{
- ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
- while ( pBand )
- {
- // process the vertical move
- if ( nVertMove != 0)
- {
- pBand->mnYTop = pBand->mnYTop + nVertMove;
- pBand->mnYBottom = pBand->mnYBottom + nVertMove;
- }
+ PolyPolygon aPoly(*getPolyPolygon());
- // process the horizontal move
- if ( nHorzMove != 0)
- pBand->MoveX( nHorzMove );
+ aPoly.Move(nHorzMove, nVertMove);
+ mpB2DPolyPolygon.reset();
+ mpPolyPolygon.reset(aPoly.Count() ? new PolyPolygon(aPoly) : 0);
+ mpRegionBand.reset();
+ }
+ else if(getRegionBand())
+ {
+ RegionBand* pNew = new RegionBand(*getRegionBand());
- pBand = pBand->mpNextBand;
- }
+ pNew->Move(nHorzMove, nVertMove);
+ mpB2DPolyPolygon.reset();
+ mpPolyPolygon.reset();
+ mpRegionBand.reset(pNew);
+ }
+ else
+ {
+ OSL_ENSURE(false, "Region::Move error: impossible combination (!)");
}
}
-// -----------------------------------------------------------------------
-
void Region::Scale( double fScaleX, double fScaleY )
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // no region data? -> nothing to do
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ if(IsNull() || IsEmpty())
+ {
+ // empty or null need no scale
return;
+ }
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ if(basegfx::fTools::equalZero(fScaleX) && basegfx::fTools::equalZero(fScaleY))
+ {
+ // no scale defined
+ return;
+ }
- if ( mpImplRegion->mpPolyPoly )
- mpImplRegion->mpPolyPoly->Scale( fScaleX, fScaleY );
- else if( mpImplRegion->mpB2DPolyPoly )
+ if(getB2DPolyPolygon())
{
- mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
+ basegfx::B2DPolyPolygon aPoly(*getB2DPolyPolygon());
+
+ aPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
+ mpB2DPolyPolygon.reset(aPoly.count() ? new basegfx::B2DPolyPolygon(aPoly) : 0);
+ mpPolyPolygon.reset();
+ mpRegionBand.reset();
}
- else
+ else if(getPolyPolygon())
{
- 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 );
- }
+ PolyPolygon aPoly(*getPolyPolygon());
- // process the horizontal move
- if ( fScaleX != 0.0 )
- pBand->ScaleX( fScaleX );
+ 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 (!)");
}
}
-// -----------------------------------------------------------------------
-
-void Region::Union( const Rectangle& rRect )
+bool Region::Union( const Rectangle& rRect )
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if(rRect.IsEmpty())
+ {
+ // empty rectangle will not expand the existing union, nothing to do
+ return true;
+ }
- // is rectangle empty? -> nothing to do
- if ( rRect.IsEmpty() )
- return;
+ if(IsEmpty())
+ {
+ // no local data, the union will be equal to source. Create using rectangle
+ *this = rRect;
+ return true;
+ }
- if( HasPolyPolygon() )
+ if(HasPolyPolygonOrB2DPolyPolygon())
{
- // get this B2DPolyPolygon
- basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
- aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+ // get this B2DPolyPolygon, solve on polygon base
+ basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
- if( aThisPolyPoly.count() == 0 )
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
+
+ if(!aThisPolyPoly.count())
{
+ // no local polygon, use the rectangle as new region
*this = rRect;
- return;
+ }
+ 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);
}
- // 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;
+ 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();
+ if(!pCurrent)
+ {
+ // no region band, create using the rectangle
+ *this = rRect;
+ return true;
+ }
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ RegionBand* pNew = new RegionBand(*pCurrent);
// get justified rectangle
- long nLeft = std::min( rRect.Left(), rRect.Right() );
- long nTop = std::min( rRect.Top(), rRect.Bottom() );
- long nRight = std::max( rRect.Left(), rRect.Right() );
- long nBottom = std::max( rRect.Top(), rRect.Bottom() );
+ 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 already in the list
- mpImplRegion->InsertBands( nTop, nBottom );
+ pNew->InsertBands(nTop, nBottom);
// process union
- mpImplRegion->Union( nLeft, nTop, nRight, nBottom );
+ pNew->Union(nLeft, nTop, nRight, nBottom);
// cleanup
- if ( !mpImplRegion->OptimizeBandList() )
+ if(!pNew->OptimizeBandList())
{
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ delete pNew;
+ pNew = 0;
}
-}
-// -----------------------------------------------------------------------
+ mpRegionBand.reset(pNew);
+ return true;
+}
-void Region::Intersect( const Rectangle& rRect )
+bool Region::Intersect( const Rectangle& rRect )
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // 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;
+ // empty rectangle will create empty region
+ SetEmpty();
+ return true;
}
- // #103137# Avoid banding for special cases
- if ( mpImplRegion->mpPolyPoly )
+ if(IsNull())
{
- // #127431# make ImplRegion unique, if not already.
- if( mpImplRegion->mnRefCount > 1 )
- {
- mpImplRegion->mnRefCount--;
- mpImplRegion = new ImplRegion( *mpImplRegion->mpPolyPoly );
- }
-
- // 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 );
+ // null region (everything) intersect with rect will give rect
+ *this = rRect;
+ return true;
+ }
- // 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;
+ if(IsEmpty())
+ {
+ // no content, cannot get more empty
+ return true;
}
- else if( mpImplRegion->mpB2DPolyPoly )
+
+ if(HasPolyPolygonOrB2DPolyPolygon())
{
- // #127431# make ImplRegion unique, if not already.
- if( mpImplRegion->mnRefCount > 1 )
+ // if polygon data prefer double precision, the other will be lost (if buffered)
+ if(getB2DPolyPolygon())
{
- mpImplRegion->mnRefCount--;
- mpImplRegion = new ImplRegion( *mpImplRegion->mpB2DPolyPoly );
+ 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());
- *mpImplRegion->mpB2DPolyPoly =
- basegfx::tools::clipPolyPolygonOnRange(
- *mpImplRegion->mpB2DPolyPoly,
- basegfx::B2DRange(
- rRect.Left(),
- rRect.Top(),
- rRect.Right() + 1,
- rRect.Bottom() + 1),
- true,
- false);
+ // 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);
- // 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);
+ mpB2DPolyPolygon.reset();
+ mpPolyPolygon.reset(aPoly.Count() ? new PolyPolygon(aPoly) : 0);
+ mpRegionBand.reset();
}
- return;
+ return true;
}
- else
- ImplPolyPolyRegionToBandRegion();
- // is region empty? -> nothing to do!
- if ( mpImplRegion == &aImplEmptyRegion )
- return;
-
- // get justified rectangle
- long nLeft = std::min( rRect.Left(), rRect.Right() );
- long nTop = std::min( rRect.Top(), rRect.Bottom() );
- long nRight = std::max( rRect.Left(), rRect.Right() );
- long nBottom = std::max( rRect.Top(), rRect.Bottom() );
+ // only region band mode possibility left here or null/empty
+ const RegionBand* pCurrent = getRegionBand();
- // is own region NULL-region? -> copy data!
- if ( mpImplRegion == &aImplNullRegion )
+ if(!pCurrent)
{
- // 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;
-
- return;
+ // region is empty -> nothing to do!
+ return true;
}
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ RegionBand* pNew = new RegionBand(*pCurrent);
- // insert bands if the boundaries are not already in the list
- mpImplRegion->InsertBands( nTop, 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()));
- // 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 );
+ // insert bands if the boundaries are not allready in the list
+ pNew->InsertBands(nTop, nBottom);
- 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;
- }
- }
+ // process intersect
+ pNew->Intersect(nLeft, nTop, nRight, nBottom);
// cleanup
- if ( !mpImplRegion->OptimizeBandList() )
+ if(!pNew->OptimizeBandList())
{
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ delete pNew;
+ pNew = 0;
}
-}
-// -----------------------------------------------------------------------
+ mpRegionBand.reset(pNew);
+ return true;
+}
-void Region::Exclude( const Rectangle& rRect )
+bool Region::Exclude( const Rectangle& rRect )
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // is rectangle empty? -> nothing to do
if ( rRect.IsEmpty() )
- return;
+ {
+ // excluding nothing will do no change
+ return true;
+ }
+
+ 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;
+ }
- 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 )
- return;
+ 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 );
+ 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);
- basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
- *this = Region( aClip );
+ *this = Region(aClip);
- return;
+ 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) )
- return;
+ if(!pCurrent)
+ {
+ // empty? -> done!
+ return true;
+ }
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ RegionBand* pNew = new RegionBand(*pCurrent);
// get justified rectangle
- long nLeft = std::min( rRect.Left(), rRect.Right() );
- long nTop = std::min( rRect.Top(), rRect.Bottom() );
- long nRight = std::max( rRect.Left(), rRect.Right() );
- long nBottom = std::max( rRect.Top(), rRect.Bottom() );
+ 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 already in the list
- mpImplRegion->InsertBands( nTop, nBottom );
+ // insert bands if the boundaries are not allready in the list
+ pNew->InsertBands(nTop, nBottom);
// process exclude
- mpImplRegion->Exclude( nLeft, nTop, nRight, nBottom );
+ pNew->Exclude(nLeft, nTop, nRight, nBottom);
// cleanup
- if ( !mpImplRegion->OptimizeBandList() )
+ if(!pNew->OptimizeBandList())
{
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ delete pNew;
+ pNew = 0;
}
-}
-// -----------------------------------------------------------------------
+ mpRegionBand.reset(pNew);
+ return true;
+}
-void Region::XOr( const Rectangle& rRect )
+bool Region::XOr( const Rectangle& rRect )
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // is rectangle empty? -> nothing to do
if ( rRect.IsEmpty() )
- return;
+ {
+ // empty rectangle will not change local content
+ return true;
+ }
+
+ if(IsEmpty())
+ {
+ // rRect will be the xored-form (local off, rect on)
+ *this = rRect;
+ return 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() );
+ 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;
+ 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 );
+ 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);
- basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
- *this = Region( aClip );
+ *this = Region(aClip);
- return;
+ 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();
+ if(!pCurrent)
+ {
+ // rRect will be the xored-form (local off, rect on)
+ *this = rRect;
+ return true;
+ }
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ // only region band mode possibility left here or null/empty
+ RegionBand* pNew = new RegionBand(*getRegionBand());
// get justified rectangle
- long nLeft = std::min( rRect.Left(), rRect.Right() );
- long nTop = std::min( rRect.Top(), rRect.Bottom() );
- long nRight = std::max( rRect.Left(), rRect.Right() );
- long nBottom = std::max( rRect.Top(), rRect.Bottom() );
+ 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 already in the list
- mpImplRegion->InsertBands( nTop, nBottom );
+ // insert bands if the boundaries are not allready in the list
+ pNew->InsertBands(nTop, nBottom);
// process xor
- mpImplRegion->XOr( nLeft, nTop, nRight, nBottom );
+ pNew->XOr(nLeft, nTop, nRight, nBottom);
// cleanup
- if ( !mpImplRegion->OptimizeBandList() )
+ if(!pNew->OptimizeBandList())
{
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ delete pNew;
+ pNew = 0;
}
+
+ mpRegionBand.reset(pNew);
+ return true;
}
-// -----------------------------------------------------------------------
-void Region::ImplUnionPolyPolygon( const Region& i_rRegion )
+bool Region::Union( const Region& rRegion )
{
- // get this B2DPolyPolygon
- basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
- aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
-
- if( aThisPolyPoly.count() == 0 )
+ if(rRegion.IsEmpty())
{
- *this = i_rRegion;
- return;
+ // no extension at all
+ return true;
}
- // get the other B2DPolyPolygon
- basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
- aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
+ 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;
+ }
- basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
+ if(IsNull())
+ {
+ // already fully expanded (is null region), cannot be extended
+ return true;
+ }
- *this = Region( aClip );
-}
+ if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
+ {
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
-void Region::Union( const Region& rRegion )
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation(aThisPolyPoly);
- if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
- {
- ImplUnionPolyPolygon( rRegion );
- return;
- }
+ if(!aThisPolyPoly.count())
+ {
+ // when no local content, union will be equal to rRegion
+ *this = rRegion;
+ return true;
+ }
- ImplPolyPolyRegionToBandRegion();
- ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
+ aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation(aOtherPolyPoly);
- // is region empty or null? -> nothing to do
- if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
- return;
+ // use logical OR operation
+ basegfx::B2DPolyPolygon aClip(basegfx::tools::solvePolygonOperationOr(aThisPolyPoly, aOtherPolyPoly));
- // no instance data? -> create!
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- mpImplRegion = new ImplRegion();
+ *this = Region( aClip );
+ return true;
+ }
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ // only region band mode possibility left here or null/empty
+ const RegionBand* pCurrent = getRegionBand();
- // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
- ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
- while ( pBand )
+ if(!pCurrent)
{
- // insert bands if the boundaries are not already in the list
- mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+ // 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;
}
+ // prepare source and target
+ RegionBand* pNew = new RegionBand(*pCurrent);
+
+ // union with source
+ pNew->Union(*pSource);
+
// cleanup
- if ( !mpImplRegion->OptimizeBandList() )
+ if(!pNew->OptimizeBandList())
{
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ delete pNew;
+ pNew = 0;
}
+
+ mpRegionBand.reset(pNew);
+ return true;
}
-// -----------------------------------------------------------------------
-void Region::ImplIntersectWithPolyPolygon( const Region& i_rRegion )
+bool Region::Intersect( const Region& rRegion )
{
- // get this B2DPolyPolygon
- basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
- if( aThisPolyPoly.count() == 0 )
+ // same instance data? -> nothing to do!
+ if(getB2DPolyPolygon() && getB2DPolyPolygon() == rRegion.getB2DPolyPolygon())
{
- *this = i_rRegion;
- return;
+ return true;
}
- // get the other B2DPolyPolygon
- basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
+ if(getPolyPolygon() && getPolyPolygon() == rRegion.getPolyPolygon())
+ {
+ return true;
+ }
- basegfx::B2DPolyPolygon aClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aOtherPolyPoly, aThisPolyPoly, true, false );
- *this = Region( aClip );
-}
+ if(getRegionBand() && getRegionBand() == rRegion.getRegionBand())
+ {
+ return true;
+ }
-void Region::Intersect( const Region& rRegion )
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if(rRegion.IsNull())
+ {
+ // source region is null-region, intersect will not change local region
+ return true;
+ }
- // same instance data? -> nothing to do!
- if ( mpImplRegion == rRegion.mpImplRegion )
- return;
+ if(IsNull())
+ {
+ // when local region is null-region, intersect will be equal to source
+ *this = rRegion;
+ return true;
+ }
- if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+ if(rRegion.IsEmpty())
{
- ImplIntersectWithPolyPolygon( rRegion );
- return;
+ // source region is empty, intersection will always be empty
+ SetEmpty();
+ return true;
}
- ImplPolyPolyRegionToBandRegion();
- ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+ if(IsEmpty())
+ {
+ // local region is empty, cannot get more emty than that. Nothing to do
+ return true;
+ }
- if ( mpImplRegion == &aImplEmptyRegion )
- return;
+ if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
+ {
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
- // is region null? -> nothing to do
- if ( rRegion.mpImplRegion == &aImplNullRegion )
- return;
+ if(!aThisPolyPoly.count())
+ {
+ // local region is empty, cannot get more emty than that. Nothing to do
+ return true;
+ }
- // is rectangle empty? -> nothing to do
- if ( rRegion.mpImplRegion == &aImplEmptyRegion )
- {
- // statische Object haben RefCount von 0
- if ( mpImplRegion->mnRefCount )
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
+
+ if(!aOtherPolyPoly.count())
{
- if ( mpImplRegion->mnRefCount > 1 )
- mpImplRegion->mnRefCount--;
- else
- delete mpImplRegion;
+ // source region is empty, intersection will always be empty
+ SetEmpty();
+ return true;
}
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
- return;
+
+ const basegfx::B2DPolyPolygon aClip(
+ basegfx::tools::clipPolyPolygonOnPolyPolygon(
+ aOtherPolyPoly,
+ aThisPolyPoly,
+ true,
+ false));
+ *this = Region( aClip );
+ return true;
}
- // is own region NULL-region? -> copy data!
- if ( mpImplRegion == &aImplNullRegion)
+ // only region band mode possibility left here or null/empty
+ const RegionBand* pCurrent = getRegionBand();
+
+ if(!pCurrent)
{
- mpImplRegion = rRegion.mpImplRegion;
- rRegion.mpImplRegion->mnRefCount++;
- return;
+ // local region is empty, cannot get more emty than that. Nothing to do
+ return true;
}
- // Wenn wir weniger Rechtecke haben, drehen wir den Intersect-Aufruf um
- if ( mpImplRegion->mnRectCount+2 < rRegion.mpImplRegion->mnRectCount )
+ const RegionBand* pSource = rRegion.getRegionBand();
+
+ if(!pSource)
{
+ // source region is empty, intersection will always be empty
+ SetEmpty();
+ return true;
+ }
+
+ // 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
{
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ // prepare new regionBand
+ RegionBand* pNew = pCurrent ? new RegionBand(*pCurrent) : new RegionBand();
- // mark all bands as untouched
- ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
- while ( pBand )
- {
- pBand->mbTouched = sal_False;
- pBand = pBand->mpNextBand;
- }
+ // intersect with source
+ pNew->Intersect(*pSource);
- pBand = rRegion.mpImplRegion->mpFirstBand;
- while ( pBand )
+ // cleanup
+ if(!pNew->OptimizeBandList())
{
- // insert bands if the boundaries are not already in the list
- mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+ delete pNew;
+ pNew = 0;
+ }
- // 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 );
- }
+ mpRegionBand.reset(pNew);
+ }
- // 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 );
- }
+ return true;
+}
- pSep = pSep->mpNextSep;
- }
+bool Region::Exclude( const Region& rRegion )
+{
+ if ( rRegion.IsEmpty() )
+ {
+ // excluding nothing will do no change
+ return true;
+ }
- pBand = pBand->mpNextBand;
- }
+ if ( rRegion.IsNull() )
+ {
+ // excluding everything will create empty region
+ SetEmpty();
+ return true;
+ }
- // remove all untouched bands if bands already left
- ImplRegionBand* pPrevBand = 0;
- pBand = mpImplRegion->mpFirstBand;
- while ( pBand )
- {
- if ( !pBand->mbTouched )
- {
- // save pointer
- ImplRegionBand* pOldBand = pBand;
+ if(IsEmpty())
+ {
+ // cannot exclude from empty, done
+ return true;
+ }
- // previous element of the list
- if ( pBand == mpImplRegion->mpFirstBand )
- mpImplRegion->mpFirstBand = pBand->mpNextBand;
- else
- pPrevBand->mpNextBand = pBand->mpNextBand;
+ 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;
+ }
- pBand = pBand->mpNextBand;
- delete pOldBand;
- }
- else
- {
- pPrevBand = pBand;
- pBand = pBand->mpNextBand;
- }
- }
+ if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
+ {
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
- // cleanup
- if ( !mpImplRegion->OptimizeBandList() )
+ if(!aThisPolyPoly.count())
{
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ // cannot exclude from empty, done
+ return true;
}
- }
-}
-// -----------------------------------------------------------------------
-void Region::ImplExcludePolyPolygon( const Region& i_rRegion )
-{
- // get this B2DPolyPolygon
- basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
- if( aThisPolyPoly.count() == 0 )
- return;
- aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
- // get the other B2DPolyPolygon
- basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
- aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
+ aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
- basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
- *this = Region( aClip );
-}
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
+ *this = Region( aClip );
+ return true;
+ }
-void Region::Exclude( const Region& rRegion )
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ // only region band mode possibility left here or null/empty
+ const RegionBand* pCurrent = getRegionBand();
- if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+ if(!pCurrent)
{
- ImplExcludePolyPolygon( rRegion );
- return;
+ // cannot exclude from empty, done
+ return true;
}
- ImplPolyPolyRegionToBandRegion();
- ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
-
- // is region empty or null? -> nothing to do
- if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
- return;
-
- // no instance data? -> nothing to do
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return;
-
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ const RegionBand* pSource = rRegion.getRegionBand();
- // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
- ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
- while ( pBand )
+ if(!pSource)
{
- // insert bands if the boundaries are not already in the list
- mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+ // excluding nothing will do no change
+ return true;
+ }
- // 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;
- }
+ // prepare source and target
+ RegionBand* pNew = new RegionBand(*pCurrent);
- // 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;
- }
+ // union with source
+ const bool bSuccess(pNew->Exclude(*pSource));
- pBand = pBand->mpNextBand;
+ // cleanup
+ if(!bSuccess)
+ {
+ delete pNew;
+ pNew = 0;
}
+
+ mpRegionBand.reset(pNew);
+ return true;
}
-// -----------------------------------------------------------------------
-void Region::ImplXOrPolyPolygon( const Region& i_rRegion )
+bool Region::XOr( const Region& rRegion )
{
- // get this B2DPolyPolygon
- basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
- if( aThisPolyPoly.count() == 0 )
+ if ( rRegion.IsEmpty() )
{
- *this = i_rRegion;
- return;
+ // empty region will not change local content
+ return true;
}
- aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
- // get the other B2DPolyPolygon
- basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
- aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
-
- basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
- *this = Region( aClip );
-}
+ if ( rRegion.IsNull() )
+ {
+ // error; cannnot exclude null region from local since this is not representable
+ // in the data
+ OSL_ENSURE(false, "Region::XOr error: Cannot XOr with null region (!)");
+ return true;
+ }
-void Region::XOr( const Region& rRegion )
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if(IsEmpty())
+ {
+ // rRect will be the xored-form (local off, rect on)
+ *this = rRegion;
+ return true;
+ }
- if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+ if(IsNull())
{
- ImplXOrPolyPolygon( rRegion );
- return;
+ // 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 false;
}
- ImplPolyPolyRegionToBandRegion();
- ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+ if( rRegion.HasPolyPolygonOrB2DPolyPolygon() || HasPolyPolygonOrB2DPolyPolygon() )
+ {
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly(GetAsB2DPolyPolygon());
- // is region empty or null? -> nothing to do
- if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
- return;
+ if(!aThisPolyPoly.count())
+ {
+ // rRect will be the xored-form (local off, rect on)
+ *this = rRegion;
+ return true;
+ }
+
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly(rRegion.GetAsB2DPolyPolygon());
+ aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
- // no own instance data? -> XOr = copy
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
+ *this = Region( aClip );
+ return true;
+ }
+
+ // only region band mode possibility left here or null/empty
+ const RegionBand* pCurrent = getRegionBand();
+
+ if(!pCurrent)
{
+ // rRect will be the xored-form (local off, rect on)
*this = rRegion;
- return;
+ return true;
}
- // no own instance data? -> make own copy!
- if ( mpImplRegion->mnRefCount > 1 )
- ImplCopyData();
+ const RegionBand* pSource = rRegion.getRegionBand();
- // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
- ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
- while ( pBand )
+ if(!pSource)
{
- // insert bands if the boundaries are not already in the list
- mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+ // empty region will not change local content
+ return true;
+ }
- // process all elements of the list
- ImplRegionBandSep* pSep = pBand->mpFirstSep;
- while ( pSep )
- {
- mpImplRegion->XOr( pSep->mnXLeft, pBand->mnYTop,
- pSep->mnXRight, pBand->mnYBottom );
- pSep = pSep->mpNextSep;
- }
+ // prepare source and target
+ RegionBand* pNew = new RegionBand(*pCurrent);
- pBand = pBand->mpNextBand;
- }
+ // union with source
+ pNew->XOr(*pSource);
// cleanup
- if ( !mpImplRegion->OptimizeBandList() )
+ if(!pNew->OptimizeBandList())
{
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ delete pNew;
+ pNew = 0;
}
-}
-// -----------------------------------------------------------------------
+ mpRegionBand.reset(pNew);
+
+ return true;
+}
Rectangle Region::GetBoundRect() const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- Rectangle aRect;
+ if(IsEmpty())
+ {
+ // no internal data? -> region is empty!
+ return Rectangle();
+ }
- // no internal data? -> region is empty!
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return aRect;
+ if(IsNull())
+ {
+ // error; null region has no BoundRect
+ // OSL_ENSURE(false, "Region::GetBoundRect error: null region has unlimitied bound rect, not representable (!)");
+ return Rectangle();
+ }
- // PolyPolygon data im Imp structure?
- if ( mpImplRegion->mpPolyPoly )
- return mpImplRegion->mpPolyPoly->GetBoundRect();
- if( mpImplRegion->mpB2DPolyPoly )
+ // prefer double precision source
+ if(getB2DPolyPolygon())
{
- const basegfx::B2DRange aRange(basegfx::tools::getRange(*mpImplRegion->mpB2DPolyPoly));
+ const basegfx::B2DRange aRange(basegfx::tools::getRange(*getB2DPolyPolygon()));
+
if(aRange.isEmpty())
{
// emulate PolyPolygon::GetBoundRect() when empty polygon
@@ -2076,264 +1277,149 @@ Rectangle Region::GetBoundRect() const
}
}
- // no band in the list? -> region is empty!
- if ( !mpImplRegion->mpFirstBand )
- return aRect;
-
- // get the boundaries of the first band
- long nYTop = mpImplRegion->mpFirstBand->mnYTop;
- long nYBottom = mpImplRegion->mpFirstBand->mnYBottom;
- long nXLeft = mpImplRegion->mpFirstBand->GetXLeftBoundary();
- long nXRight = mpImplRegion->mpFirstBand->GetXRightBoundary();
-
- // look in the band list (don't test first band again!)
- ImplRegionBand* pBand = mpImplRegion->mpFirstBand->mpNextBand;
- while ( pBand )
+ if(getPolyPolygon())
{
- nYBottom = pBand->mnYBottom;
- nXLeft = std::min( nXLeft, pBand->GetXLeftBoundary() );
- nXRight = std::max( nXRight, pBand->GetXRightBoundary() );
+ return getPolyPolygon()->GetBoundRect();
+ }
- pBand = pBand->mpNextBand;
+ if(getRegionBand())
+ {
+ return getRegionBand()->GetBoundRect();
}
- // set rectangle
- aRect = Rectangle( nXLeft, nYTop, nXRight, nYBottom );
- return aRect;
+ return Rectangle();
}
-// -----------------------------------------------------------------------
-
-sal_Bool Region::HasPolyPolygon() const
+const PolyPolygon Region::GetAsPolyPolygon() const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
- if( !mpImplRegion )
- return false;
- if( mpImplRegion->mpPolyPoly )
- return true;
- if( mpImplRegion->mpB2DPolyPoly )
- return true;
- return false;
-}
-
-// -----------------------------------------------------------------------
+ if(getPolyPolygon())
+ {
+ return *getPolyPolygon();
+ }
-PolyPolygon Region::GetPolyPolygon() const
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if(getB2DPolyPolygon())
+ {
+ // the polygon needs to be converted, buffer the down converion
+ const PolyPolygon aPolyPolgon(*getB2DPolyPolygon());
+ const_cast< Region* >(this)->mpPolyPolygon.reset(new PolyPolygon(aPolyPolgon));
- PolyPolygon aRet;
+ return *getPolyPolygon();
+ }
- if( mpImplRegion->mpPolyPoly )
- aRet = *mpImplRegion->mpPolyPoly;
- else if( mpImplRegion->mpB2DPolyPoly )
+ if(getRegionBand())
{
- // the polygon needs to be converted
- aRet = PolyPolygon( *mpImplRegion->mpB2DPolyPoly );
- // TODO: cache the converted polygon?
- // mpImplRegion->mpB2DPolyPoly = aRet;
+ // the BandRegion needs to be converted, buffer the converion
+ const PolyPolygon aPolyPolgon(ImplCreatePolyPolygonFromRegionBand());
+ const_cast< Region* >(this)->mpPolyPolygon.reset(new PolyPolygon(aPolyPolgon));
+
+ return *getPolyPolygon();
}
- return aRet;
+ return PolyPolygon();
}
-// -----------------------------------------------------------------------
-
-const basegfx::B2DPolyPolygon Region::GetB2DPolyPolygon() const
+const basegfx::B2DPolyPolygon Region::GetAsB2DPolyPolygon() const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if(getB2DPolyPolygon())
+ {
+ return *getB2DPolyPolygon();
+ }
- basegfx::B2DPolyPolygon aRet;
+ if(getPolyPolygon())
+ {
+ // the polygon needs to be converted, buffer the up conversion. This will be preferred from now.
+ const basegfx::B2DPolyPolygon aB2DPolyPolygon(getPolyPolygon()->getB2DPolyPolygon());
+ const_cast< Region* >(this)->mpB2DPolyPolygon.reset(new basegfx::B2DPolyPolygon(aB2DPolyPolygon));
+
+ return *getB2DPolyPolygon();
+ }
- if( mpImplRegion->mpB2DPolyPoly )
- aRet = *mpImplRegion->mpB2DPolyPoly;
- else if( mpImplRegion->mpPolyPoly )
+ if(getRegionBand())
{
- // the polygon needs to be converted
- aRet = mpImplRegion->mpPolyPoly->getB2DPolyPolygon();
- // TODO: cache the converted polygon?
- // mpImplRegion->mpB2DPolyPoly = aRet;
+ // the BandRegion needs to be converted, buffer the converion
+ const basegfx::B2DPolyPolygon aB2DPolyPolygon(ImplCreateB2DPolyPolygonFromRegionBand());
+ const_cast< Region* >(this)->mpB2DPolyPolygon.reset(new basegfx::B2DPolyPolygon(aB2DPolyPolygon));
+
+ return *getB2DPolyPolygon();
}
- return aRet;
+ return basegfx::B2DPolyPolygon();
}
-// -----------------------------------------------------------------------
-
-basegfx::B2DPolyPolygon Region::ConvertToB2DPolyPolygon()
+const RegionBand* Region::GetAsRegionBand() const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- basegfx::B2DPolyPolygon aRet;
-
- if( HasPolyPolygon() )
- aRet = GetB2DPolyPolygon();
- else
+ if(!getRegionBand())
{
- RegionHandle aHdl = BeginEnumRects();
- Rectangle aSubRect;
- while( GetNextEnumRect( aHdl, aSubRect ) )
+ if(getB2DPolyPolygon())
+ {
+ // convert B2DPolyPolygon to RegionBand, buffer it and return it
+ const_cast< Region* >(this)->mpRegionBand.reset(ImplCreateRegionBandFromPolyPolygon(PolyPolygon(*getB2DPolyPolygon())));
+ }
+ else if(getPolyPolygon())
{
- basegfx::B2DPolygon aPoly( basegfx::tools::createPolygonFromRect(
- basegfx::B2DRectangle( aSubRect.Left(), aSubRect.Top(), aSubRect.Right(), aSubRect.Bottom() ) ) );
- aRet.append( aPoly );
+ // convert B2DPolyPolygon to RegionBand, buffer it and return it
+ const_cast< Region* >(this)->mpRegionBand.reset(ImplCreateRegionBandFromPolyPolygon(*getPolyPolygon()));
}
- EndEnumRects( aHdl );
}
- return aRet;
+ return getRegionBand();
}
-// -----------------------------------------------------------------------
-
-bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
- long& rX, long& rY,
- long& rWidth, long& rHeight ) const
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- ((Region*)this)->ImplPolyPolyRegionToBandRegion();
-
- // no internal data? -> region is empty!
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return false;
-
- // no band in the list? -> region is empty!
- if ( mpImplRegion->mpFirstBand == NULL )
- return false;
-
- // initialise pointer for first access
- ImplRegionBand* pCurrRectBand = mpImplRegion->mpFirstBand;
- ImplRegionBandSep* pCurrRectBandSep = pCurrRectBand->mpFirstSep;
-
- DBG_ASSERT( pCurrRectBandSep != NULL, "Erstes Band wurde nicht optimiert." );
- if ( !pCurrRectBandSep )
- return false;
-
- // get boundaries of current rectangle
- rX = pCurrRectBandSep->mnXLeft;
- rY = pCurrRectBand->mnYTop;
- rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
- rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
-
- // save pointers
- rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
- rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
-
- return true;
-}
-
-// -----------------------------------------------------------------------
-
-bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
- long& rX, long& rY,
- long& rWidth, long& rHeight ) const
+bool Region::IsInside( const Point& rPoint ) const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // no internal data? -> region is empty!
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ if(IsEmpty())
+ {
+ // no point can be in empty region
return false;
+ }
- // get last pointers
- ImplRegionBand* pCurrRectBand = (ImplRegionBand*)rImplRegionInfo.mpVoidCurrRectBand;
- ImplRegionBandSep* pCurrRectBandSep = (ImplRegionBandSep*)rImplRegionInfo.mpVoidCurrRectBandSep;
-
- // get next separation from current band
- pCurrRectBandSep = pCurrRectBandSep->mpNextSep;
-
- // no separation found? -> go to next band!
- if ( !pCurrRectBandSep )
+ if(IsNull())
{
- // get next band
- pCurrRectBand = pCurrRectBand->mpNextBand;
-
- // no band found? -> not further rectangles!
- if( !pCurrRectBand )
- return false;
-
- // get first separation in current band
- pCurrRectBandSep = pCurrRectBand->mpFirstSep;
+ // all points are inside null-region
+ return true;
}
- // get boundaries of current rectangle
- rX = pCurrRectBandSep->mnXLeft;
- rY = pCurrRectBand->mnYTop;
- rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
- rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
+ // Too expensive (?)
+ //if(mpImplRegion->getRegionPolyPoly())
+ //{
+ // return mpImplRegion->getRegionPolyPoly()->IsInside( rPoint );
+ //}
- // save new pointers
- rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
- rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
+ // ensure RegionBand existance
+ const_cast< Region* >(this)->GetAsRegionBand();
+ const RegionBand* pRegionBand = getRegionBand();
- return true;
-}
-
-// -----------------------------------------------------------------------
+ if(pRegionBand)
+ {
+ return pRegionBand->IsInside(rPoint);
+ }
-RegionType Region::GetType() const
-{
- if ( mpImplRegion == &aImplEmptyRegion )
- return REGION_EMPTY;
- else if ( mpImplRegion == &aImplNullRegion )
- return REGION_NULL;
- else if ( mpImplRegion->mnRectCount == 1 )
- return REGION_RECTANGLE;
- else
- return REGION_COMPLEX;
+ return false;
}
-// -----------------------------------------------------------------------
-
-sal_Bool Region::IsInside( const Point& rPoint ) const
+bool Region::IsInside( const Rectangle& rRect ) const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // PolyPolygon data im Imp structure?
- ((Region*)this)->ImplPolyPolyRegionToBandRegion();
-
- // no instance data? -> not inside
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return sal_False;
-
- // search band list
- ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
- while ( pBand )
+ if(IsEmpty())
{
- // is point within band?
- if ( (pBand->mnYTop <= rPoint.Y()) &&
- (pBand->mnYBottom >= rPoint.Y()) )
- {
- // is point within separation of the band?
- if ( pBand->IsInside( rPoint.X() ) )
- return sal_True;
- else
- return sal_False;
- }
-
- pBand = pBand->mpNextBand;
+ // no rectangle can be in empty region
+ return false;
}
- return sal_False;
-}
-
-// -----------------------------------------------------------------------
-
-sal_Bool Region::IsInside( const Rectangle& rRect ) const
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if(IsNull())
+ {
+ // rectangle always inside null-region
+ return true;
+ }
- // is rectangle empty? -> not inside
if ( rRect.IsEmpty() )
- return sal_False;
-
- // no instance data? -> not inside
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return sal_False;
+ {
+ // is rectangle empty? -> not inside
+ return false;
+ }
// create region from rectangle and intersect own region
Region aRegion(rRect);
- aRegion.Exclude( *this );
+ aRegion.Exclude(*this);
// rectangle is inside if exclusion is empty
return aRegion.IsEmpty();
@@ -2341,12 +1427,19 @@ sal_Bool Region::IsInside( const Rectangle& rRect ) const
// -----------------------------------------------------------------------
-sal_Bool Region::IsOver( const Rectangle& rRect ) const
+bool Region::IsOver( const Rectangle& rRect ) const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if(IsEmpty())
+ {
+ // nothing can be over something empty
+ return false;
+ }
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return sal_False;
+ if(IsNull())
+ {
+ // everything is over null region
+ return true;
+ }
// Can we optimize this ??? - is used in StarDraw for brushes pointers
// Why we have no IsOver for Regions ???
@@ -2358,210 +1451,127 @@ sal_Bool Region::IsOver( const Rectangle& rRect ) const
return !aRegion.IsEmpty();
}
-// -----------------------------------------------------------------------
-
void Region::SetNull()
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // statische Object haben RefCount von 0
- if ( mpImplRegion->mnRefCount )
- {
- if ( mpImplRegion->mnRefCount > 1 )
- mpImplRegion->mnRefCount--;
- else
- delete mpImplRegion;
- }
-
- // set new type
- mpImplRegion = (ImplRegion*)(&aImplNullRegion);
+ // reset all content
+ mpB2DPolyPolygon.reset();
+ mpPolyPolygon.reset();
+ mpRegionBand.reset();
+ mbIsNull = true;
}
-// -----------------------------------------------------------------------
-
void Region::SetEmpty()
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // statische Object haben RefCount von 0
- if ( mpImplRegion->mnRefCount )
- {
- if ( mpImplRegion->mnRefCount > 1 )
- mpImplRegion->mnRefCount--;
- else
- delete mpImplRegion;
- }
-
- // set new type
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ // reset all content
+ mpB2DPolyPolygon.reset();
+ mpPolyPolygon.reset();
+ mpRegionBand.reset();
+ mbIsNull = false;
}
-// -----------------------------------------------------------------------
-
Region& Region::operator=( const Region& rRegion )
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
- DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
- DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
-
- // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
- // RefCount == 0 fuer statische Objekte
- if ( rRegion.mpImplRegion->mnRefCount )
- rRegion.mpImplRegion->mnRefCount++;
+ // reset all content
+ mpB2DPolyPolygon = rRegion.mpB2DPolyPolygon;
+ mpPolyPolygon = rRegion.mpPolyPolygon;
+ mpRegionBand = rRegion.mpRegionBand;
+ mbIsNull = rRegion.mbIsNull;
- // statische Object haben RefCount von 0
- if ( mpImplRegion->mnRefCount )
- {
- if ( mpImplRegion->mnRefCount > 1 )
- mpImplRegion->mnRefCount--;
- else
- delete mpImplRegion;
- }
-
- mpImplRegion = rRegion.mpImplRegion;
return *this;
}
-// -----------------------------------------------------------------------
-
Region& Region::operator=( const Rectangle& rRect )
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ mpB2DPolyPolygon.reset();
+ mpPolyPolygon.reset();
+ mpRegionBand.reset(rRect.IsEmpty() ? 0 : new RegionBand(rRect));
+ mbIsNull = false;
- // statische Object haben RefCount von 0
- if ( mpImplRegion->mnRefCount )
- {
- if ( mpImplRegion->mnRefCount > 1 )
- mpImplRegion->mnRefCount--;
- else
- delete mpImplRegion;
- }
-
- ImplCreateRectRegion( rRect );
return *this;
}
-// -----------------------------------------------------------------------
-
-sal_Bool Region::operator==( const Region& rRegion ) const
+bool Region::operator==( const Region& rRegion ) const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
- DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
-
- // reference to same object? -> equal!
- if ( mpImplRegion == rRegion.mpImplRegion )
- return sal_True;
-
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return sal_False;
-
- if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
- return sal_False;
-
- if ( rRegion.mpImplRegion->mpPolyPoly && mpImplRegion->mpPolyPoly )
- return *rRegion.mpImplRegion->mpPolyPoly == *mpImplRegion->mpPolyPoly;
- else
+ if(IsNull() && rRegion.IsNull())
{
- ((Region*)this)->ImplPolyPolyRegionToBandRegion();
- ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
-
- // Eine der beiden Regions kann jetzt Empty sein
- if ( mpImplRegion == rRegion.mpImplRegion )
- return sal_True;
-
- if ( mpImplRegion == &aImplEmptyRegion )
- return sal_False;
-
- if ( rRegion.mpImplRegion == &aImplEmptyRegion )
- return sal_False;
+ // both are null region
+ return true;
}
- // initialise pointers
- ImplRegionBand* pOwnRectBand = mpImplRegion->mpFirstBand;
- ImplRegionBandSep* pOwnRectBandSep = pOwnRectBand->mpFirstSep;
- ImplRegionBand* pSecondRectBand = rRegion.mpImplRegion->mpFirstBand;
- ImplRegionBandSep* pSecondRectBandSep = pSecondRectBand->mpFirstSep;
- while ( pOwnRectBandSep && pSecondRectBandSep )
+ if(IsEmpty() && rRegion.IsEmpty())
{
- // get boundaries of current rectangle
- long nOwnXLeft = pOwnRectBandSep->mnXLeft;
- long nSecondXLeft = pSecondRectBandSep->mnXLeft;
- if ( nOwnXLeft != nSecondXLeft )
- return sal_False;
-
- long nOwnYTop = pOwnRectBand->mnYTop;
- long nSecondYTop = pSecondRectBand->mnYTop;
- if ( nOwnYTop != nSecondYTop )
- return sal_False;
+ // both are empty
+ return true;
+ }
- long nOwnXRight = pOwnRectBandSep->mnXRight;
- long nSecondXRight = pSecondRectBandSep->mnXRight;
- if ( nOwnXRight != nSecondXRight )
- return sal_False;
+ if(getB2DPolyPolygon() && getB2DPolyPolygon() == rRegion.getB2DPolyPolygon())
+ {
+ // same instance data? -> equal
+ return true;
+ }
- long nOwnYBottom = pOwnRectBand->mnYBottom;
- long nSecondYBottom = pSecondRectBand->mnYBottom;
- if ( nOwnYBottom != nSecondYBottom )
- return sal_False;
+ if(getPolyPolygon() && getPolyPolygon() == rRegion.getPolyPolygon())
+ {
+ // same instance data? -> equal
+ return true;
+ }
- // get next separation from current band
- pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
+ if(getRegionBand() && getRegionBand() == rRegion.getRegionBand())
+ {
+ // same instance data? -> equal
+ return true;
+ }
- // no separation found? -> go to next band!
- if ( !pOwnRectBandSep )
- {
- // get next band
- pOwnRectBand = pOwnRectBand->mpNextBand;
+ if(IsNull() || IsEmpty())
+ {
+ return false;
+ }
- // get first separation in current band
- if( pOwnRectBand )
- pOwnRectBandSep = pOwnRectBand->mpFirstSep;
- }
+ if(rRegion.IsNull() || rRegion.IsEmpty())
+ {
+ return false;
+ }
- // get next separation from current band
- pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
+ if(rRegion.getB2DPolyPolygon() || getB2DPolyPolygon())
+ {
+ // one of both has a B2DPolyPolygon based region, ensure both have it
+ // by evtl. conversion
+ const_cast< Region* >(this)->GetAsB2DPolyPolygon();
+ const_cast< Region& >(rRegion).GetAsB2DPolyPolygon();
- // no separation found? -> go to next band!
- if ( !pSecondRectBandSep )
- {
- // get next band
- pSecondRectBand = pSecondRectBand->mpNextBand;
+ return *rRegion.getB2DPolyPolygon() == *getB2DPolyPolygon();
+ }
- // get first separation in current band
- if( pSecondRectBand )
- pSecondRectBandSep = pSecondRectBand->mpFirstSep;
- }
+ if(rRegion.getPolyPolygon() || getPolyPolygon())
+ {
+ // one of both has a B2DPolyPolygon based region, ensure both have it
+ // by evtl. conversion
+ const_cast< Region* >(this)->GetAsPolyPolygon();
+ const_cast< Region& >(rRegion).GetAsPolyPolygon();
- if ( pOwnRectBandSep && !pSecondRectBandSep )
- return sal_False;
+ return *rRegion.getPolyPolygon() == *getPolyPolygon();
+ }
- if ( !pOwnRectBandSep && pSecondRectBandSep )
- return sal_False;
+ // both are not empty or null (see above) and if content supported polygon
+ // data the comparison is already done. Only both on RegionBand base can be left,
+ // but better check
+ if(rRegion.getRegionBand() && getRegionBand())
+ {
+ return *rRegion.getRegionBand() == *getRegionBand();
}
- return sal_True;
+ // should not happen, but better deny equality
+ return false;
}
-// -----------------------------------------------------------------------
-
-enum StreamEntryType { STREAMENTRY_BANDHEADER, STREAMENTRY_SEPARATION, STREAMENTRY_END };
-
-SvStream& operator>>( SvStream& rIStrm, Region& rRegion )
+SvStream& operator>>(SvStream& rIStrm, Region& rRegion)
{
- DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
-
- VersionCompat aCompat( rIStrm, STREAM_READ );
- sal_uInt16 nVersion;
- sal_uInt16 nTmp16;
+ VersionCompat aCompat(rIStrm, STREAM_READ);
+ sal_uInt16 nVersion(0);
+ sal_uInt16 nTmp16(0);
- // statische Object haben RefCount von 0
- if ( rRegion.mpImplRegion->mnRefCount )
- {
- if ( rRegion.mpImplRegion->mnRefCount > 1 )
- rRegion.mpImplRegion->mnRefCount--;
- else
- delete rRegion.mpImplRegion;
- }
+ // clear region to be loaded
+ rRegion.SetEmpty();
// get version of streamed region
rIStrm >> nVersion;
@@ -2569,479 +1579,172 @@ SvStream& operator>>( SvStream& rIStrm, Region& rRegion )
// get type of region
rIStrm >> nTmp16;
+ enum RegionType { REGION_NULL, REGION_EMPTY, REGION_RECTANGLE, REGION_COMPLEX };
RegionType meStreamedType = (RegionType)nTmp16;
- switch( meStreamedType )
+ switch(meStreamedType)
{
case REGION_NULL:
- rRegion.mpImplRegion = (ImplRegion*)&aImplNullRegion;
- break;
+ {
+ rRegion.SetNull();
+ break;
+ }
case REGION_EMPTY:
- rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
- break;
+ {
+ rRegion.SetEmpty();
+ break;
+ }
default:
{
- // create instance of implementation class
- rRegion.mpImplRegion = new ImplRegion();
-
- // get header from first element
- rIStrm >> nTmp16;
-
- // get all bands
- rRegion.mpImplRegion->mnRectCount = 0;
- ImplRegionBand* pCurrBand = NULL;
- while ( (StreamEntryType)nTmp16 != STREAMENTRY_END )
- {
- // insert new band or new separation?
- if ( (StreamEntryType)nTmp16 == STREAMENTRY_BANDHEADER )
- {
- //#fdo39428 SvStream no longer supports operator>>(long&)
- sal_Int32 nYTop;
- sal_Int32 nYBottom;
-
- rIStrm >> nYTop;
- rIStrm >> nYBottom;
-
- // create band
- ImplRegionBand* pNewBand = new ImplRegionBand( nYTop, nYBottom );
-
- // first element? -> set as first into the list
- if ( !pCurrBand )
- rRegion.mpImplRegion->mpFirstBand = pNewBand;
- else
- pCurrBand->mpNextBand = pNewBand;
-
- // save pointer for next creation
- pCurrBand = pNewBand;
- }
- else
- {
- //#fdo39428 SvStream no longer supports operator>>(long&)
- sal_Int32 nXLeft;
- sal_Int32 nXRight;
-
- rIStrm >> nXLeft;
- rIStrm >> nXRight;
-
- // add separation
- if ( pCurrBand )
- {
- pCurrBand->Union( nXLeft, nXRight );
- rRegion.mpImplRegion->mnRectCount++;
- }
- }
-
- if( rIStrm.IsEof() )
- {
- OSL_FAIL( "premature end of region stream" );
- delete rRegion.mpImplRegion;
- rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
- return rIStrm;
- }
+ RegionBand* pNewRegionBand = new RegionBand();
+ pNewRegionBand->load(rIStrm);
+ rRegion.mpRegionBand.reset(pNewRegionBand);
- // get next header
- rIStrm >> nTmp16;
- }
-
- if( aCompat.GetVersion() >= 2 )
+ if(aCompat.GetVersion() >= 2)
{
- sal_Bool bHasPolyPolygon;
+ sal_Bool bHasPolyPolygon(sal_False);
rIStrm >> bHasPolyPolygon;
- if( bHasPolyPolygon )
+ if(bHasPolyPolygon)
{
- delete rRegion.mpImplRegion->mpPolyPoly;
- rRegion.mpImplRegion->mpPolyPoly = new PolyPolygon;
- rIStrm >> *( rRegion.mpImplRegion->mpPolyPoly );
+ PolyPolygon* pNewPoly = new PolyPolygon();
+ rIStrm >> *pNewPoly;
+ rRegion.mpPolyPolygon.reset(pNewPoly);
}
}
+
+ break;
}
- break;
}
return rIStrm;
}
-// -----------------------------------------------------------------------
-
SvStream& operator<<( SvStream& rOStrm, const Region& rRegion )
{
- DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
-
- sal_uInt16 nVersion = 2;
- VersionCompat aCompat( rOStrm, STREAM_WRITE, nVersion );
- Region aTmpRegion( rRegion );
-
- // use tmp region to avoid destruction of internal region (polypolygon) of rRegion
- aTmpRegion.ImplPolyPolyRegionToBandRegion();
+ const sal_uInt16 nVersion(2);
+ VersionCompat aCompat(rOStrm, STREAM_WRITE, nVersion);
// put version
rOStrm << nVersion;
// put type
- rOStrm << (sal_uInt16)aTmpRegion.GetType();
+ enum RegionType { REGION_NULL, REGION_EMPTY, REGION_RECTANGLE, REGION_COMPLEX };
+ RegionType aRegionType(REGION_COMPLEX);
+ bool bEmpty(rRegion.IsEmpty());
- // put all bands if not null or empty
- if ( (aTmpRegion.mpImplRegion != &aImplEmptyRegion) && (aTmpRegion.mpImplRegion != &aImplNullRegion) )
+ if(!bEmpty && rRegion.getB2DPolyPolygon() && 0 == rRegion.getB2DPolyPolygon()->count())
{
- ImplRegionBand* pBand = aTmpRegion.mpImplRegion->mpFirstBand;
- while ( pBand )
- {
- // put boundaries
- //#fdo39428 SvStream no longer supports operator<<(long)
- rOStrm << (sal_uInt16) STREAMENTRY_BANDHEADER;
- rOStrm << sal::static_int_cast<sal_Int32>(pBand->mnYTop);
- rOStrm << sal::static_int_cast<sal_Int32>(pBand->mnYBottom);
-
- // put separations of current band
- ImplRegionBandSep* pSep = pBand->mpFirstSep;
- while ( pSep )
- {
- // put separation
- //#fdo39428 SvStream no longer supports operator<<(long)
- rOStrm << (sal_uInt16) STREAMENTRY_SEPARATION;
- rOStrm << sal::static_int_cast<sal_Int32>(pSep->mnXLeft);
- rOStrm << sal::static_int_cast<sal_Int32>(pSep->mnXRight);
-
- // next separation from current band
- pSep = pSep->mpNextSep;
- }
-
- pBand = pBand->mpNextBand;
- }
-
- // put endmarker
- rOStrm << (sal_uInt16) STREAMENTRY_END;
-
- // write polypolygon if available
- const sal_Bool bHasPolyPolygon = rRegion.HasPolyPolygon();
- rOStrm << bHasPolyPolygon;
-
- if( bHasPolyPolygon )
- {
- // #i105373#
- PolyPolygon aNoCurvePolyPolygon;
- rRegion.GetPolyPolygon().AdaptiveSubdivide(aNoCurvePolyPolygon);
-
- rOStrm << aNoCurvePolyPolygon;
- }
+ OSL_ENSURE(false, "Region with empty B2DPolyPolygon, should not be created (!)");
+ bEmpty = true;
}
- return rOStrm;
-}
-
-// -----------------------------------------------------------------------
-
-void Region::ImplBeginAddRect()
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- // statische Object haben RefCount von 0
- if ( mpImplRegion->mnRefCount )
+ if(!bEmpty && rRegion.getPolyPolygon() && 0 == rRegion.getPolyPolygon()->Count())
{
- if ( mpImplRegion->mnRefCount > 1 )
- mpImplRegion->mnRefCount--;
- else
- delete mpImplRegion;
+ OSL_ENSURE(false, "Region with empty PolyPolygon, should not be created (!)");
+ bEmpty = true;
}
- // create fresh region
- mpImplRegion = new ImplRegion();
-}
-
-// -----------------------------------------------------------------------
-
-sal_Bool Region::ImplAddRect( const Rectangle& rRect )
-{
- // Hier kein CheckThis, da nicht alle Daten auf Stand
-
- if ( rRect.IsEmpty() )
- return sal_True;
-
- // get justified rectangle
- long nTop;
- long nBottom;
- long nLeft;
- long nRight;
- if ( rRect.Top() <= rRect.Bottom() )
+ if(bEmpty)
{
- nTop = rRect.Top();
- nBottom = rRect.Bottom();
+ aRegionType = REGION_EMPTY;
}
- else
+ else if(rRegion.IsNull())
{
- nTop = rRect.Bottom();
- nBottom = rRect.Top();
+ aRegionType = REGION_NULL;
}
- if ( rRect.Left() <= rRect.Right() )
+ else if(rRegion.getRegionBand() && rRegion.getRegionBand()->isSingleRectangle())
{
- nLeft = rRect.Left();
- nRight = rRect.Right();
+ aRegionType = REGION_RECTANGLE;
}
- else
- {
- nLeft = rRect.Right();
- nRight = rRect.Left();
- }
-
- if ( !mpImplRegion->mpLastCheckedBand )
- {
- // create new band
- mpImplRegion->mpLastCheckedBand = new ImplRegionBand( nTop, nBottom );
-
- // set band as current
- mpImplRegion->mpFirstBand = mpImplRegion->mpLastCheckedBand;
- mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
- }
- else
- {
- DBG_ASSERT( nTop >= mpImplRegion->mpLastCheckedBand->mnYTop,
- "Region::ImplAddRect() - nTopY < nLastTopY" );
- // new band? create it!
- if ( (nTop != mpImplRegion->mpLastCheckedBand->mnYTop) ||
- (nBottom != mpImplRegion->mpLastCheckedBand->mnYBottom) )
- {
- // create new band
- ImplRegionBand* pNewRegionBand = new ImplRegionBand( nTop, nBottom );
+ rOStrm << (sal_uInt16)aRegionType;
- // append band to the end
- mpImplRegion->mpLastCheckedBand->mpNextBand = pNewRegionBand;
+ // get RegionBand
+ const RegionBand* pRegionBand = rRegion.getRegionBand();
- // skip to the new band
- mpImplRegion->mpLastCheckedBand = mpImplRegion->mpLastCheckedBand->mpNextBand;
- }
-
- // Insert Sep
- mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
- }
-
- return sal_True;
-}
-
-// -----------------------------------------------------------------------
-
-void Region::ImplEndAddRect()
-{
- // check if we are empty
- if ( !mpImplRegion->mpFirstBand )
- {
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
- return;
- }
-
- // check if we have something to optimize
- if ( !mpImplRegion->mpFirstBand->mpNextBand )
- {
- // update mpImplRegion->mnRectCount, because no OptimizeBandList is called
- ImplRegionBandSep* pSep = mpImplRegion->mpFirstBand->mpFirstSep;
- mpImplRegion->mnRectCount = 0;
- while( pSep )
- {
- mpImplRegion->mnRectCount++;
- pSep = pSep->mpNextSep;
- }
-
- // Erst hier testen, da hier die Daten wieder stimmen
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
- return;
- }
-
- // have to revert list? -> do it now!
- if ( mpImplRegion->mpFirstBand->mnYTop >
- mpImplRegion->mpFirstBand->mpNextBand->mnYTop )
+ if(pRegionBand)
{
- ImplRegionBand * pNewFirstRegionBand;
-
- // initialize temp list with first element
- pNewFirstRegionBand = mpImplRegion->mpFirstBand;
- mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
- pNewFirstRegionBand->mpNextBand = NULL;
-
- // insert elements to the temp list
- while ( mpImplRegion->mpFirstBand )
- {
- ImplRegionBand * pSavedRegionBand = pNewFirstRegionBand;
- pNewFirstRegionBand = mpImplRegion->mpFirstBand;
- mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
- pNewFirstRegionBand->mpNextBand = pSavedRegionBand;
- }
-
- // set temp list as new list
- mpImplRegion->mpFirstBand = pNewFirstRegionBand;
+ pRegionBand->save(rOStrm);
}
- // cleanup
- if ( !mpImplRegion->OptimizeBandList() )
- {
- delete mpImplRegion;
- mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
- }
-
- // Erst hier testen, da hier die Daten wieder stimmen
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-}
-
-// -----------------------------------------------------------------------
-
-sal_uLong Region::GetRectCount() const
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- ((Region*)this)->ImplPolyPolyRegionToBandRegion();
-
-#ifdef DBG_UTIL
- sal_uLong nCount = 0;
+ // write polypolygon if available
+ const sal_Bool bHasPolyPolygon(rRegion.HasPolyPolygonOrB2DPolyPolygon());
+ rOStrm << bHasPolyPolygon;
- // all bands if not null or empty
- if ( (mpImplRegion != &aImplEmptyRegion) && (mpImplRegion != &aImplNullRegion) )
+ if(bHasPolyPolygon)
{
- ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
- while ( pBand )
- {
- ImplRegionBandSep* pSep = pBand->mpFirstSep;
- while( pSep )
- {
- nCount++;
- pSep = pSep->mpNextSep;
- }
-
- pBand = pBand->mpNextBand;
- }
- }
-
- DBG_ASSERT( mpImplRegion->mnRectCount == nCount, "Region: invalid mnRectCount!" );
-#endif
+ // #i105373#
+ PolyPolygon aNoCurvePolyPolygon;
+ rRegion.GetAsPolyPolygon().AdaptiveSubdivide(aNoCurvePolyPolygon);
- return mpImplRegion->mnRectCount;
-}
-
-// -----------------------------------------------------------------------
-
-RegionHandle Region::BeginEnumRects()
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- ImplPolyPolyRegionToBandRegion();
-
- // no internal data? -> region is empty!
- if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return 0;
-
- // no band in the list? -> region is empty!
- if ( mpImplRegion->mpFirstBand == NULL )
- {
- DBG_ASSERT( mpImplRegion->mpFirstBand, "Region::BeginEnumRects() First Band is Empty!" );
- return 0;
+ rOStrm << aNoCurvePolyPolygon;
}
- ImplRegionHandle* pData = new ImplRegionHandle;
- pData->mpRegion = new Region( *this );
- pData->mbFirst = sal_True;
-
- // save pointers
- pData->mpCurrRectBand = pData->mpRegion->mpImplRegion->mpFirstBand;
- pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
-
- return (RegionHandle)pData;
+ return rOStrm;
}
-// -----------------------------------------------------------------------
-
-sal_Bool Region::GetEnumRects( RegionHandle pVoidData, Rectangle& rRect )
+void Region::GetRegionRectangles(RectangleVector& rTarget) const
{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ // clear returnvalues
+ rTarget.clear();
- ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
- if ( !pData )
- return sal_False;
+ // ensure RegionBand existance
+ const_cast< Region* >(this)->GetAsRegionBand();
+ const RegionBand* pRegionBand = getRegionBand();
- if ( pData->mbFirst )
- pData->mbFirst = sal_False;
- else
+ if(pRegionBand)
{
- // get next separation from current band
- pData->mpCurrRectBandSep = pData->mpCurrRectBandSep->mpNextSep;
-
- // no separation found? -> go to next band!
- if ( !pData->mpCurrRectBandSep )
- {
- // get next band
- pData->mpCurrRectBand = pData->mpCurrRectBand->mpNextBand;
-
- // no band found? -> not further rectangles!
- if ( !pData->mpCurrRectBand )
- return sal_False;
-
- // get first separation in current band
- pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
- }
+ pRegionBand->GetRegionRectangles(rTarget);
}
-
- // get boundaries of current rectangle
- rRect.Top() = pData->mpCurrRectBand->mnYTop;
- rRect.Bottom() = pData->mpCurrRectBand->mnYBottom;
- rRect.Left() = pData->mpCurrRectBandSep->mnXLeft;
- rRect.Right() = pData->mpCurrRectBandSep->mnXRight;
- return sal_True;
}
-// -----------------------------------------------------------------------
-
-void Region::EndEnumRects( RegionHandle pVoidData )
-{
- DBG_CHKTHIS( Region, ImplDbgTestRegion );
-
- ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
- if ( !pData )
- return;
-
- // cleanup
- delete pData->mpRegion;
- delete pData;
-}
-
-// -----------------------------------------------------------------------
-
static inline bool ImplPolygonRectTest( const Polygon& rPoly, Rectangle* pRectOut = NULL )
{
bool bIsRect = false;
const Point* pPoints = rPoly.GetConstPointAry();
sal_uInt16 nPoints = rPoly.GetSize();
+
if( nPoints == 4 || (nPoints == 5 && pPoints[0] == pPoints[4]) )
{
- long nX1 = pPoints[0].X(), nX2 = pPoints[2].X(),
- nY1 = pPoints[0].Y(), nY2 = pPoints[2].Y();
- if( ( (pPoints[1].X() == nX1 && pPoints[3].X() == nX2) &&
- (pPoints[1].Y() == nY2 && pPoints[3].Y() == nY1) )
- ||
- ( (pPoints[1].X() == nX2 && pPoints[3].X() == nX1) &&
- (pPoints[1].Y() == nY1 && pPoints[3].Y() == nY2) ) )
+ long nX1 = pPoints[0].X(), nX2 = pPoints[2].X(), nY1 = pPoints[0].Y(), nY2 = pPoints[2].Y();
+
+ if( ( (pPoints[1].X() == nX1 && pPoints[3].X() == nX2) && (pPoints[1].Y() == nY2 && pPoints[3].Y() == nY1) )
+ || ( (pPoints[1].X() == nX2 && pPoints[3].X() == nX1) && (pPoints[1].Y() == nY1 && pPoints[3].Y() == nY2) ) )
{
bIsRect = true;
+
if( pRectOut )
{
long nSwap;
+
if( nX2 < nX1 )
{
nSwap = nX2;
nX2 = nX1;
nX1 = nSwap;
}
+
if( nY2 < nY1 )
{
nSwap = nY2;
nY2 = nY1;
nY1 = nSwap;
}
+
if( nX2 != nX1 )
+ {
nX2--;
+ }
+
if( nY2 != nY1 )
+ {
nY2--;
+ }
+
pRectOut->Left() = nX1;
pRectOut->Right() = nX2;
pRectOut->Top() = nY1;
@@ -3049,6 +1752,7 @@ static inline bool ImplPolygonRectTest( const Polygon& rPoly, Rectangle* pRectOu
}
}
}
+
return bIsRect;
}
@@ -3058,31 +1762,46 @@ Region Region::GetRegionFromPolyPolygon( const PolyPolygon& rPolyPoly )
// check if it's worth extracting the XOr'ing the Rectangles
// empiricism shows that break even between XOr'ing rectangles separately
- // and ImplPolyPolyRegionToBandRegion is at half rectangles/half polygons
+ // and ImplCreateRegionBandFromPolyPolygon is at half rectangles/half polygons
int nPolygonRects = 0, nPolygonPolygons = 0;
int nPolygons = rPolyPoly.Count();
for( sal_uInt16 i = 0; i < nPolygons; i++ )
{
const Polygon& rPoly = rPolyPoly[i];
+
if( ImplPolygonRectTest( rPoly ) )
+ {
nPolygonRects++;
+ }
else
+ {
nPolygonPolygons++;
+ }
}
+
if( nPolygonPolygons > nPolygonRects )
+ {
return Region( rPolyPoly );
+ }
Region aResult;
Rectangle aRect;
+
for( sal_uInt16 i = 0; i < nPolygons; i++ )
{
const Polygon& rPoly = rPolyPoly[i];
+
if( ImplPolygonRectTest( rPoly, &aRect ) )
+ {
aResult.XOr( aRect );
+ }
else
+ {
aResult.XOr( Region(rPoly) );
+ }
}
+
return aResult;
}
diff --git a/vcl/source/gdi/regionband.cxx b/vcl/source/gdi/regionband.cxx
new file mode 100644
index 000000000000..1a4d249c0a1d
--- /dev/null
+++ b/vcl/source/gdi/regionband.cxx
@@ -0,0 +1,1377 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tools/stream.hxx>
+#include <tools/debug.hxx>
+#include <regionband.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+DBG_NAME( RegionBand )
+DBG_NAMEEX( Polygon )
+DBG_NAMEEX( PolyPolygon )
+
+//////////////////////////////////////////////////////////////////////////////
+
+RegionBand::RegionBand()
+: mpFirstBand(0),
+ mpLastCheckedBand(0)
+{
+ DBG_CTOR(RegionBand, ImplDbgTestRegionBand);
+}
+
+RegionBand::RegionBand(const RegionBand& rRef)
+: mpFirstBand(0),
+ mpLastCheckedBand(0)
+{
+ *this = rRef;
+ DBG_CTOR(RegionBand, ImplDbgTestRegionBand);
+}
+
+RegionBand& RegionBand::operator=(const RegionBand& rRef)
+{
+ ImplRegionBand* pPrevBand = 0;
+ ImplRegionBand* pBand = rRef.mpFirstBand;
+
+ while(pBand)
+ {
+ ImplRegionBand* pNewBand = new ImplRegionBand(*pBand);
+
+ // first element? -> set as first into the list
+ if(pBand == rRef.mpFirstBand)
+ {
+ mpFirstBand = pNewBand;
+ }
+ else
+ {
+ pPrevBand->mpNextBand = pNewBand;
+ }
+
+ pPrevBand = pNewBand;
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ DBG_CHKOBJ(&rRef, RegionBand, ImplDbgTestRegionBand);
+
+ return *this;
+}
+
+RegionBand::RegionBand(const Rectangle& rRect)
+: mpFirstBand(0),
+ mpLastCheckedBand(0)
+{
+ const long nTop(std::min(rRect.Top(), rRect.Bottom()));
+ const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
+ const long nLeft(std::min(rRect.Left(), rRect.Right()));
+ const long nRight(std::max(rRect.Left(), rRect.Right()));
+
+ // add band with boundaries of the rectangle
+ mpFirstBand = new ImplRegionBand(nTop, nBottom);
+
+ // Set left and right boundaries of the band
+ mpFirstBand->Union(nLeft, nRight);
+
+ DBG_CTOR(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::implReset()
+{
+ ImplRegionBand* pBand = mpFirstBand;
+
+ while(pBand)
+ {
+ ImplRegionBand* pTempBand = pBand->mpNextBand;
+ delete pBand;
+ pBand = pTempBand;
+ }
+
+ mpLastCheckedBand = 0;
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+RegionBand::~RegionBand()
+{
+ implReset();
+ DBG_DTOR(RegionBand, ImplDbgTestRegionBand);
+}
+
+bool RegionBand::operator==( const RegionBand& rRegionBand ) const
+{
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ DBG_CHKOBJ(&rRegionBand, RegionBand, ImplDbgTestRegionBand);
+
+ // initialise pointers
+ ImplRegionBand* pOwnRectBand = mpFirstBand;
+ ImplRegionBandSep* pOwnRectBandSep = pOwnRectBand->mpFirstSep;
+ ImplRegionBand* pSecondRectBand = rRegionBand.mpFirstBand;
+ ImplRegionBandSep* pSecondRectBandSep = pSecondRectBand->mpFirstSep;
+
+ while ( pOwnRectBandSep && pSecondRectBandSep )
+ {
+ // get boundaries of current rectangle
+ long nOwnXLeft = pOwnRectBandSep->mnXLeft;
+ long nSecondXLeft = pSecondRectBandSep->mnXLeft;
+
+ if ( nOwnXLeft != nSecondXLeft )
+ {
+ return false;
+ }
+
+ long nOwnYTop = pOwnRectBand->mnYTop;
+ long nSecondYTop = pSecondRectBand->mnYTop;
+
+ if ( nOwnYTop != nSecondYTop )
+ {
+ return false;
+ }
+
+ long nOwnXRight = pOwnRectBandSep->mnXRight;
+ long nSecondXRight = pSecondRectBandSep->mnXRight;
+
+ if ( nOwnXRight != nSecondXRight )
+ {
+ return false;
+ }
+
+ long nOwnYBottom = pOwnRectBand->mnYBottom;
+ long nSecondYBottom = pSecondRectBand->mnYBottom;
+
+ if ( nOwnYBottom != nSecondYBottom )
+ {
+ return false;
+ }
+
+ // get next separation from current band
+ pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pOwnRectBandSep )
+ {
+ // get next band
+ pOwnRectBand = pOwnRectBand->mpNextBand;
+
+ // get first separation in current band
+ if( pOwnRectBand )
+ {
+ pOwnRectBandSep = pOwnRectBand->mpFirstSep;
+ }
+ }
+
+ // get next separation from current band
+ pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pSecondRectBandSep )
+ {
+ // get next band
+ pSecondRectBand = pSecondRectBand->mpNextBand;
+
+ // get first separation in current band
+ if( pSecondRectBand )
+ {
+ pSecondRectBandSep = pSecondRectBand->mpFirstSep;
+ }
+ }
+
+ if ( pOwnRectBandSep && !pSecondRectBandSep )
+ {
+ return false;
+ }
+
+ if ( !pOwnRectBandSep && pSecondRectBandSep )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+enum StreamEntryType { STREAMENTRY_BANDHEADER, STREAMENTRY_SEPARATION, STREAMENTRY_END };
+
+void RegionBand::load(SvStream& rIStrm)
+{
+ // clear this nstance's data
+ implReset();
+
+ // get all bands
+ ImplRegionBand* pCurrBand = 0;
+
+ // get header from first element
+ sal_uInt16 nTmp16(0);
+ rIStrm >> nTmp16;
+
+ while(STREAMENTRY_END != (StreamEntryType)nTmp16)
+ {
+ // insert new band or new separation?
+ if(STREAMENTRY_BANDHEADER == (StreamEntryType)nTmp16)
+ {
+ long nYTop;
+ long nYBottom;
+
+ rIStrm >> nYTop;
+ rIStrm >> nYBottom;
+
+ // create band
+ ImplRegionBand* pNewBand = new ImplRegionBand( nYTop, nYBottom );
+
+ // first element? -> set as first into the list
+ if ( !pCurrBand )
+ {
+ mpFirstBand = pNewBand;
+ }
+ else
+ {
+ pCurrBand->mpNextBand = pNewBand;
+ }
+
+ // save pointer for next creation
+ pCurrBand = pNewBand;
+ }
+ else
+ {
+ long nXLeft;
+ long nXRight;
+
+ rIStrm >> nXLeft;
+ rIStrm >> nXRight;
+
+ // add separation
+ if ( pCurrBand )
+ {
+ pCurrBand->Union( nXLeft, nXRight );
+ }
+ }
+
+ if( rIStrm.IsEof() )
+ {
+ OSL_ENSURE(false, "premature end of region stream" );
+ implReset();
+ return;
+ }
+
+ // get next header
+ rIStrm >> nTmp16;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::save(SvStream& rOStrm) const
+{
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ ImplRegionBand* pBand = mpFirstBand;
+
+ while(pBand)
+ {
+ // put boundaries
+ rOStrm << (sal_uInt16)STREAMENTRY_BANDHEADER;
+ rOStrm << pBand->mnYTop;
+ rOStrm << pBand->mnYBottom;
+
+ // put separations of current band
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+
+ while(pSep)
+ {
+ // put separation
+ rOStrm << (sal_uInt16)STREAMENTRY_SEPARATION;
+ rOStrm << pSep->mnXLeft;
+ rOStrm << pSep->mnXRight;
+
+ // next separation from current band
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // put endmarker
+ rOStrm << (sal_uInt16)STREAMENTRY_END;
+}
+
+bool RegionBand::isSingleRectangle() const
+{
+ // just one band?
+ if(mpFirstBand && !mpFirstBand->mpNextBand)
+ {
+ // just one sep?
+ if(mpFirstBand->mpFirstSep && !mpFirstBand->mpFirstSep->mpNextSep)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void RegionBand::InsertBand(ImplRegionBand* pPreviousBand, ImplRegionBand* pBandToInsert)
+{
+ OSL_ASSERT(pBandToInsert!=NULL);
+
+ if(!pPreviousBand)
+ {
+ // Insert band before all others.
+ if(mpFirstBand)
+ {
+ mpFirstBand->mpPrevBand = pBandToInsert;
+ }
+
+ pBandToInsert->mpNextBand = mpFirstBand;
+ mpFirstBand = pBandToInsert;
+ }
+ else
+ {
+ // Insert band directly after pPreviousBand.
+ pBandToInsert->mpNextBand = pPreviousBand->mpNextBand;
+ pPreviousBand->mpNextBand = pBandToInsert;
+ pBandToInsert->mpPrevBand = pPreviousBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::processPoints()
+{
+ ImplRegionBand* pRegionBand = mpFirstBand;
+
+ while(pRegionBand)
+ {
+ // generate separations from the lines and process union
+ pRegionBand->ProcessPoints();
+ pRegionBand = pRegionBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+/** This function is similar to the RegionBand::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 RegionBand::ImplAddMissingBands(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 = 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));
+ 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.
+ InsertBand(
+ pPreviousBand,
+ new ImplRegionBand(
+ nCurrentTop,
+ nBottom));
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::CreateBandRange(long nYTop, long nYBottom)
+{
+ // 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;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+bool RegionBand::InsertLine(const Point& rStartPt, const Point& rEndPt, long nLineId)
+{
+ long nX, nY;
+
+ // lines consisting of a single point do not interest here
+ if ( rStartPt == rEndPt )
+ {
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+ }
+
+ LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
+ if ( rStartPt.X() == rEndPt.X() )
+ {
+ // vertical line
+ const long nEndY = rEndPt.Y();
+
+ nX = rStartPt.X();
+ nY = rStartPt.Y();
+
+ if( nEndY > nY )
+ {
+ for ( ; nY <= nEndY; nY++ )
+ {
+ Point aNewPoint( nX, nY );
+ InsertPoint( aNewPoint, nLineId,
+ (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
+ eLineType );
+ }
+ }
+ else
+ {
+ 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;
+
+ 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;
+ }
+ }
+
+ // last point
+ InsertPoint( Point( nEndX, nEndY ), nLineId, true, eLineType );
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+}
+
+bool RegionBand::InsertPoint(const Point &rPoint, long nLineID, bool bEndPoint, LineType eLineType)
+{
+ DBG_ASSERT( mpFirstBand != NULL, "RegionBand::InsertPoint - no bands available!" );
+
+ if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ {
+ mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
+ return 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 );
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+ }
+
+ mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
+ }
+
+ OSL_ENSURE(false, "RegionBand::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 );
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+ }
+
+ mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
+ }
+
+ OSL_ENSURE(false, "RegionBand::InsertPoint reached the beginning of the list!" );
+ }
+
+ OSL_ENSURE(false, "RegionBand::InsertPoint point not inserted!" );
+
+ // reinitialize pointer (should never be reached!)
+ mpLastCheckedBand = mpFirstBand;
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return false;
+}
+
+bool RegionBand::OptimizeBandList()
+{
+ ImplRegionBand* pPrevBand = 0;
+ ImplRegionBand* pBand = mpFirstBand;
+
+ while ( pBand )
+ {
+ const 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 )
+ {
+ pSep = pSep->mpNextSep;
+ }
+
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ }
+ }
+
+#ifdef DBG_UTIL
+ pBand = mpFirstBand;
+ while ( pBand )
+ {
+ DBG_ASSERT( pBand->mpFirstSep != NULL, "Exiting RegionBand::OptimizeBandList(): empty band in region!" );
+
+ if ( pBand->mnYBottom < pBand->mnYTop )
+ OSL_ENSURE(false, "RegionBand::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
+
+ if ( pBand->mpNextBand )
+ {
+ if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
+ OSL_ENSURE(false, "RegionBand::OptimizeBandList(): overlapping bands in region!" );
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+#endif
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return (0 != mpFirstBand);
+}
+
+void RegionBand::Move(long nHorzMove, long nVertMove)
+{
+ ImplRegionBand* pBand = mpFirstBand;
+
+ while(pBand)
+ {
+ // process the vertical move
+ if(nVertMove)
+ {
+ pBand->mnYTop = pBand->mnYTop + nVertMove;
+ pBand->mnYBottom = pBand->mnYBottom + nVertMove;
+ }
+
+ // process the horizontal move
+ if(nHorzMove)
+ {
+ pBand->MoveX(nHorzMove);
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::Scale(double fScaleX, double fScaleY)
+{
+ ImplRegionBand* pBand = mpFirstBand;
+
+ while(pBand)
+ {
+ // process the vertical move
+ if(0.0 != fScaleY)
+ {
+ pBand->mnYTop = basegfx::fround(pBand->mnYTop * fScaleY);
+ pBand->mnYBottom = basegfx::fround(pBand->mnYBottom * fScaleY);
+ }
+
+ // process the horizontal move
+ if(0.0 != fScaleX)
+ {
+ pBand->ScaleX(fScaleX);
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::InsertBands(long nTop, long nBottom)
+{
+ // region empty? -> set rectagle as first entry!
+ if ( !mpFirstBand )
+ {
+ // add band with boundaries of the rectangle
+ mpFirstBand = new ImplRegionBand( nTop, nBottom );
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return;
+ }
+
+ // find/insert bands for the boundaries of the rectangle
+ bool bTopBoundaryInserted = false;
+ bool bTop2BoundaryInserted = false;
+ bool bBottomBoundaryInserted = 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;
+
+ bTopBoundaryInserted = true;
+ }
+
+ // 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;
+ }
+
+ // 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;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+bool RegionBand::InsertSingleBand(ImplRegionBand* pBand, long nYBandPosition)
+{
+ // boundary already included in band with height 1? -> nothing to do!
+ if ( (pBand->mnYTop == pBand->mnYBottom) && (nYBandPosition == pBand->mnYTop) )
+ {
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return 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;
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ 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;
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+ }
+
+ // 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;
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+ }
+
+ if ( nYBandPosition > pBand->mnYBottom )
+ {
+ // create new band
+ pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
+
+ // append band to the list
+ pBand->mpNextBand = pNewBand;
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+ }
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return false;
+}
+
+void RegionBand::Union(long nLeft, long nTop, long nRight, long nBottom)
+{
+ DBG_ASSERT( nLeft <= nRight, "RegionBand::Union() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "RegionBand::Union() - nTop > nBottom" );
+
+ // process union
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ 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) )
+ {
+ OSL_ENSURE(false, "RegionBand::Union() - Bands not sorted!" );
+ }
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::Intersect(long nLeft, long nTop, long nRight, long nBottom)
+{
+ // process intersections
+ ImplRegionBand* pPrevBand = 0;
+ ImplRegionBand* pBand = 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 == mpFirstBand)
+ {
+ mpFirstBand = pBand->mpNextBand;
+ }
+ else
+ {
+ pPrevBand->mpNextBand = pBand->mpNextBand;
+ }
+
+ pBand = pBand->mpNextBand;
+ delete pOldBand;
+ }
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::Union(const RegionBand& rSource)
+{
+ // apply all rectangles from rSource to this
+ ImplRegionBand* pBand = rSource.mpFirstBand;
+
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ InsertBands(pBand->mnYTop, pBand->mnYBottom);
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+
+ while(pSep)
+ {
+ Union(pSep->mnXLeft, pBand->mnYTop, pSep->mnXRight, pBand->mnYBottom);
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::Exclude(long nLeft, long nTop, long nRight, long nBottom)
+{
+ DBG_ASSERT( nLeft <= nRight, "RegionBand::Exclude() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "RegionBand::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))
+ {
+ OSL_ENSURE(false, "RegionBand::Exclude() - Bands not sorted!" );
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::XOr(long nLeft, long nTop, long nRight, long nBottom)
+{
+ DBG_ASSERT( nLeft <= nRight, "RegionBand::Exclude() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "RegionBand::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))
+ {
+ OSL_ENSURE(false, "RegionBand::XOr() - Bands not sorted!" );
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+void RegionBand::Intersect(const RegionBand& rSource)
+{
+ // mark all bands as untouched
+ ImplRegionBand* pBand = mpFirstBand;
+
+ while ( pBand )
+ {
+ pBand->mbTouched = false;
+ pBand = pBand->mpNextBand;
+ }
+
+ pBand = rSource.mpFirstBand;
+
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // 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
+ 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
+ Exclude( pSep->mnXRight+1, pBand->mnYTop, LONG_MAX-1, pBand->mnYBottom );
+ }
+ else
+ {
+ // process intersection and do not remove untouched bands
+ Exclude( pSep->mnXRight+1, pBand->mnYTop, pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
+ }
+
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // remove all untouched bands if bands allready left
+ ImplRegionBand* pPrevBand = 0;
+ pBand = mpFirstBand;
+
+ while ( pBand )
+ {
+ if ( !pBand->mbTouched )
+ {
+ // 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
+ {
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+}
+
+bool RegionBand::Exclude(const RegionBand& rSource)
+{
+ // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
+ ImplRegionBand* pBand = rSource.mpFirstBand;
+
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+
+ while ( pSep )
+ {
+ Exclude( pSep->mnXLeft, pBand->mnYTop, pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ // to test less bands, already check in the loop
+ if ( !OptimizeBandList() )
+ {
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return false;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+ return true;
+}
+
+Rectangle RegionBand::GetBoundRect() const
+{
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+
+ // get the boundaries of the first band
+ long nYTop(mpFirstBand->mnYTop);
+ long nYBottom(mpFirstBand->mnYBottom);
+ long nXLeft(mpFirstBand->GetXLeftBoundary());
+ long nXRight(mpFirstBand->GetXRightBoundary());
+
+ // look in the band list (don't test first band again!)
+ ImplRegionBand* pBand = mpFirstBand->mpNextBand;
+
+ while ( pBand )
+ {
+ nYBottom = pBand->mnYBottom;
+ nXLeft = std::min( nXLeft, pBand->GetXLeftBoundary() );
+ nXRight = std::max( nXRight, pBand->GetXRightBoundary() );
+
+ pBand = pBand->mpNextBand;
+ }
+
+ return Rectangle( nXLeft, nYTop, nXRight, nYBottom );
+}
+
+void RegionBand::XOr(const RegionBand& rSource)
+{
+ ImplRegionBand* pBand = rSource.mpFirstBand;
+
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+
+ while ( pSep )
+ {
+ XOr( pSep->mnXLeft, pBand->mnYTop, pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+bool RegionBand::IsInside(const Point& rPoint) const
+{
+ DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
+
+ // search band list
+ ImplRegionBand* pBand = mpFirstBand;
+
+ while(pBand)
+ {
+ // is point within band?
+ if((pBand->mnYTop <= rPoint.Y()) && (pBand->mnYBottom >= rPoint.Y()))
+ {
+ // is point within separation of the band?
+ if(pBand->IsInside(rPoint.X()))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ return false;
+}
+
+void RegionBand::GetRegionRectangles(RectangleVector& rTarget) const
+{
+ // clear result vector
+ rTarget.clear();
+ ImplRegionBand* mpCurrRectBand = mpFirstBand;
+ Rectangle aRectangle;
+
+ while(mpCurrRectBand)
+ {
+ ImplRegionBandSep* mpCurrRectBandSep = mpCurrRectBand->mpFirstSep;
+
+ aRectangle.Top() = mpCurrRectBand->mnYTop;
+ aRectangle.Bottom() = mpCurrRectBand->mnYBottom;
+
+ while(mpCurrRectBandSep)
+ {
+ aRectangle.Left() = mpCurrRectBandSep->mnXLeft;
+ aRectangle.Right() = mpCurrRectBandSep->mnXRight;
+ rTarget.push_back(aRectangle);
+ mpCurrRectBandSep = mpCurrRectBandSep->mpNextSep;
+ }
+
+ mpCurrRectBand = mpCurrRectBand->mpNextBand;
+ }
+}
+
+sal_uInt32 RegionBand::getRectangleCount() const
+{
+ sal_uInt32 nCount = 0;
+ const ImplRegionBand* pBand = mpFirstBand;
+
+ while(pBand)
+ {
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+
+ while(pSep)
+ {
+ nCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ return 0;
+}
+
+#ifdef DBG_UTIL
+const char* ImplDbgTestRegionBand(const void* pObj)
+{
+ const RegionBand* pRegionBand = reinterpret_cast< const RegionBand* >(pObj);
+
+ if(pRegionBand)
+ {
+ const ImplRegionBand* pBand = pRegionBand->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)
+ {
+ 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 )
+ {
+ return "Sep-mbRemoved overwrite";
+ }
+
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index 01137b635ae2..529346a7768d 100644
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -31,7 +31,6 @@
#include <vcl/unowrap.hxx>
#include <window.h>
-#include <region.h>
#include <outdev.h>
#include <sallayout.hxx>
#include <salgdi.hxx>
@@ -235,28 +234,38 @@ sal_Bool SalGraphics::mirror( sal_uInt32 nPoints, const SalPoint *pPtAry, SalPoi
void SalGraphics::mirror( Region& rRgn, const OutputDevice *pOutDev, bool bBack ) const
{
- if( rRgn.HasPolyPolygon() )
+ if( rRgn.HasPolyPolygonOrB2DPolyPolygon() )
{
- basegfx::B2DPolyPolygon aPolyPoly( rRgn.ConvertToB2DPolyPolygon() );
- aPolyPoly = mirror( aPolyPoly, pOutDev, bBack );
- rRgn = Region( aPolyPoly );
+ const basegfx::B2DPolyPolygon aPolyPoly(mirror(rRgn.GetAsB2DPolyPolygon(), pOutDev, bBack));
+
+ rRgn = Region(aPolyPoly);
}
else
{
- ImplRegionInfo aInfo;
- bool bRegionRect;
- Region aMirroredRegion;
- long nX, nY, nWidth, nHeight;
+ RectangleVector aRectangles;
+ rRgn.GetRegionRectangles(aRectangles);
+ rRgn.SetEmpty();
- bRegionRect = rRgn.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
- while ( bRegionRect )
+ for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
- mirror( aRect, pOutDev, bBack );
- aMirroredRegion.Union( aRect );
- bRegionRect = rRgn.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ mirror(*aRectIter, pOutDev, bBack);
+ rRgn.Union(*aRectIter);
}
- rRgn = aMirroredRegion;
+
+ //ImplRegionInfo aInfo;
+ //bool bRegionRect;
+ //Region aMirroredRegion;
+ //long nX, nY, nWidth, nHeight;
+ //
+ //bRegionRect = rRgn.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ //while ( bRegionRect )
+ //{
+ // Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
+ // mirror( aRect, pOutDev, bBack );
+ // aMirroredRegion.Union( aRect );
+ // bRegionRect = rRgn.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ //}
+ //rRgn = aMirroredRegion;
}
}
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 1c8e8908ecc9..b9d89429dade 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -68,7 +68,6 @@
#include "window.h"
#include "toolbox.h"
#include "outdev.h"
-#include "region.h"
#include "brdwin.hxx"
#include "helpwin.hxx"
#include "sallayout.hxx"
@@ -152,8 +151,8 @@ ImplAccessibleInfos::~ImplAccessibleInfos()
WindowImpl::WindowImpl( WindowType nType )
{
maZoom = Fraction( 1, 1 );
- maWinRegion = Region( REGION_NULL );
- maWinClipRegion = Region( REGION_NULL );
+ maWinRegion = Region(true);
+ maWinClipRegion = Region(true);
mpWinData = NULL; // Extra Window Data, that we dont need for all windows
mpOverlapData = NULL; // Overlap Data
mpFrameData = NULL; // Frame Data
@@ -1834,23 +1833,38 @@ sal_Bool Window::ImplSysObjClip( const Region* pOldRegion )
aRegion.Move( -mnOutOffX, -mnOutOffY );
// ClipRegion setzen/updaten
- long nX;
- long nY;
- long nWidth;
- long nHeight;
- sal_uLong nRectCount;
- ImplRegionInfo aInfo;
- sal_Bool bRegionRect;
-
- nRectCount = aRegion.GetRectCount();
- mpWindowImpl->mpSysObj->BeginSetClipRegion( nRectCount );
- bRegionRect = aRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
- while ( bRegionRect )
+ RectangleVector aRectangles;
+ aRegion.GetRegionRectangles(aRectangles);
+ mpWindowImpl->mpSysObj->BeginSetClipRegion(aRectangles.size());
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- mpWindowImpl->mpSysObj->UnionClipRegion( nX, nY, nWidth, nHeight );
- bRegionRect = aRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ mpWindowImpl->mpSysObj->UnionClipRegion(
+ aRectIter->Left(),
+ aRectIter->Top(),
+ aRectIter->GetWidth(), // orig nWidth was ((R - L) + 1), same as GetWidth does
+ aRectIter->GetHeight()); // same for height
}
+
mpWindowImpl->mpSysObj->EndSetClipRegion();
+
+ //long nX;
+ //long nY;
+ //long nWidth;
+ //long nHeight;
+ //sal_uLong nRectCount;
+ //ImplRegionInfo aInfo;
+ //sal_Bool bRegionRect;
+ //
+ //nRectCount = aRegion.GetRectCount();
+ //mpWindowImpl->mpSysObj->BeginSetClipRegion( nRectCount );
+ //bRegionRect = aRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ //while ( bRegionRect )
+ //{
+ // mpWindowImpl->mpSysObj->UnionClipRegion( nX, nY, nWidth, nHeight );
+ // bRegionRect = aRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ //}
+ //mpWindowImpl->mpSysObj->EndSetClipRegion();
}
}
else
@@ -2371,6 +2385,9 @@ void Window::ImplCalcOverlapRegion( const Rectangle& rSourceRect, Region& rRegio
void Window::ImplCallPaint( const Region* pRegion, sal_uInt16 nPaintFlags )
{
+ Exception aException;
+ bool bExceptionCaught(false);
+
// call PrePaint. PrePaint may add to the invalidate region as well as
// other parameters used below.
PrePaint();
@@ -2464,7 +2481,19 @@ void Window::ImplCallPaint( const Region* pRegion, sal_uInt16 nPaintFlags )
if( mpWindowImpl->mbDrawSelectionBackground )
aSelectionRect = aPaintRect;
- Paint( aPaintRect );
+ // Paint can throw exceptions; to not have a situation where
+ // mpWindowImpl->mbInPaint keeps to be on true (and other
+ // settings, too) better catch here to avoid to go completely out of
+ // this method without executing the after-paint stuff
+ try
+ {
+ Paint( aPaintRect );
+ }
+ catch(Exception& rException)
+ {
+ aException = rException;
+ bExceptionCaught = true;
+ }
if ( mpWindowImpl->mpWinData )
{
@@ -2504,6 +2533,11 @@ void Window::ImplCallPaint( const Region* pRegion, sal_uInt16 nPaintFlags )
DrawSelectionBackground( aSelectionRect, 3, sal_False, sal_True, sal_False );
delete pChildRegion;
+
+ if(bExceptionCaught)
+ {
+ throw(aException);
+ }
}
// -----------------------------------------------------------------------
@@ -5865,7 +5899,7 @@ void Window::SetWindowRegionPixel()
mpWindowImpl->mpBorderWindow->SetWindowRegionPixel();
else if( mpWindowImpl->mbFrame )
{
- mpWindowImpl->maWinRegion = Region( REGION_NULL);
+ mpWindowImpl->maWinRegion = Region(true);
mpWindowImpl->mbWinRegion = sal_False;
mpWindowImpl->mpFrame->ResetClipRegion();
}
@@ -5873,7 +5907,7 @@ void Window::SetWindowRegionPixel()
{
if ( mpWindowImpl->mbWinRegion )
{
- mpWindowImpl->maWinRegion = Region( REGION_NULL );
+ mpWindowImpl->maWinRegion = Region(true);
mpWindowImpl->mbWinRegion = sal_False;
ImplSetClipFlag();
@@ -5902,30 +5936,46 @@ void Window::SetWindowRegionPixel( const Region& rRegion )
mpWindowImpl->mpBorderWindow->SetWindowRegionPixel( rRegion );
else if( mpWindowImpl->mbFrame )
{
- if( rRegion.GetType() != REGION_NULL )
+ if( !rRegion.IsNull() )
{
mpWindowImpl->maWinRegion = rRegion;
mpWindowImpl->mbWinRegion = ! rRegion.IsEmpty();
+
if( mpWindowImpl->mbWinRegion )
{
// set/update ClipRegion
- long nX;
- long nY;
- long nWidth;
- long nHeight;
- sal_uLong nRectCount;
- ImplRegionInfo aInfo;
- sal_Bool bRegionRect;
-
- nRectCount = mpWindowImpl->maWinRegion.GetRectCount();
- mpWindowImpl->mpFrame->BeginSetClipRegion( nRectCount );
- bRegionRect = mpWindowImpl->maWinRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
- while ( bRegionRect )
+ RectangleVector aRectangles;
+ mpWindowImpl->maWinRegion.GetRegionRectangles(aRectangles);
+ mpWindowImpl->mpFrame->BeginSetClipRegion(aRectangles.size());
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- mpWindowImpl->mpFrame->UnionClipRegion( nX, nY, nWidth, nHeight );
- bRegionRect = mpWindowImpl->maWinRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ mpWindowImpl->mpFrame->UnionClipRegion(
+ aRectIter->Left(),
+ aRectIter->Top(),
+ aRectIter->GetWidth(), // orig nWidth was ((R - L) + 1), same as GetWidth does
+ aRectIter->GetHeight()); // same for height
}
+
mpWindowImpl->mpFrame->EndSetClipRegion();
+
+ //long nX;
+ //long nY;
+ //long nWidth;
+ //long nHeight;
+ //sal_uLong nRectCount;
+ //ImplRegionInfo aInfo;
+ //sal_Bool bRegionRect;
+ //
+ //nRectCount = mpWindowImpl->maWinRegion.GetRectCount();
+ //mpWindowImpl->mpFrame->BeginSetClipRegion( nRectCount );
+ //bRegionRect = mpWindowImpl->maWinRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ //while ( bRegionRect )
+ //{
+ // mpWindowImpl->mpFrame->UnionClipRegion( nX, nY, nWidth, nHeight );
+ // bRegionRect = mpWindowImpl->maWinRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ //}
+ //mpWindowImpl->mpFrame->EndSetClipRegion();
}
else
SetWindowRegionPixel();
@@ -5935,11 +5985,11 @@ void Window::SetWindowRegionPixel( const Region& rRegion )
}
else
{
- if ( rRegion.GetType() == REGION_NULL )
+ if ( rRegion.IsNull() )
{
if ( mpWindowImpl->mbWinRegion )
{
- mpWindowImpl->maWinRegion = Region( REGION_NULL );
+ mpWindowImpl->maWinRegion = Region(true);
mpWindowImpl->mbWinRegion = sal_False;
ImplSetClipFlag();
}
@@ -6040,7 +6090,7 @@ Region Window::GetPaintRegion() const
}
else
{
- Region aPaintRegion( REGION_NULL );
+ Region aPaintRegion(true);
return aPaintRegion;
}
}
@@ -6290,7 +6340,7 @@ void Window::Show( sal_Bool bVisible, sal_uInt16 nFlags )
if ( mpWindowImpl->mbReallyVisible )
{
- Region aInvRegion( REGION_EMPTY );
+ Region aInvRegion;
sal_Bool bSaveBack = sal_False;
if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 2098457b9e1e..18ca15ece773 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -52,7 +52,6 @@
#include "generic/printergfx.hxx"
#include "xrender_peer.hxx"
-#include "region.h"
#define STATIC_POINTS 64
@@ -559,24 +558,48 @@ bool X11SalGraphics::setClipRegion( const Region& i_rClip )
XDestroyRegion( mpClipRegion );
mpClipRegion = XCreateRegion();
- ImplRegionInfo aInfo;
- long nX, nY, nW, nH;
- bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
- while( bRegionRect )
+ RectangleVector aRectangles;
+ i_rClip.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- if ( nW && nH )
+ const long nW(aRectIter->GetWidth());
+
+ if(nW)
{
- XRectangle aRect;
- aRect.x = (short)nX;
- aRect.y = (short)nY;
- aRect.width = (unsigned short)nW;
- aRect.height = (unsigned short)nH;
+ const long nH(aRectIter->GetHeight());
+
+ if(nH)
+ {
+ XRectangle aRect;
- XUnionRectWithRegion( &aRect, mpClipRegion, mpClipRegion );
+ aRect.x = (short)aRectIter->Left();
+ aRect.y = (short)aRectIter->Top();
+ aRect.width = (unsigned short)nW;
+ aRect.height = (unsigned short)nH;
+ XUnionRectWithRegion(&aRect, mpClipRegion, mpClipRegion);
+ }
}
- bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
}
+ //ImplRegionInfo aInfo;
+ //long nX, nY, nW, nH;
+ //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
+ //while( bRegionRect )
+ //{
+ // if ( nW && nH )
+ // {
+ // XRectangle aRect;
+ // aRect.x = (short)nX;
+ // aRect.y = (short)nY;
+ // aRect.width = (unsigned short)nW;
+ // aRect.height = (unsigned short)nH;
+ //
+ // XUnionRectWithRegion( &aRect, mpClipRegion, mpClipRegion );
+ // }
+ // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
+ //}
+
// done, invalidate GCs
bPenGC_ = sal_False;
bFontGC_ = sal_False;
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index 0a0fe89fabad..8518ab32dcb5 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -49,7 +49,7 @@ sal_Bool GtkSalGraphics::bNeedPixmapPaint = sal_False;
GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
: X11SalGraphics(),
m_pWindow( pWindow ),
- m_aClipRegion( REGION_NULL )
+ m_aClipRegion(true)
{
Init( pFrame, GDK_WINDOW_XID( widget_get_window( pWindow ) ),
SalX11Screen( gdk_x11_screen_get_screen_number(
@@ -828,16 +828,29 @@ sal_Bool GtkSalGraphics::drawNativeControl( ControlType nType,
}
else
{
- RegionHandle aHdl = aClipRegion.BeginEnumRects();
- Rectangle aPaintRect;
- while( aClipRegion.GetNextEnumRect( aHdl, aPaintRect ) )
+ RectangleVector aRectangles;
+ aClipRegion.GetRegionRectangles(aRectangles);
+
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- aPaintRect = aCtrlRect.GetIntersection( aPaintRect );
- if( aPaintRect.IsEmpty() )
+ if(aRectIter->IsEmpty())
+ {
continue;
- aClip.push_back( aPaintRect );
+ }
+
+ aClip.push_back(*aRectIter);
}
- aClipRegion.EndEnumRects( aHdl );
+
+ //RegionHandle aHdl = aClipRegion.BeginEnumRects();
+ //Rectangle aPaintRect;
+ //while( aClipRegion.GetEnumRects( aHdl, aPaintRect ) )
+ //{
+ // aPaintRect = aCtrlRect.GetIntersection( aPaintRect );
+ // if( aPaintRect.IsEmpty() )
+ // continue;
+ // aClip.push_back( aPaintRect );
+ //}
+ //aClipRegion.EndEnumRects( aHdl );
}
if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) )
diff --git a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx
index 8b9f2d20737e..cc33f0130bed 100644
--- a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx
@@ -1450,7 +1450,8 @@ void GtkSalGraphics::getStyleContext(GtkStyleContext** style, GtkWidget* widget)
GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
: SvpSalGraphics(),
mpFrame( pFrame ),
- mpWindow( pWindow )
+ mpWindow( pWindow ),
+ m_aClipRegion(true)
{
if(style_loaded)
return;
diff --git a/vcl/win/source/gdi/salgdi.cxx b/vcl/win/source/gdi/salgdi.cxx
index 7bba68e43354..59fde95c7054 100644
--- a/vcl/win/source/gdi/salgdi.cxx
+++ b/vcl/win/source/gdi/salgdi.cxx
@@ -35,8 +35,6 @@
#include <win/salgdi.h>
#include <win/salframe.h>
-#include <region.h>
-
// =======================================================================
// comment out to prevent use of beziers on GDI functions
@@ -848,10 +846,9 @@ bool WinSalGraphics::setClipRegion( const Region& i_rClip )
mhRegion = 0;
}
- if( i_rClip.HasPolyPolygon() )
+ if( i_rClip.HasPolyPolygonOrB2DPolyPolygon() )
{
- // TODO: ConvertToB2DPolyPolygon actually is kind of const, just it does not advertise it in the header
- basegfx::B2DPolyPolygon aPolyPolygon( const_cast<Region&>(i_rClip).ConvertToB2DPolyPolygon() );
+ const basegfx::B2DPolyPolygon aPolyPolygon( i_rClip.GetAsB2DPolyPolygon() );
const sal_uInt32 nCount(aPolyPolygon.count());
if( nCount )
@@ -859,12 +856,15 @@ bool WinSalGraphics::setClipRegion( const Region& i_rClip )
std::vector< POINT > aPolyPoints;
aPolyPoints.reserve( 1024 );
std::vector< INT > aPolyCounts( nCount, 0 );
+
for(sal_uInt32 a(0); a < nCount; a++)
{
- basegfx::B2DPolygon aPoly( aPolyPolygon.getB2DPolygon(a) );
+ basegfx::B2DPolygon aPoly(aPolyPolygon.getB2DPolygon(a));
+
aPoly = basegfx::tools::adaptiveSubdivideByDistance( aPoly, 1 );
const sal_uInt32 nPoints = aPoly.count();
aPolyCounts[a] = nPoints;
+
for( sal_uInt32 b = 0; b < nPoints; b++ )
{
basegfx::B2DPoint aPt( aPoly.getB2DPoint( b ) );
@@ -874,15 +874,18 @@ bool WinSalGraphics::setClipRegion( const Region& i_rClip )
aPolyPoints.push_back( aPOINT );
}
}
+
mhRegion = CreatePolyPolygonRgn( &aPolyPoints[0], &aPolyCounts[0], nCount, ALTERNATE );
}
}
else
{
- sal_uLong nRectCount = i_rClip.GetRectCount();
+ RectangleVector aRectangles;
+ i_rClip.GetRegionRectangles(aRectangles);
- sal_uLong nRectBufSize = sizeof(RECT)*nRectCount;
- if ( nRectCount < SAL_CLIPRECT_COUNT )
+ //sal_uLong nRectCount = i_rClip.GetRectCount();
+ sal_uLong nRectBufSize = sizeof(RECT)*aRectangles.size();
+ if ( aRectangles.size() < SAL_CLIPRECT_COUNT )
{
if ( !mpStdClipRgnData )
mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))];
@@ -892,50 +895,58 @@ bool WinSalGraphics::setClipRegion( const Region& i_rClip )
mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER );
mpClipRgnData->rdh.iType = RDH_RECTANGLES;
- mpClipRgnData->rdh.nCount = nRectCount;
+ mpClipRgnData->rdh.nCount = aRectangles.size();
mpClipRgnData->rdh.nRgnSize = nRectBufSize;
RECT* pBoundRect = &(mpClipRgnData->rdh.rcBound);
SetRectEmpty( pBoundRect );
RECT* pNextClipRect = (RECT*)(&(mpClipRgnData->Buffer));
bool bFirstClipRect = true;
- ImplRegionInfo aInfo;
- long nX, nY, nW, nH;
- bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
- while( bRegionRect )
+ for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
{
- if ( nW && nH )
+ const long nW(aRectIter->GetWidth());
+ const long nH(aRectIter->GetHeight());
+
+ if(nW && nH)
{
- long nRight = nX + nW;
- long nBottom = nY + nH;
+ const long nRight(aRectIter->Left() + nW);
+ const long nBottom(aRectIter->Top() + nH);
- if ( bFirstClipRect )
+ if(bFirstClipRect)
{
- pBoundRect->left = nX;
- pBoundRect->top = nY;
- pBoundRect->right = nRight;
- pBoundRect->bottom = nBottom;
+ pBoundRect->left = aRectIter->Left();
+ pBoundRect->top = aRectIter->Top();
+ pBoundRect->right = nRight;
+ pBoundRect->bottom = nBottom;
bFirstClipRect = false;
}
else
{
- if ( nX < pBoundRect->left )
- pBoundRect->left = (int)nX;
+ if(aRectIter->Left() < pBoundRect->left)
+ {
+ pBoundRect->left = (int)aRectIter->Left();
+ }
- if ( nY < pBoundRect->top )
- pBoundRect->top = (int)nY;
+ if(aRectIter->Top() < pBoundRect->top)
+ {
+ pBoundRect->top = (int)aRectIter->Top();
+ }
- if ( nRight > pBoundRect->right )
+ if(nRight > pBoundRect->right)
+ {
pBoundRect->right = (int)nRight;
+ }
- if ( nBottom > pBoundRect->bottom )
+ if(nBottom > pBoundRect->bottom)
+ {
pBoundRect->bottom = (int)nBottom;
+ }
}
- pNextClipRect->left = (int)nX;
- pNextClipRect->top = (int)nY;
- pNextClipRect->right = (int)nRight;
- pNextClipRect->bottom = (int)nBottom;
+ pNextClipRect->left = (int)aRectIter->Left();
+ pNextClipRect->top = (int)aRectIter->Top();
+ pNextClipRect->right = (int)nRight;
+ pNextClipRect->bottom = (int)nBottom;
pNextClipRect++;
}
else
@@ -943,8 +954,55 @@ bool WinSalGraphics::setClipRegion( const Region& i_rClip )
mpClipRgnData->rdh.nCount--;
mpClipRgnData->rdh.nRgnSize -= sizeof( RECT );
}
- bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
}
+
+ //ImplRegionInfo aInfo;
+ //long nX, nY, nW, nH;
+ //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
+ //while( bRegionRect )
+ //{
+ // if ( nW && nH )
+ // {
+ // long nRight = nX + nW;
+ // long nBottom = nY + nH;
+ //
+ // if ( bFirstClipRect )
+ // {
+ // pBoundRect->left = nX;
+ // pBoundRect->top = nY;
+ // pBoundRect->right = nRight;
+ // pBoundRect->bottom = nBottom;
+ // bFirstClipRect = false;
+ // }
+ // else
+ // {
+ // if ( nX < pBoundRect->left )
+ // pBoundRect->left = (int)nX;
+ //
+ // if ( nY < pBoundRect->top )
+ // pBoundRect->top = (int)nY;
+ //
+ // if ( nRight > pBoundRect->right )
+ // pBoundRect->right = (int)nRight;
+ //
+ // if ( nBottom > pBoundRect->bottom )
+ // pBoundRect->bottom = (int)nBottom;
+ // }
+ //
+ // pNextClipRect->left = (int)nX;
+ // pNextClipRect->top = (int)nY;
+ // pNextClipRect->right = (int)nRight;
+ // pNextClipRect->bottom = (int)nBottom;
+ // pNextClipRect++;
+ // }
+ // else
+ // {
+ // mpClipRgnData->rdh.nCount--;
+ // mpClipRgnData->rdh.nRgnSize -= sizeof( RECT );
+ // }
+ // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
+ //}
+
// create clip region from ClipRgnData
if ( mpClipRgnData->rdh.nCount == 1 )
{