[ooo-build-commit] patches/test
Thorsten Behrens
thorsten at kemper.freedesktop.org
Wed Sep 30 13:29:38 PDT 2009
patches/test/clipstate.diff | 805 +++++++++++++++++++++++++++++++++--------
patches/test/wmf-clipperf.diff | 439 ++++++++++++++++++++++
2 files changed, 1105 insertions(+), 139 deletions(-)
New commits:
commit 49fb422bcf33f80c89a7b800009e17dcd4941aec
Author: Thorsten Behrens <tbehrens at novell.com>
Date: Wed Sep 30 22:23:00 2009 +0200
Updated B2DClipState; made us of it in wmf import
* patches/test/clipstate.diff:
* patches/test/wmf-clipperf.diff:
diff --git a/patches/test/clipstate.diff b/patches/test/clipstate.diff
index e1dd123..08c2ad9 100644
--- a/patches/test/clipstate.diff
+++ b/patches/test/clipstate.diff
@@ -5,29 +5,50 @@ From: Thorsten Behrens <thb at openoffice.org>
---
- basegfx/inc/basegfx/tools/b2dclipstate.hxx | 111 +++++++
- basegfx/prj/d.lst | 2
+ basegfx/inc/basegfx/range/b2dpolyrange.hxx | 6
+ basegfx/inc/basegfx/tools/b2dclipstate.hxx | 119 +++++
+ basegfx/prj/d.lst | 3
basegfx/qa/mkpolygons.pl | 0
- basegfx/source/tools/b2dclipstate.cxx | 431 ++++++++++++++++++++++++++++
+ basegfx/source/range/b2dpolyrange.cxx | 40 ++
+ basegfx/source/tools/b2dclipstate.cxx | 662 ++++++++++++++++++++++++++++
basegfx/source/tools/makefile.mk | 3
basegfx/test/basegfx2d.cxx | 6
- basegfx/test/genericclipper.cxx | 168 +++++++++++
- basegfx/test/makefile.mk | 1
- slideshow/source/engine/slide/layer.cxx | 11 -
+ basegfx/test/clipstate.cxx | 187 ++++++++
+ basegfx/test/genericclipper.cxx | 168 +++++++
+ basegfx/test/makefile.mk | 8
+ slideshow/source/engine/slide/layer.cxx | 11
slideshow/source/engine/slide/layer.hxx | 6
- 10 files changed, 729 insertions(+), 10 deletions(-)
+ 13 files changed, 1206 insertions(+), 13 deletions(-)
create mode 100644 basegfx/inc/basegfx/tools/b2dclipstate.hxx
mode change 100644 => 100755 basegfx/qa/mkpolygons.pl
create mode 100644 basegfx/source/tools/b2dclipstate.cxx
+ create mode 100644 basegfx/test/clipstate.cxx
create mode 100644 basegfx/test/genericclipper.cxx
+diff --git basegfx/inc/basegfx/range/b2dpolyrange.hxx basegfx/inc/basegfx/range/b2dpolyrange.hxx
+index 0c07dc2..ad53552 100644
+--- basegfx/inc/basegfx/range/b2dpolyrange.hxx
++++ basegfx/inc/basegfx/range/b2dpolyrange.hxx
+@@ -131,6 +131,12 @@ namespace basegfx
+ */
+ B2DPolyPolygon solveCrossovers() const;
+
++ // element iterators
++ const B2DRange* begin() const;
++ const B2DRange* end() const;
++ B2DRange* begin();
++ B2DRange* end();
++
+ private:
+ o3tl::cow_wrapper< ImplB2DPolyRange > mpImpl;
+ };
diff --git basegfx/inc/basegfx/tools/b2dclipstate.hxx basegfx/inc/basegfx/tools/b2dclipstate.hxx
new file mode 100644
-index 0000000..4ea041b
+index 0000000..92b1578
--- /dev/null
+++ basegfx/inc/basegfx/tools/b2dclipstate.hxx
-@@ -0,0 +1,111 @@
+@@ -0,0 +1,119 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -96,6 +117,7 @@ index 0000000..4ea041b
+ ImplType mpImpl;
+
+ public:
++ /// Init clip, in 'cleared' state - everything is visible
+ B2DClipState();
+ ~B2DClipState();
+ B2DClipState( const B2DClipState& );
@@ -107,7 +129,15 @@ index 0000000..4ea041b
+ /// unshare this poly-range with all internally shared instances
+ void makeUnique();
+
-+ void clear();
++ /// Set clip to 'null' - nothing is visible
++ void makeNull();
++ /// returns true when clip is 'null' - nothing is visible
++ bool isNull() const;
++
++ /// Set clip 'cleared' - everything is visible
++ void makeClear();
++ /// returns true when clip is 'cleared' - everything is visible
++ bool isCleared() const;
+
+ bool operator==(const B2DClipState&) const;
+ bool operator!=(const B2DClipState&) const;
@@ -133,14 +163,13 @@ index 0000000..4ea041b
+ void xorClipState(const B2DClipState& );
+
+ B2DPolyPolygon getClipPoly() const;
-+ B2DPolyRange getClipRanges() const;
+ };
+ }
+}
+
+#endif // _BGFX_TOOLS_CLIPSTATE_HXX
diff --git basegfx/prj/d.lst basegfx/prj/d.lst
-index 9dd6085..b9d3a10 100644
+index 9dd6085..9c54511 100644
--- basegfx/prj/d.lst
+++ basegfx/prj/d.lst
@@ -27,7 +27,7 @@ mkdir: %_DEST%\inc%_EXT%\basegfx\range
@@ -152,15 +181,81 @@ index 9dd6085..b9d3a10 100644
..\inc\basegfx\range\b2drange.hxx %_DEST%\inc%_EXT%\basegfx\range\b2drange.hxx
..\inc\basegfx\range\b2drectangle.hxx %_DEST%\inc%_EXT%\basegfx\range\b2drectangle.hxx
..\inc\basegfx\range\b2dconnectedranges.hxx %_DEST%\inc%_EXT%\basegfx\range\b2dconnectedranges.hxx
+@@ -90,6 +90,7 @@ mkdir: %_DEST%\inc%_EXT%\basegfx\tuple
+ mkdir: %_DEST%\inc%_EXT%\basegfx\tools
+ ..\inc\basegfx\tools\canvastools.hxx %_DEST%\inc%_EXT%\basegfx\tools\canvastools.hxx
+ ..\inc\basegfx\tools\unopolypolygon.hxx %_DEST%\inc%_EXT%\basegfx\tools\unopolypolygon.hxx
++..\inc\basegfx\tools\b2dclipstate.hxx %_DEST%\inc%_EXT%\basegfx\tools\b2dclipstate.hxx
+ ..\inc\basegfx\tools\rectcliptools.hxx %_DEST%\inc%_EXT%\basegfx\tools\rectcliptools.hxx
+ ..\inc\basegfx\tools\tools.hxx %_DEST%\inc%_EXT%\basegfx\tools\tools.hxx
+ ..\inc\basegfx\tools\gradienttools.hxx %_DEST%\inc%_EXT%\basegfx\tools\gradienttools.hxx
diff --git basegfx/qa/mkpolygons.pl basegfx/qa/mkpolygons.pl
old mode 100644
new mode 100755
+diff --git basegfx/source/range/b2dpolyrange.cxx basegfx/source/range/b2dpolyrange.cxx
+index ae94f14..a69cd5b 100644
+--- basegfx/source/range/b2dpolyrange.cxx
++++ basegfx/source/range/b2dpolyrange.cxx
+@@ -227,6 +227,26 @@ namespace basegfx
+ return tools::solveCrossovers(maRanges,maOrient);
+ }
+
++ const B2DRange* begin() const
++ {
++ return &maRanges.front();
++ }
++
++ const B2DRange* end() const
++ {
++ return &maRanges[maRanges.size()];
++ }
++
++ B2DRange* begin()
++ {
++ return &maRanges.front();
++ }
++
++ B2DRange* end()
++ {
++ return &maRanges[maRanges.size()];
++ }
++
+ private:
+ B2DRange maBounds;
+ std::vector<B2DRange> maRanges;
+@@ -366,6 +386,26 @@ namespace basegfx
+ return mpImpl->solveCrossovers();
+ }
+
++ const B2DRange* B2DPolyRange::begin() const
++ {
++ return mpImpl->begin();
++ }
++
++ const B2DRange* B2DPolyRange::end() const
++ {
++ return mpImpl->end();
++ }
++
++ B2DRange* B2DPolyRange::begin()
++ {
++ return mpImpl->begin();
++ }
++
++ B2DRange* B2DPolyRange::end()
++ {
++ return mpImpl->end();
++ }
++
+ } // end of namespace basegfx
+
+ // eof
diff --git basegfx/source/tools/b2dclipstate.cxx basegfx/source/tools/b2dclipstate.cxx
new file mode 100644
-index 0000000..76e2aaf
+index 0000000..f203d4f
--- /dev/null
+++ basegfx/source/tools/b2dclipstate.cxx
-@@ -0,0 +1,431 @@
+@@ -0,0 +1,662 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -197,6 +292,7 @@ index 0000000..76e2aaf
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2dpolyrange.hxx>
++#include <basegfx/range/b2drangeclipper.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
@@ -210,238 +306,458 @@ index 0000000..76e2aaf
+ struct ImplB2DClipState
+ {
+ public:
-+ enum Operation {UNION, INTERSECT, XOR};
++ enum Operation {UNION, INTERSECT, XOR, SUBTRACT};
+
+ ImplB2DClipState() :
-+ maPending(),
++ maPendingPolygons(),
++ maPendingRanges(),
+ maClipPoly(),
+ mePendingOps(UNION)
+ {}
+
+ explicit ImplB2DClipState( const B2DRange& rRange ) :
-+ maPending(),
++ maPendingPolygons(),
++ maPendingRanges(),
+ maClipPoly(
+ tools::createPolygonFromRect(rRange)),
+ mePendingOps(UNION)
+ {}
+
+ explicit ImplB2DClipState( const B2DPolygon& rPoly ) :
-+ maPending(),
++ maPendingPolygons(),
++ maPendingRanges(),
+ maClipPoly(rPoly),
+ mePendingOps(UNION)
+ {}
+
+ explicit ImplB2DClipState( const B2DPolyPolygon& rPoly ) :
-+ maPending(),
++ maPendingPolygons(),
++ maPendingRanges(),
+ maClipPoly(rPoly),
+ mePendingOps(UNION)
+ {}
+
-+ void clear()
++ bool isCleared() const
++ {
++ return !maClipPoly.count()
++ && !maPendingPolygons.count()
++ && !maPendingRanges.count();
++ }
++
++ void makeClear()
++ {
++ maPendingPolygons.clear();
++ maPendingRanges.clear();
++ maClipPoly.clear();
++ mePendingOps = UNION;
++ }
++
++ bool isNullClipPoly() const
++ {
++ return maClipPoly.count() == 1
++ && !maClipPoly.getB2DPolygon(0).count();
++ }
++
++ bool isNull() const
++ {
++ return !maPendingPolygons.count()
++ && !maPendingRanges.count()
++ && isNullClipPoly();
++ }
++
++ void makeNull()
+ {
-+ maPending.clear();
++ maPendingPolygons.clear();
++ maPendingRanges.clear();
+ maClipPoly.clear();
++ maClipPoly.append(B2DPolygon());
+ mePendingOps = UNION;
+ }
+
+ bool operator==(const ImplB2DClipState& rRHS) const
+ {
-+ return maPending == rRHS.maPending
++ return maPendingPolygons == rRHS.maPendingPolygons
++ && maPendingRanges == rRHS.maPendingRanges
+ && maClipPoly == rRHS.maClipPoly
+ && mePendingOps == rRHS.mePendingOps;
+ }
+
-+ void unionRange(const B2DRange& rRange)
++ void addRange(const B2DRange& rRange, Operation eOp)
+ {
+ if( rRange.isEmpty() )
+ return;
+
-+ if( maPending.count() && mePendingOps != UNION )
-+ commitToPolygon();
++ commitPendingPolygons();
++ if( mePendingOps != eOp )
++ commitPendingRanges();
+
-+ mePendingOps = UNION;
-+ maPending.append(
-+ tools::createPolygonFromRect(rRange));
++ mePendingOps = eOp;
++ maPendingRanges.appendElement(
++ rRange,
++ ORIENTATION_POSITIVE);
++ }
++
++ void addPolygon(B2DPolygon aPoly, Operation eOp)
++ {
++ commitPendingRanges();
++ if( mePendingOps != eOp )
++ commitPendingPolygons();
++
++ mePendingOps = eOp;
++ maPendingPolygons.append(aPoly);
++ }
++
++ void addPolyPolygon(B2DPolyPolygon aPoly, Operation eOp)
++ {
++ commitPendingRanges();
++ if( mePendingOps != eOp )
++ commitPendingPolygons();
++
++ mePendingOps = eOp;
++ maPendingPolygons.append(aPoly);
++ }
++
++ void addClipState(const ImplB2DClipState& rOther, Operation eOp)
++ {
++ if( rOther.mePendingOps == mePendingOps
++ && !rOther.maClipPoly.count()
++ && !rOther.maPendingPolygons.count() )
++ {
++ maPendingRanges.appendPolyRange( rOther.maPendingRanges );
++ }
++ else
++ {
++ commitPendingRanges();
++ commitPendingPolygons();
++ rOther.commitPendingRanges();
++ rOther.commitPendingPolygons();
++
++ maPendingPolygons = rOther.maClipPoly;
++ mePendingOps = eOp;
++ }
++ }
++
++ void unionRange(const B2DRange& rRange)
++ {
++ if( isCleared() )
++ return;
++
++ addRange(rRange,UNION);
+ }
+
+ void unionPolygon(const B2DPolygon& rPoly)
+ {
-+ if( maPending.count() && mePendingOps != UNION )
-+ commitToPolygon();
++ if( isCleared() )
++ return;
+
-+ mePendingOps = UNION;
-+ maPending.append(
-+ tools::prepareForPolygonOperation(rPoly));
++ addPolygon(rPoly,UNION);
+ }
+
+ void unionPolyPolygon(const B2DPolyPolygon& rPolyPoly)
+ {
-+ if( maPending.count() && mePendingOps != UNION )
-+ commitToPolygon();
++ if( isCleared() )
++ return;
+
-+ mePendingOps = UNION;
-+ maPending.append(
-+ tools::prepareForPolygonOperation(rPolyPoly));
++ addPolyPolygon(rPolyPoly,UNION);
+ }
+
-+ void unionClipState(const B2DClipState&)
-+ {}
++ void unionClipState(const ImplB2DClipState& rOther)
++ {
++ if( isCleared() )
++ return;
++
++ addClipState(rOther, UNION);
++ }
+
+ void intersectRange(const B2DRange& rRange)
+ {
-+ if( rRange.isEmpty() )
++ if( isNull() )
+ return;
+
-+ if( maPending.count() && mePendingOps != INTERSECT )
-+ commitToPolygon();
-+
-+ mePendingOps = INTERSECT;
-+ maPending.append(
-+ tools::createPolygonFromRect(rRange));
++ addRange(rRange,INTERSECT);
+ }
+
+ void intersectPolygon(const B2DPolygon& rPoly)
+ {
-+ if( maPending.count() && mePendingOps != INTERSECT )
-+ commitToPolygon();
++ if( isNull() )
++ return;
+
-+ mePendingOps = INTERSECT;
-+ maPending.append(rPoly);
++ addPolygon(rPoly,INTERSECT);
+ }
+
+ void intersectPolyPolygon(const B2DPolyPolygon& rPolyPoly)
+ {
-+ if( maPending.count() && mePendingOps != INTERSECT )
-+ commitToPolygon();
++ if( isNull() )
++ return;
+
-+ mePendingOps = INTERSECT;
-+ maPending.append(rPolyPoly);
++ addPolyPolygon(rPolyPoly,INTERSECT);
+ }
+
-+ void intersectClipState(const tools::B2DClipState& )
-+ {}
++ void intersectClipState(const ImplB2DClipState& rOther)
++ {
++ if( isNull() )
++ return;
++
++ addClipState(rOther, INTERSECT);
++ }
+
+ void subtractRange(const B2DRange& rRange )
+ {
-+ if( rRange.isEmpty() )
++ if( isNull() )
+ return;
+
-+ // how unfortunate. subtract is not associative, cannot
-+ // lump together
-+ commitToPolygon();
-+
-+ maClipPoly = tools::solvePolygonOperationDiff(
-+ maClipPoly,
-+ B2DPolyPolygon(
-+ tools::createPolygonFromRect(rRange)));
++ addRange(rRange,SUBTRACT);
+ }
+
+ void subtractPolygon(const B2DPolygon& rPoly)
+ {
-+ // how unfortunate. subtract is not associative, cannot
-+ // lump together
-+ commitToPolygon();
++ if( isNull() )
++ return;
+
-+ maClipPoly = tools::solvePolygonOperationDiff(
-+ maClipPoly,
-+ prepareForPolygonOperation(rPoly));
++ addPolygon(rPoly,SUBTRACT);
+ }
+
-+ void subtractPolyPolygon(const B2DPolyPolygon& rPoly)
++ void subtractPolyPolygon(const B2DPolyPolygon& rPolyPoly)
+ {
-+ // how unfortunate. subtract is not associative, cannot
-+ // lump together
-+ commitToPolygon();
++ if( isNull() )
++ return;
+
-+ maClipPoly = tools::solvePolygonOperationDiff(
-+ maClipPoly,
-+ prepareForPolygonOperation(rPoly));
++ addPolyPolygon(rPolyPoly,SUBTRACT);
+ }
+
-+ void subtractClipState(const B2DClipState& )
-+ {}
-+
-+ void xorRange(const B2DRange& rRange)
++ void subtractClipState(const ImplB2DClipState& rOther)
+ {
-+ if( rRange.isEmpty() )
++ if( isNull() )
+ return;
+
-+ if( maPending.count() && mePendingOps != XOR )
-+ commitToPolygon();
-+
-+ mePendingOps = XOR;
-+ maPending.append(
-+ tools::createPolygonFromRect(rRange));
++ addClipState(rOther, SUBTRACT);
++ }
++
++ void xorRange(const B2DRange& rRange)
++ {
++ addRange(rRange,XOR);
+ }
+
+ void xorPolygon(const B2DPolygon& rPoly)
+ {
-+ if( maPending.count() && mePendingOps != XOR )
-+ commitToPolygon();
-+
-+ mePendingOps = XOR;
-+ maPending.append(rPoly);
++ addPolygon(rPoly,XOR);
+ }
+
+ void xorPolyPolygon(const B2DPolyPolygon& rPolyPoly)
+ {
-+ if( maPending.count() && mePendingOps != XOR )
-+ commitToPolygon();
-+
-+ mePendingOps = XOR;
-+ maPending.append(rPolyPoly);
++ addPolyPolygon(rPolyPoly,XOR);
+ }
+
-+ void xorClipState(const B2DClipState& )
-+ {}
++ void xorClipState(const ImplB2DClipState& rOther)
++ {
++ addClipState(rOther, XOR);
++ }
+
+ B2DPolyPolygon getClipPoly() const
+ {
-+ commitToPolygon();
-+ return maClipPoly;
-+ }
++ commitPendingRanges();
++ commitPendingPolygons();
+
-+ B2DPolyRange getClipRanges() const
-+ {
-+ return B2DPolyRange();
++ return maClipPoly;
+ }
+
+ private:
-+ void commitToPolygon() const
++ void commitPendingPolygons() const
+ {
-+ if( !maPending.count() )
++ if( !maPendingPolygons.count() )
+ return;
+
+ // assumption: maClipPoly has kept polygons prepared for
+ // clipping; i.e. no neutral polygons & correct
+ // orientation
-+ maPending = tools::prepareForPolygonOperation(maPending);
++ maPendingPolygons = tools::prepareForPolygonOperation(maPendingPolygons);
++ const bool bIsEmpty=isNullClipPoly();
++ const bool bIsCleared=!maClipPoly.count();
+ switch(mePendingOps)
+ {
+ case UNION:
-+ maClipPoly = tools::solvePolygonOperationOr(
-+ maClipPoly,
-+ maPending);
++ OSL_ASSERT( !bIsCleared );
++
++ if( bIsEmpty )
++ maClipPoly = maPendingPolygons;
++ else
++ maClipPoly = tools::solvePolygonOperationOr(
++ maClipPoly,
++ maPendingPolygons);
+ break;
+ case INTERSECT:
-+ maClipPoly = tools::solvePolygonOperationAnd(
-+ maClipPoly,
-+ maPending);
++ OSL_ASSERT( !bIsEmpty );
++
++ if( bIsCleared )
++ maClipPoly = maPendingPolygons;
++ else
++ maClipPoly = tools::solvePolygonOperationAnd(
++ maClipPoly,
++ maPendingPolygons);
+ break;
+ case XOR:
-+ maClipPoly = tools::solvePolygonOperationXor(
-+ maClipPoly,
-+ maPending);
++ if( bIsEmpty )
++ maClipPoly = maPendingPolygons;
++ else if( bIsCleared )
++ {
++ // not representable, strictly speaking,
++ // using polygons with the common even/odd
++ // or nonzero winding number fill rule. If
++ // we'd want to represent it, fill rule
++ // would need to be "non-negative winding
++ // number" (and we then would return
++ // 'holes' here)
++
++ // going for an ugly hack meanwhile
++ maClipPoly = tools::solvePolygonOperationXor(
++ B2DPolyPolygon(
++ tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))),
++ maPendingPolygons);
++ }
++ else
++ maClipPoly = tools::solvePolygonOperationXor(
++ maClipPoly,
++ maPendingPolygons);
++ break;
++ case SUBTRACT:
++ OSL_ASSERT( !bIsEmpty );
++
++ // first union all pending ones, subtract en bloc then
++ maPendingPolygons = solveCrossovers(maPendingPolygons);
++ maPendingPolygons = stripNeutralPolygons(maPendingPolygons);
++ maPendingPolygons = stripDispensablePolygons(maPendingPolygons, false);
++
++ if( bIsCleared )
++ {
++ // not representable, strictly speaking,
++ // using polygons with the common even/odd
++ // or nonzero winding number fill rule. If
++ // we'd want to represent it, fill rule
++ // would need to be "non-negative winding
++ // number" (and we then would return
++ // 'holes' here)
++
++ // going for an ugly hack meanwhile
++ maClipPoly = tools::solvePolygonOperationDiff(
++ B2DPolyPolygon(
++ tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))),
++ maPendingPolygons);
++ }
++ else
++ maClipPoly = tools::solvePolygonOperationDiff(
++ maClipPoly,
++ maPendingPolygons);
+ break;
-+ default:
-+ OSL_ASSERT(false);
+ }
+
-+ maPending.clear();
++ maPendingPolygons.clear();
++ mePendingOps = UNION;
++ }
++
++ void commitPendingRanges() const
++ {
++ if( !maPendingRanges.count() )
++ return;
++
++ // use the specialized range clipper for the win
++ B2DPolyPolygon aCollectedRanges;
++ const bool bIsEmpty=isNullClipPoly();
++ const bool bIsCleared=!maClipPoly.count();
++ switch(mePendingOps)
++ {
++ case UNION:
++ OSL_ASSERT( !bIsCleared );
++
++ aCollectedRanges = maPendingRanges.solveCrossovers();
++ aCollectedRanges = stripNeutralPolygons(aCollectedRanges);
++ aCollectedRanges = stripDispensablePolygons(aCollectedRanges, false);
++ if( bIsEmpty )
++ maClipPoly = aCollectedRanges;
++ else
++ maClipPoly = tools::solvePolygonOperationOr(
++ maClipPoly,
++ aCollectedRanges);
++ break;
++ case INTERSECT:
++ OSL_ASSERT( !bIsEmpty );
++
++ aCollectedRanges = maPendingRanges.solveCrossovers();
++ aCollectedRanges = stripNeutralPolygons(aCollectedRanges);
++ if( maPendingRanges.count() > 1 )
++ aCollectedRanges = stripDispensablePolygons(aCollectedRanges, true);
++
++ if( bIsCleared )
++ maClipPoly = aCollectedRanges;
++ else
++ maClipPoly = tools::solvePolygonOperationAnd(
++ maClipPoly,
++ aCollectedRanges);
++ break;
++ case XOR:
++ aCollectedRanges = maPendingRanges.solveCrossovers();
++ aCollectedRanges = stripNeutralPolygons(aCollectedRanges);
++ aCollectedRanges = correctOrientations(aCollectedRanges);
++
++ if( bIsEmpty )
++ maClipPoly = aCollectedRanges;
++ else if( bIsCleared )
++ {
++ // not representable, strictly speaking,
++ // using polygons with the common even/odd
++ // or nonzero winding number fill rule. If
++ // we'd want to represent it, fill rule
++ // would need to be "non-negative winding
++ // number" (and we then would return
++ // 'holes' here)
++
++ // going for an ugly hack meanwhile
++ maClipPoly = tools::solvePolygonOperationXor(
++ B2DPolyPolygon(
++ tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))),
++ aCollectedRanges);
++ }
++ else
++ maClipPoly = tools::solvePolygonOperationXor(
++ maClipPoly,
++ aCollectedRanges);
++ break;
++ case SUBTRACT:
++ OSL_ASSERT( !bIsEmpty );
++
++ // first union all pending ranges, subtract en bloc then
++ aCollectedRanges = maPendingRanges.solveCrossovers();
++ aCollectedRanges = stripNeutralPolygons(aCollectedRanges);
++ aCollectedRanges = stripDispensablePolygons(aCollectedRanges, false);
++
++ if( bIsCleared )
++ {
++ // not representable, strictly speaking,
++ // using polygons with the common even/odd
++ // or nonzero winding number fill rule. If
++ // we'd want to represent it, fill rule
++ // would need to be "non-negative winding
++ // number" (and we then would return
++ // 'holes' here)
++
++ // going for an ugly hack meanwhile
++ maClipPoly = tools::solvePolygonOperationDiff(
++ B2DPolyPolygon(
++ tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))),
++ aCollectedRanges);
++ }
++ else
++ maClipPoly = tools::solvePolygonOperationDiff(
++ maClipPoly,
++ aCollectedRanges);
++ break;
++ }
++
++ maPendingRanges.clear();
+ mePendingOps = UNION;
+ }
+
-+ mutable B2DPolyPolygon maPending;
++ mutable B2DPolyPolygon maPendingPolygons;
++ mutable B2DPolyRange maPendingRanges;
+ mutable B2DPolyPolygon maClipPoly;
+ mutable Operation mePendingOps;
+ };
@@ -480,9 +796,24 @@ index 0000000..76e2aaf
+ mpImpl.make_unique();
+ }
+
-+ void B2DClipState::clear()
++ void B2DClipState::makeNull()
++ {
++ mpImpl->makeNull();
++ }
++
++ bool B2DClipState::isNull() const
++ {
++ return mpImpl->isNull();
++ }
++
++ void B2DClipState::makeClear()
++ {
++ mpImpl->makeClear();
++ }
++
++ bool B2DClipState::isCleared() const
+ {
-+ mpImpl->clear();
++ return mpImpl->isCleared();
+ }
+
+ bool B2DClipState::operator==(const B2DClipState& rRHS) const
@@ -515,7 +846,7 @@ index 0000000..76e2aaf
+
+ void B2DClipState::unionClipState(const B2DClipState& rState)
+ {
-+ mpImpl->unionClipState(rState);
++ mpImpl->unionClipState(*rState.mpImpl);
+ }
+
+ void B2DClipState::intersectRange(const B2DRange& rRange)
@@ -535,7 +866,7 @@ index 0000000..76e2aaf
+
+ void B2DClipState::intersectClipState(const B2DClipState& rState)
+ {
-+ mpImpl->intersectClipState(rState);
++ mpImpl->intersectClipState(*rState.mpImpl);
+ }
+
+ void B2DClipState::subtractRange(const B2DRange& rRange)
@@ -555,7 +886,7 @@ index 0000000..76e2aaf
+
+ void B2DClipState::subtractClipState(const B2DClipState& rState)
+ {
-+ mpImpl->subtractClipState(rState);
++ mpImpl->subtractClipState(*rState.mpImpl);
+ }
+
+ void B2DClipState::xorRange(const B2DRange& rRange)
@@ -575,7 +906,7 @@ index 0000000..76e2aaf
+
+ void B2DClipState::xorClipState(const B2DClipState& rState)
+ {
-+ mpImpl->xorClipState(rState);
++ mpImpl->xorClipState(*rState.mpImpl);
+ }
+
+ B2DPolyPolygon B2DClipState::getClipPoly() const
@@ -583,11 +914,6 @@ index 0000000..76e2aaf
+ return mpImpl->getClipPoly();
+ }
+
-+ B2DPolyRange B2DClipState::getClipRanges() const
-+ {
-+ return mpImpl->getClipRanges();
-+ }
-+
+} // end of namespace tools
+} // end of namespace basegfx
+
@@ -623,6 +949,199 @@ index 8b1d659..ef49c2e 100644
}
// Change the following lines only, if you add, remove or rename
+diff --git basegfx/test/clipstate.cxx basegfx/test/clipstate.cxx
+new file mode 100644
+index 0000000..aeb7cfc
+--- /dev/null
++++ basegfx/test/clipstate.cxx
+@@ -0,0 +1,187 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: basegfx2d.cxx,v $
++ * $Revision: 1.14 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_basegfx.hxx"
++// autogenerated file with codegen.pl
++
++#include <cppunit/simpleheader.hxx>
++
++#include <basegfx/tools/b2dclipstate.hxx>
++#include <basegfx/range/b2dpolyrange.hxx>
++#include <basegfx/polygon/b2dpolygon.hxx>
++#include <basegfx/polygon/b2dpolygontools.hxx>
++#include <basegfx/polygon/b2dpolypolygontools.hxx>
++#include <basegfx/polygon/b2dpolypolygon.hxx>
++#include <basegfx/numeric/ftools.hxx>
++
++#include <boost/bind.hpp>
++
++using namespace ::basegfx;
++
++
++namespace basegfx2d
++{
++
++class clipstate : public CppUnit::TestFixture
++{
++private:
++ tools::B2DClipState aUnion1;
++ tools::B2DClipState aUnion2;
++ tools::B2DClipState aIntersect;
++ tools::B2DClipState aXor;
++ tools::B2DClipState aSubtract;
++
++public:
++ void setUp()
++ {
++ B2DRange aCenter(100, 100, -100, -100);
++ B2DRange aNorth(-10, -110, 10, -90);
++ B2DRange aWest(-110, -10, -90, 10);
++ B2DRange aSouth(-10, 110, 10, 90);
++ B2DRange aEast(110, -10, 90, 10);
++
++ aUnion1.unionRange(aCenter);
++ aUnion1.unionRange(aNorth);
++ aUnion1.unionRange(aWest);
++ aUnion1.unionRange(aSouth);
++ aUnion1.unionRange(aEast);
++
++ aUnion2.makeNull();
++ aUnion2.unionRange(aCenter);
++ aUnion2.unionRange(aNorth);
++ aUnion2.unionRange(aWest);
++ aUnion2.unionRange(aSouth);
++ aUnion2.unionRange(aEast);
++
++ aIntersect.intersectRange(aCenter);
++ aIntersect.intersectRange(aNorth);
++ aIntersect.intersectRange(aWest);
++ aIntersect.intersectRange(aSouth);
++ aIntersect.intersectRange(aEast);
++
++ aXor.makeNull();
++ aXor.xorRange(aCenter);
++ aXor.xorRange(aNorth);
++ aXor.xorRange(aWest);
++ aXor.xorRange(aSouth);
++ aXor.xorRange(aEast);
++
++ aSubtract.intersectRange(aCenter);
++ aSubtract.subtractRange(aNorth);
++ aSubtract.subtractRange(aWest);
++ aSubtract.subtractRange(aSouth);
++ aSubtract.subtractRange(aEast);
++ }
++
++ void tearDown()
++ {}
++
++ void verifyPoly(const char* sName, const char* sSvg, const tools::B2DClipState& toTest)
++ {
++#if defined(VERBOSE)
++ fprintf(stderr, "%s - svg:d=\"%s\"\n",
++ sName, rtl::OUStringToOString(
++ basegfx::tools::exportToSvgD(toTest.getClipPoly()),
++ RTL_TEXTENCODING_UTF8).getStr() );
++#endif
++
++ B2DPolyPolygon aTmp1;
++ CPPUNIT_ASSERT_MESSAGE(sName,
++ tools::importFromSvgD(
++ aTmp1,
++ rtl::OUString::createFromAscii(sSvg)));
++
++ const rtl::OUString aSvg=
++ tools::exportToSvgD(toTest.getClipPoly());
++ B2DPolyPolygon aTmp2;
++ CPPUNIT_ASSERT_MESSAGE(sName,
++ tools::importFromSvgD(
++ aTmp2,
++ aSvg));
++
++ CPPUNIT_ASSERT_MESSAGE(
++ sName,
++ aTmp2 == aTmp1);
++ }
++
++ void verifySimpleRange()
++ {
++ const char* unionSvg="m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
++ const char* intersectSvg="m-100 10v-20h10v20zm80 90v-10h20v10zm-20-190v-10h20v10zm80 100v-20h10v20z";
++ const char* xorSvg="m-100 10h10v-20h-10zm90 110h20v-10h-20zm0-180h20v-10h-20zm100 110h10v-20h-10zm10 20v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
++ const char* subtractSvg="m-90 10v-20h-10v-90h90v10h20v-10h90v90h-10v20h10v90h-90v-10h-20v10h-90v-90z";
++
++ CPPUNIT_ASSERT_MESSAGE("cleared clip stays empty under union operation",
++ aUnion1.isCleared());
++ verifyPoly("union", unionSvg, aUnion2);
++ verifyPoly("intersect", intersectSvg, aIntersect);
++ verifyPoly("xor", xorSvg, aXor);
++ verifyPoly("subtract", subtractSvg, aSubtract);
++ }
++
++ void verifyMixedClips()
++ {
++ tools::B2DClipState aMixedClip;
++
++ const char* unionSvg="m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
++
++ B2DPolyPolygon aTmp1;
++ tools::importFromSvgD(
++ aTmp1,
++ rtl::OUString::createFromAscii(unionSvg));
++
++ aMixedClip.intersectPolyPolygon(aTmp1);
++ aMixedClip.subtractRange(B2DRange(-20,-150,20,0));
++ aMixedClip.subtractRange(B2DRange(-150,-20,0,20));
++ aMixedClip.xorRange(B2DRange(-150,-150,150,150));
++
++ const char* mixedClipSvg="m0 0v20h-100v80h90v10h20v-10h90v-90h10v-20h-10v-90h-80v100zm-40-20v-80h-80v80zm-50 170v-300h300v300z";
++ verifyPoly("mixed clip", mixedClipSvg, aMixedClip);
++ }
++
++ CPPUNIT_TEST_SUITE(clipstate);
++ CPPUNIT_TEST(verifySimpleRange);
++ CPPUNIT_TEST(verifyMixedClips);
++ CPPUNIT_TEST_SUITE_END();
++};
++
++// -----------------------------------------------------------------------------
++CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::clipstate, "clipstate");
++} // namespace basegfx2d
++
++
++// -----------------------------------------------------------------------------
++
++// this macro creates an empty function, which will called by the RegisterAllFunctions()
++// to let the user the possibility to also register some functions by hand.
++// NOADDITIONAL;
++
diff --git basegfx/test/genericclipper.cxx basegfx/test/genericclipper.cxx
new file mode 100644
index 0000000..70455fd
@@ -798,13 +1317,21 @@ index 0000000..70455fd
+// NOADDITIONAL;
+
diff --git basegfx/test/makefile.mk basegfx/test/makefile.mk
-index 320bd0c..4ca75c1 100644
+index 320bd0c..31ea7f8 100644
--- basegfx/test/makefile.mk
+++ basegfx/test/makefile.mk
-@@ -47,6 +47,7 @@ SHL1OBJS= \
- $(SLO)$/basegfx2d.obj \
- $(SLO)$/basegfx3d.obj \
+@@ -43,10 +43,12 @@ ENABLE_EXCEPTIONS=TRUE
+ # --- Common ----------------------------------------------------------
+
+ SHL1OBJS= \
+- $(SLO)$/basegfx1d.obj \
+- $(SLO)$/basegfx2d.obj \
+- $(SLO)$/basegfx3d.obj \
++ $(SLO)$/basegfx1d.obj \
++ $(SLO)$/basegfx2d.obj \
++ $(SLO)$/basegfx3d.obj \
$(SLO)$/boxclipper.obj \
++ $(SLO)$/clipstate.obj \
+ $(SLO)$/genericclipper.obj \
$(SLO)$/testtools.obj
diff --git a/patches/test/wmf-clipperf.diff b/patches/test/wmf-clipperf.diff
new file mode 100644
index 0000000..71e3cce
--- /dev/null
+++ b/patches/test/wmf-clipperf.diff
@@ -0,0 +1,439 @@
+Use the new B2DClipState to improve wmf clip performance
+
+From: Thorsten Behrens <thb at openoffice.org>
+
+
+---
+
+ svtools/source/filter.vcl/wmf/winmtf.cxx | 178 ++++++++++++------------------
+ svtools/source/filter.vcl/wmf/winmtf.hxx | 54 +++++----
+ svtools/util/makefile.mk | 1
+ 3 files changed, 97 insertions(+), 136 deletions(-)
+
+
+diff --git svtools/source/filter.vcl/wmf/winmtf.cxx svtools/source/filter.vcl/wmf/winmtf.cxx
+index 666b0a0..026d024 100644
+--- svtools/source/filter.vcl/wmf/winmtf.cxx
++++ svtools/source/filter.vcl/wmf/winmtf.cxx
+@@ -33,8 +33,11 @@
+
+
+ #include "winmtf.hxx"
++#include <basegfx/matrix/b2dhommatrix.hxx>
++#include <basegfx/polygon/b2dpolypolygontools.hxx>
+ #include <vcl/metaact.hxx>
+ #include <vcl/graphictools.hxx>
++#include <vcl/canvastools.hxx>
+ #include <vcl/metric.hxx>
+ #include <rtl/tencinfo.h>
+
+@@ -45,99 +48,56 @@
+
+ #define WIN_MTF_MAX_POLYPOLYCOUNT 16
+
+-void WinMtfClipPath::ImpUpdateType()
++void WinMtfClipPath::intersectClipRect( const Rectangle& rRect )
+ {
+- if ( !aPolyPoly.Count() )
+- eType = EMPTY;
+- else if ( aPolyPoly.IsRect() )
+- eType = RECTANGLE;
+- else
+- eType = COMPLEX;
+-
+- bNeedsUpdate = sal_True;
+-}
+-
+-void WinMtfClipPath::IntersectClipRect( const Rectangle& rRect )
+-{
+- if ( !aPolyPoly.Count() )
+- aPolyPoly = Polygon( rRect );
+- else if ( aPolyPoly.Count() < WIN_MTF_MAX_POLYPOLYCOUNT )
+- {
+- Polygon aPolygon( rRect );
+- PolyPolygon aIntersection;
+- PolyPolygon aPolyPolyRect( aPolygon );
+- aPolyPoly.GetIntersection( aPolyPolyRect, aIntersection );
+- aPolyPoly = aIntersection;
+- }
+- ImpUpdateType();
++ maClip.intersectRange(
++ vcl::unotools::b2DRectangleFromRectangle(rRect));
+ }
+
+-void WinMtfClipPath::ExcludeClipRect( const Rectangle& rRect )
++void WinMtfClipPath::excludeClipRect( const Rectangle& rRect )
+ {
+- if ( aPolyPoly.Count() && ( aPolyPoly.Count() < WIN_MTF_MAX_POLYPOLYCOUNT ) )
+- {
+- Polygon aPolygon( rRect );
+- PolyPolygon aPolyPolyRect( aPolygon );
+- PolyPolygon aDifference;
+- aPolyPoly.GetDifference( aPolyPolyRect, aDifference );
+- aPolyPoly = aDifference;
+- }
+- ImpUpdateType();
++ maClip.subtractRange(
++ vcl::unotools::b2DRectangleFromRectangle(rRect));
+ }
+
+-void WinMtfClipPath::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
++void WinMtfClipPath::setClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
+ {
+- if ( !rPolyPolygon.Count() )
+- aPolyPoly = rPolyPolygon;
+- else if ( rPolyPolygon.Count() < WIN_MTF_MAX_POLYPOLYCOUNT )
++ const basegfx::B2DPolyPolygon& rB2DPoly=rPolyPolygon.getB2DPolyPolygon();
++ switch ( nClippingMode )
+ {
+- PolyPolygon aNewClipPath;
+-
+- // #115345# Watch out for empty aPolyPoly here - conceptually,
+- // an empty clip path is a rectangle of infinite size, but it
+- // is represented by an empty aPolyPoly. When intersecting
+- // rPolyPolygon with this _empty_ aPolyPoly, set algebra
+- // guarantees wrong results.
+- switch ( nClippingMode )
+- {
+- case RGN_OR :
+- // #115345# clip stays empty, when ORing an arbitrary
+- // rPolyPolygon. Thus, we can save us the unnecessary
+- // clipper call.
+- if( aPolyPoly.Count() )
+- aPolyPoly.GetUnion( rPolyPolygon, aNewClipPath );
++ case RGN_OR :
++ maClip.unionPolyPolygon(rB2DPoly);
+ break;
+- case RGN_XOR :
+- // TODO:
+- // #115345# Cannot handle this case, for the time being
+- aPolyPoly.GetXOR( rPolyPolygon, aNewClipPath );
++ case RGN_XOR :
++ maClip.xorPolyPolygon(rB2DPoly);
+ break;
+- case RGN_DIFF :
+- // TODO:
+- // #115345# Cannot handle this case, for the time being
+- aPolyPoly.GetDifference( rPolyPolygon, aNewClipPath );
++ case RGN_DIFF :
++ maClip.subtractPolyPolygon(rB2DPoly);
+ break;
+- case RGN_AND :
+- // #115345# Clip becomes rPolyPolygon, when ANDing
+- // with an arbitrary rPolyPolygon
+- if( aPolyPoly.Count() )
+- aPolyPoly.GetIntersection( rPolyPolygon, aNewClipPath );
+- else
+- aNewClipPath = rPolyPolygon;
++ case RGN_AND :
++ maClip.intersectPolyPolygon(rB2DPoly);
+ break;
+- case RGN_COPY :
+- aNewClipPath = rPolyPolygon;
++ case RGN_COPY :
++ maClip = basegfx::tools::B2DClipState(rB2DPoly);
+ break;
+- }
+- aPolyPoly = aNewClipPath;
+ }
+- ImpUpdateType();
+ }
+
+-void WinMtfClipPath::MoveClipRegion( const Size& rSize )
++void WinMtfClipPath::moveClipRegion( const Size& rSize )
++{
++ // what a weird concept. emulate, don't want this in B2DClipState
++ // API
++ basegfx::B2DPolyPolygon aCurrClip=maClip.getClipPoly();
++ basegfx::B2DHomMatrix aTranslate;
++ aTranslate.translate(rSize.Width(), rSize.Height());
++
++ aCurrClip.transform(aTranslate);
++ maClip = basegfx::tools::B2DClipState( aCurrClip );
++}
++
++basegfx::B2DPolyPolygon WinMtfClipPath::getClipPath() const
+ {
+- aPolyPoly.Move( rSize.Width(), rSize.Height() );
+- bNeedsUpdate = sal_True;
++ return maClip.getClipPoly();
+ }
+
+ // ------------------------------------------------------------------------
+@@ -882,31 +842,35 @@ void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
+
+ void WinMtfOutput::IntersectClipRect( const Rectangle& rRect )
+ {
+- aClipPath.IntersectClipRect( ImplMap( rRect ) );
++ mbClipNeedsUpdate=true;
++ aClipPath.intersectClipRect( ImplMap( rRect ) );
+ }
+
+ //-----------------------------------------------------------------------------------
+
+ void WinMtfOutput::ExcludeClipRect( const Rectangle& rRect )
+ {
+- aClipPath.ExcludeClipRect( ImplMap( rRect ) );
++ mbClipNeedsUpdate=true;
++ aClipPath.excludeClipRect( ImplMap( rRect ) );
+ }
+
+ //-----------------------------------------------------------------------------------
+
+ void WinMtfOutput::MoveClipRegion( const Size& rSize )
+ {
+- aClipPath.MoveClipRegion( ImplMap( rSize ) );
++ mbClipNeedsUpdate=true;
++ aClipPath.moveClipRegion( ImplMap( rSize ) );
+ }
+
+ void WinMtfOutput::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, sal_Bool bIsMapped )
+ {
++ mbClipNeedsUpdate=true;
+ if ( bIsMapped )
+- aClipPath.SetClipPath( rPolyPolygon, nClippingMode );
++ aClipPath.setClipPath( rPolyPolygon, nClippingMode );
+ else
+ {
+ PolyPolygon aPP( rPolyPolygon );
+- aClipPath.SetClipPath( ImplMap( aPP ), nClippingMode );
++ aClipPath.setClipPath( ImplMap( aPP ), nClippingMode );
+ }
+ }
+
+@@ -928,6 +892,8 @@ WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
+ maActPos ( Point() ),
+ mbNopMode ( sal_False ),
+ mbFillStyleSelected ( sal_False ),
++ mbClipNeedsUpdate ( true ),
++ mbComplexClip ( false ),
+ mnGfxMode ( GM_COMPATIBLE ),
+ mnMapMode ( MM_TEXT ),
+ mnDevOrgX ( 0 ),
+@@ -979,31 +945,25 @@ WinMtfOutput::~WinMtfOutput()
+
+ void WinMtfOutput::UpdateClipRegion()
+ {
+- if ( aClipPath.bNeedsUpdate )
++ if ( mbClipNeedsUpdate )
+ {
+- aClipPath.bNeedsUpdate = sal_False;
++ mbClipNeedsUpdate = false;
++ mbComplexClip = false;
+
+ mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the orignal clipregion
+ mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); //
+
+- switch ( aClipPath.GetType() )
++ // skip for 'no clipping at all' case
++ if( !aClipPath.isEmpty() )
+ {
+- case RECTANGLE :
+- case COMPLEX :
+- {
+-// we will not generate a RegionClipRegion Action, because this action
+-// cannot be saved to the wmf format - saving to wmf always happens
+-// if the placeholder graphic for ole objects is generated. (SJ)
+-
+-// Region aClipRegion( aClipPath.GetClipPath() );
+-// mpGDIMetaFile->AddAction( new MetaISectRegionClipRegionAction( aClipRegion ) );
+-
+- Rectangle aClipRect( aClipPath.GetClipPath().GetBoundRect() );
+- mpGDIMetaFile->AddAction( new MetaISectRectClipRegionAction( aClipRect ) );
+- }
+- break;
+- case EMPTY:
+- break; // -Wall not handled.
++ const basegfx::B2DPolyPolygon& rClipPoly( aClipPath.getClipPath() );
++ mpGDIMetaFile->AddAction(
++ new MetaISectRectClipRegionAction(
++ vcl::unotools::rectangleFromB2DRectangle(
++ rClipPoly.getB2DRange())));
++
++ mbComplexClip = rClipPoly.count() > 1
++ || !basegfx::tools::isRectangle(rClipPoly);
+ }
+ }
+ }
+@@ -1182,12 +1142,12 @@ void WinMtfOutput::DrawRect( const Rectangle& rRect, BOOL bEdge )
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+- if ( aClipPath.GetType() == COMPLEX )
++ if ( mbComplexClip )
+ {
+ Polygon aPoly( ImplMap( rRect ) );
+ PolyPolygon aPolyPolyRect( aPoly );
+ PolyPolygon aDest;
+- aClipPath.GetClipPath().GetIntersection( aPolyPolyRect, aDest );
++ PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPolyRect, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+@@ -1342,11 +1302,11 @@ void WinMtfOutput::DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath )
+ {
+ UpdateFillStyle();
+
+- if ( aClipPath.GetType() == COMPLEX )
++ if ( mbComplexClip )
+ {
+ PolyPolygon aPolyPoly( rPolygon );
+ PolyPolygon aDest;
+- aClipPath.GetClipPath().GetIntersection( aPolyPoly, aDest );
++ PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPoly, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+@@ -1418,10 +1378,10 @@ void WinMtfOutput::DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordP
+ {
+ UpdateFillStyle();
+
+- if ( aClipPath.GetType() == COMPLEX )
++ if ( mbComplexClip )
+ {
+ PolyPolygon aDest;
+- aClipPath.GetClipPath().GetIntersection( rPolyPolygon, aDest );
++ PolyPolygon(aClipPath.getClipPath()).GetIntersection( rPolyPolygon, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+@@ -1656,7 +1616,7 @@ void WinMtfOutput::DrawText( Point& rPosition, String& rText, sal_Int32* pDXArry
+ void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap )
+ {
+ BitmapEx aBmpEx( rBitmap );
+- if ( aClipPath.GetType() == COMPLEX )
++ if ( mbComplexClip )
+ {
+ VirtualDevice aVDev;
+ MapMode aMapMode( MAP_100TH_MM );
+@@ -1671,7 +1631,7 @@ void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const B
+ aVDev.SetMapMode( aMapMode );
+ aVDev.SetOutputSizePixel( aSizePixel );
+ aVDev.SetFillColor( Color( COL_BLACK ) );
+- const PolyPolygon aClip( aClipPath.GetClipPath() );
++ const PolyPolygon aClip( aClipPath.getClipPath() );
+ aVDev.DrawPolyPolygon( aClip );
+ const Point aEmptyPoint;
+
+@@ -2220,7 +2180,7 @@ void WinMtfOutput::Pop()
+ if ( ! ( aClipPath == pSave->aClipPath ) )
+ {
+ aClipPath = pSave->aClipPath;
+- aClipPath.bNeedsUpdate = sal_True;
++ mbClipNeedsUpdate = true;
+ }
+ if ( meLatestRasterOp != meRasterOp )
+ mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
+diff --git svtools/source/filter.vcl/wmf/winmtf.hxx svtools/source/filter.vcl/wmf/winmtf.hxx
+index 19e2a06..9286953 100644
+--- svtools/source/filter.vcl/wmf/winmtf.hxx
++++ svtools/source/filter.vcl/wmf/winmtf.hxx
+@@ -48,6 +48,7 @@
+ #include <vcl/graph.hxx>
+ #include <vcl/virdev.hxx>
+ #include <tools/poly.hxx>
++#include <basegfx/tools/b2dclipstate.hxx>
+ #include <vcl/font.hxx>
+ #include <vcl/bmpacc.hxx>
+ #include <vcl/lineinfo.hxx>
+@@ -311,34 +312,26 @@ struct LOGFONTW
+ void WinMtfAssertHandler( const sal_Char*, sal_uInt32 nFlags = WIN_MTF_ASSERT_MIFE );
+ #endif
+
+-enum WinMtfClipPathType{ EMPTY, RECTANGLE, COMPLEX };
+-
+ class WinMtfClipPath
+ {
+- PolyPolygon aPolyPoly;
+- WinMtfClipPathType eType;
+-
+- void ImpUpdateType();
+-
+- public :
+-
+- sal_Bool bNeedsUpdate;
+-
+- WinMtfClipPath(): eType(EMPTY), bNeedsUpdate( sal_False ){};
++ basegfx::tools::B2DClipState maClip;
+
+- void SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode );
+- void IntersectClipRect( const Rectangle& rRect );
+- void ExcludeClipRect( const Rectangle& rRect );
+- void MoveClipRegion( const Size& rSize );
++public :
++ WinMtfClipPath(): maClip() {};
+
+- WinMtfClipPathType GetType() const { return eType; };
+- const PolyPolygon& GetClipPath() const { return aPolyPoly; };
++ void setClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode );
++ void intersectClipRect( const Rectangle& rRect );
++ void excludeClipRect( const Rectangle& rRect );
++ void moveClipRegion( const Size& rSize );
+
+- sal_Bool operator==( const WinMtfClipPath& rPath )
+- {
+- return ( rPath.eType == eType ) &&
+- ( rPath.aPolyPoly == aPolyPoly );
+- };
++ bool isEmpty() const { return maClip.isCleared(); }
++
++ basegfx::B2DPolyPolygon getClipPath() const;
++
++ bool operator==( const WinMtfClipPath& rPath ) const
++ {
++ return maClip == rPath.maClip;
++ };
+ };
+
+ class WinMtfPathObj : public PolyPolygon
+@@ -380,20 +373,25 @@ struct WinMtfFillStyle
+
+ WinMtfFillStyle() :
+ aFillColor ( Color( COL_BLACK ) ),
+- bTransparent( FALSE )
++ bTransparent( FALSE ),
++ aType(),
++ aBmp()
+ {
+ };
+
+ WinMtfFillStyle( const Color& rColor, BOOL bTrans = FALSE ) :
+ aFillColor ( rColor ),
+ bTransparent( bTrans ),
+- aType ( FillStyleSolid )
++ aType ( FillStyleSolid ),
++ aBmp()
+ {
+ };
+
+ WinMtfFillStyle( Bitmap& rBmp ) :
+- aBmp ( rBmp ),
+- aType( FillStylePattern )
++ aFillColor (),
++ bTransparent( FALSE ),
++ aType( FillStylePattern ),
++ aBmp ( rBmp )
+ {
+ };
+
+@@ -584,6 +582,8 @@ class WinMtfOutput
+ sal_uInt32 mnRop;
+ sal_Bool mbNopMode;
+ sal_Bool mbFillStyleSelected;
++ sal_Bool mbClipNeedsUpdate;
++ sal_Bool mbComplexClip;
+
+ std::vector< SaveStructPtr > vSaveStack;
+
+diff --git svtools/util/makefile.mk svtools/util/makefile.mk
+index d401956..2f869a2 100644
+--- svtools/util/makefile.mk
++++ svtools/util/makefile.mk
+@@ -139,6 +139,7 @@ SHL1STDLIBS+= \
+ $(VCLLIB) \
+ $(SVLLIB) \
+ $(SOTLIB) \
++ $(BASEGFXLIB) \
+ $(UNOTOOLSLIB) \
+ $(TOOLSLIB) \
+ $(I18NISOLANGLIB) \
More information about the ooo-build-commit
mailing list